Stop using legacy NODE_TYPE_CASTS() macro in svg/
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Sep 2014 17:25:43 +0000 (17:25 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Sep 2014 17:25:43 +0000 (17:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137106

Reviewed by Ryosuke Niwa.

Stop using legacy NODE_TYPE_CASTS() in svg/ and use the new
SPECIALIZE_TYPE_TRAITS_*() macro instead so that is<>() / downcast<>()
can be used for those types.

No new tests, no behavior change.

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::propertyValue):
* dom/Element.h:
* dom/Node.h:
(WebCore::is):
* dom/make_names.pl:
(printTypeHelpers):
* html/HTMLElement.h:
* html/HTMLMediaElement.h:
* html/HTMLPlugInImageElement.h:
* html/LabelableElement.h:
* mathml/MathMLElement.h:
Rename NodeTypeCastTraits::is() to NodeTypeCastTraits::isType() to
avoid naming conflict with the global is<>() function. This was an
issue when is<>() was called from one of the template specializations.

* rendering/svg/RenderSVGBlock.h:
(WebCore::RenderSVGBlock::graphicsElement):
* rendering/svg/RenderSVGGradientStop.cpp:
(WebCore::RenderSVGGradientStop::gradientElement):
* rendering/svg/RenderSVGInline.h:
(WebCore::RenderSVGInline::graphicsElement):
* rendering/svg/RenderSVGResourceClipper.cpp:
(WebCore::RenderSVGResourceClipper::pathOnlyClipping):
* rendering/svg/RenderSVGResourceContainer.cpp:
(WebCore::RenderSVGResourceContainer::transformOnNonScalingStroke):
* rendering/svg/RenderSVGShape.h:
(WebCore::RenderSVGShape::graphicsElement):
* rendering/svg/RenderSVGTransformableContainer.h:
* rendering/svg/SVGRenderSupport.cpp:
(WebCore::SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending):
* rendering/svg/SVGRenderTreeAsText.cpp:
(WebCore::operator<<):
* rendering/svg/SVGRenderingContext.cpp:
(WebCore::SVGRenderingContext::prepareToRenderSVGContent):
* rendering/svg/SVGResources.cpp:
(WebCore::targetReferenceFromResource):
* svg/SVGAElement.cpp:
(WebCore::SVGAElement::defaultEventHandler):
* svg/SVGAnimateElement.cpp:
(WebCore::SVGAnimateElement::calculateAnimatedValue):
(WebCore::isSVGAnimateElement): Deleted.
Use is<>() / downcast<>() where appropriate.

* svg/SVGAnimateElement.h:
(WebCore::isSVGAnimateElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
overload for isSVGAnimateElement() taking an SVGElement in argument to
bypass the is<SVGElement>() check when the input type is an SVGElement.

* svg/SVGAnimationElement.cpp:
(WebCore::SVGAnimationElement::currentValuesForValuesAnimation):
* svg/SVGElement.cpp:
(WebCore::SVGElement::getBoundingBox):
Use is<>() / downcast<>() where appropriate.

* svg/SVGElement.h:
* svg/SVGFilterPrimitiveStandardAttributes.h:
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and drop
the pre-existing NodeTypeCastTraits template specialization as it is
now generated by the macro.

* svg/SVGGradientElement.cpp:
(WebCore::isSVGGradientElement): Deleted.
* svg/SVGGradientElement.h:
(WebCore::isSVGGradientElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
overload for isSVGAnimateElement() taking an SVGElement in argument to
bypass the is<SVGElement>() check when the input type is an SVGElement.

* svg/SVGGraphicsElement.h:
(WebCore::isSVGGraphicsElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS().

* svg/SVGLinearGradientElement.cpp:
(WebCore::SVGLinearGradientElement::collectGradientAttributes):
* svg/SVGLocatable.cpp:
(WebCore::SVGLocatable::getTransformToElement):
* svg/SVGPolyElement.cpp:
(WebCore::SVGPolyElement::synchronizePoints):
(WebCore::SVGPolyElement::lookupOrCreatePointsWrapper):
(WebCore::isSVGPolyElement): Deleted.
Use is<>() / downcast<>() where appropriate.

* svg/SVGPolyElement.h:
(WebCore::isSVGPolyElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
overload for isPolyElement() taking an SVGElement in argument to
bypass the is<SVGElement>() check when the input type is an SVGElement.

* svg/SVGRadialGradientElement.cpp:
(WebCore::SVGRadialGradientElement::collectGradientAttributes):
* svg/SVGTextContentElement.cpp:
(WebCore::SVGTextContentElement::synchronizeTextLength):
(WebCore::SVGTextContentElement::lookupOrCreateTextLengthWrapper):
(WebCore::SVGTextContentElement::elementFromRenderer):
Use is<>() / downcast<>() where appropriate.

* svg/SVGTextContentElement.h:
WebCore::isSVGTextContentElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS().

* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::toClipPath):
Use is<>() / downcast<>() where appropriate. Also use tighter typing
for value returned by shadowTreeElement().

* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::buildPendingResource):
(WebCore::SVGSMILElement::connectConditions):
(WebCore::SVGSMILElement::disconnectConditions):
Use is<>() / downcast<>() where appropriate.

* svg/animation/SVGSMILElement.h:
(WebCore::isSVGSMILElement):
Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and drop
the pre-existing NodeTypeCastTraits template specialization as it is
now generated by the macro.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173970 268f45cc-cd09-0410-ab3c-d52691b4dbfc

41 files changed:
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/Node.h
Source/WebCore/dom/make_names.pl
Source/WebCore/html/HTMLElement.h
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/HTMLPlugInImageElement.h
Source/WebCore/html/LabelableElement.h
Source/WebCore/mathml/MathMLElement.h
Source/WebCore/rendering/svg/RenderSVGBlock.h
Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp
Source/WebCore/rendering/svg/RenderSVGInline.h
Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
Source/WebCore/rendering/svg/RenderSVGShape.h
Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h
Source/WebCore/rendering/svg/SVGRenderSupport.cpp
Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
Source/WebCore/rendering/svg/SVGRenderingContext.cpp
Source/WebCore/rendering/svg/SVGResources.cpp
Source/WebCore/svg/SVGAElement.cpp
Source/WebCore/svg/SVGAnimateElement.cpp
Source/WebCore/svg/SVGAnimateElement.h
Source/WebCore/svg/SVGAnimationElement.cpp
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h
Source/WebCore/svg/SVGGradientElement.cpp
Source/WebCore/svg/SVGGradientElement.h
Source/WebCore/svg/SVGGraphicsElement.h
Source/WebCore/svg/SVGLinearGradientElement.cpp
Source/WebCore/svg/SVGLocatable.cpp
Source/WebCore/svg/SVGPolyElement.cpp
Source/WebCore/svg/SVGPolyElement.h
Source/WebCore/svg/SVGRadialGradientElement.cpp
Source/WebCore/svg/SVGTextContentElement.cpp
Source/WebCore/svg/SVGTextContentElement.h
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/animation/SVGSMILElement.cpp
Source/WebCore/svg/animation/SVGSMILElement.h

index fcd14d8..4f3fd9d 100644 (file)
@@ -1,3 +1,135 @@
+2014-09-25  Christophe Dumez  <cdumez@apple.com>
+
+        Stop using legacy NODE_TYPE_CASTS() macro in svg/
+        https://bugs.webkit.org/show_bug.cgi?id=137106
+
+        Reviewed by Ryosuke Niwa.
+
+        Stop using legacy NODE_TYPE_CASTS() in svg/ and use the new
+        SPECIALIZE_TYPE_TRAITS_*() macro instead so that is<>() / downcast<>()
+        can be used for those types.
+
+        No new tests, no behavior change.
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::propertyValue):
+        * dom/Element.h:
+        * dom/Node.h:
+        (WebCore::is):
+        * dom/make_names.pl:
+        (printTypeHelpers):
+        * html/HTMLElement.h:
+        * html/HTMLMediaElement.h:
+        * html/HTMLPlugInImageElement.h:
+        * html/LabelableElement.h:
+        * mathml/MathMLElement.h:
+        Rename NodeTypeCastTraits::is() to NodeTypeCastTraits::isType() to
+        avoid naming conflict with the global is<>() function. This was an
+        issue when is<>() was called from one of the template specializations.
+
+        * rendering/svg/RenderSVGBlock.h:
+        (WebCore::RenderSVGBlock::graphicsElement):
+        * rendering/svg/RenderSVGGradientStop.cpp:
+        (WebCore::RenderSVGGradientStop::gradientElement):
+        * rendering/svg/RenderSVGInline.h:
+        (WebCore::RenderSVGInline::graphicsElement):
+        * rendering/svg/RenderSVGResourceClipper.cpp:
+        (WebCore::RenderSVGResourceClipper::pathOnlyClipping):
+        * rendering/svg/RenderSVGResourceContainer.cpp:
+        (WebCore::RenderSVGResourceContainer::transformOnNonScalingStroke):
+        * rendering/svg/RenderSVGShape.h:
+        (WebCore::RenderSVGShape::graphicsElement):
+        * rendering/svg/RenderSVGTransformableContainer.h:
+        * rendering/svg/SVGRenderSupport.cpp:
+        (WebCore::SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending):
+        * rendering/svg/SVGRenderTreeAsText.cpp:
+        (WebCore::operator<<):
+        * rendering/svg/SVGRenderingContext.cpp:
+        (WebCore::SVGRenderingContext::prepareToRenderSVGContent):
+        * rendering/svg/SVGResources.cpp:
+        (WebCore::targetReferenceFromResource):
+        * svg/SVGAElement.cpp:
+        (WebCore::SVGAElement::defaultEventHandler):
+        * svg/SVGAnimateElement.cpp:
+        (WebCore::SVGAnimateElement::calculateAnimatedValue):
+        (WebCore::isSVGAnimateElement): Deleted.
+        Use is<>() / downcast<>() where appropriate.
+
+        * svg/SVGAnimateElement.h:
+        (WebCore::isSVGAnimateElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
+        overload for isSVGAnimateElement() taking an SVGElement in argument to
+        bypass the is<SVGElement>() check when the input type is an SVGElement.
+
+        * svg/SVGAnimationElement.cpp:
+        (WebCore::SVGAnimationElement::currentValuesForValuesAnimation):
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::getBoundingBox):
+        Use is<>() / downcast<>() where appropriate.
+
+        * svg/SVGElement.h:
+        * svg/SVGFilterPrimitiveStandardAttributes.h:
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and drop
+        the pre-existing NodeTypeCastTraits template specialization as it is
+        now generated by the macro.
+
+        * svg/SVGGradientElement.cpp:
+        (WebCore::isSVGGradientElement): Deleted.
+        * svg/SVGGradientElement.h:
+        (WebCore::isSVGGradientElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
+        overload for isSVGAnimateElement() taking an SVGElement in argument to
+        bypass the is<SVGElement>() check when the input type is an SVGElement.
+
+        * svg/SVGGraphicsElement.h:
+        (WebCore::isSVGGraphicsElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS().
+
+        * svg/SVGLinearGradientElement.cpp:
+        (WebCore::SVGLinearGradientElement::collectGradientAttributes):
+        * svg/SVGLocatable.cpp:
+        (WebCore::SVGLocatable::getTransformToElement):
+        * svg/SVGPolyElement.cpp:
+        (WebCore::SVGPolyElement::synchronizePoints):
+        (WebCore::SVGPolyElement::lookupOrCreatePointsWrapper):
+        (WebCore::isSVGPolyElement): Deleted.
+        Use is<>() / downcast<>() where appropriate.
+
+        * svg/SVGPolyElement.h:
+        (WebCore::isSVGPolyElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and add
+        overload for isPolyElement() taking an SVGElement in argument to
+        bypass the is<SVGElement>() check when the input type is an SVGElement.
+
+        * svg/SVGRadialGradientElement.cpp:
+        (WebCore::SVGRadialGradientElement::collectGradientAttributes):
+        * svg/SVGTextContentElement.cpp:
+        (WebCore::SVGTextContentElement::synchronizeTextLength):
+        (WebCore::SVGTextContentElement::lookupOrCreateTextLengthWrapper):
+        (WebCore::SVGTextContentElement::elementFromRenderer):
+        Use is<>() / downcast<>() where appropriate.
+
+        * svg/SVGTextContentElement.h:
+        WebCore::isSVGTextContentElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS().
+
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::toClipPath):
+        Use is<>() / downcast<>() where appropriate. Also use tighter typing
+        for value returned by shadowTreeElement().
+
+        * svg/animation/SVGSMILElement.cpp:
+        (WebCore::SVGSMILElement::buildPendingResource):
+        (WebCore::SVGSMILElement::connectConditions):
+        (WebCore::SVGSMILElement::disconnectConditions):
+        Use is<>() / downcast<>() where appropriate.
+
+        * svg/animation/SVGSMILElement.h:
+        (WebCore::isSVGSMILElement):
+        Use SPECIALIZE_TYPE_TRAITS_*() instead of NODE_TYPE_CASTS() and drop
+        the pre-existing NodeTypeCastTraits template specialization as it is
+        now generated by the macro.
+
 2014-09-25  Brent Fulgham  <bfulgham@apple.com>
 
         Minor refactoring to mediaType/presentationType
index b2f1041..82b65ba 100644 (file)
@@ -1712,7 +1712,7 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
 
         renderer = styledNode->renderer();
 
-        if (propertyID == CSSPropertyDisplay && !renderer && isSVGElement(*styledNode) && !downcast<SVGElement>(*styledNode).isValid())
+        if (propertyID == CSSPropertyDisplay && !renderer && is<SVGElement>(*styledNode) && !downcast<SVGElement>(*styledNode).isValid())
             return nullptr;
 
         style = computeRenderStyleForProperty(styledNode, m_pseudoElementSpecifier, propertyID);
index 2892bdf..5239355 100644 (file)
@@ -672,7 +672,7 @@ NODE_TYPE_CASTS(Element)
 
 template <>
 struct NodeTypeCastTraits<const Element, const Node> {
-    static bool is(const Node& node) { return node.isElementNode(); }
+    static bool isType(const Node& node) { return node.isElementNode(); }
 };
 
 inline bool Node::hasAttributes() const
index c881725..7c8a9a6 100644 (file)
@@ -741,12 +741,12 @@ inline ContainerNode* Node::parentNodeGuaranteedHostFree() const
 
 template <typename ExpectedType, typename ArgType>
 struct NodeTypeCastTraits {
-    static bool is(ArgType&);
+    static bool isType(ArgType&);
 };
 
 template <typename ExpectedType>
 struct NodeTypeCastTraits<ExpectedType, ExpectedType> {
-    static bool is(ExpectedType&) { return true; }
+    static bool isType(ExpectedType&) { return true; }
 };
 
 // Type checking function for Nodes, to use before casting with downcast<>().
@@ -754,7 +754,7 @@ template <typename ExpectedType, typename ArgType>
 inline bool is(ArgType& node)
 {
     static_assert(!std::is_base_of<ExpectedType, ArgType>::value, "Unnecessary type check");
-    return NodeTypeCastTraits<const ExpectedType, const ArgType>::is(node);
+    return NodeTypeCastTraits<const ExpectedType, const ArgType>::isType(node);
 }
 
 template <typename ExpectedType, typename ArgType>
@@ -762,7 +762,7 @@ inline bool is(ArgType* node)
 {
     ASSERT(node);
     static_assert(!std::is_base_of<ExpectedType, ArgType>::value, "Unnecessary type check");
-    return NodeTypeCastTraits<const ExpectedType, const ArgType>::is(*node);
+    return NodeTypeCastTraits<const ExpectedType, const ArgType>::isType(*node);
 }
 
 // Downcasting functions for Node types.
@@ -785,7 +785,7 @@ template<typename Target, typename Source> inline typename std::conditional<std:
     template <typename ArgType> \
     class NodeTypeCastTraits<const ClassName, ArgType> { \
     public: \
-        static bool is(ArgType& node) { return is##ClassName(node); } \
+        static bool isType(ArgType& node) { return is##ClassName(node); } \
     private:
 
 #define SPECIALIZE_TYPE_TRAITS_END() \
index ae9dc3b..7957ea4 100755 (executable)
@@ -638,7 +638,7 @@ class $class;
 template <typename ArgType>
 class NodeTypeCastTraits<const $class, ArgType> {
 public:
-    static bool is(ArgType& node) { return checkTagName(node); }
+    static bool isType(ArgType& node) { return checkTagName(node); }
 private:
 END
        ;
index 6f823a0..87f2fdb 100644 (file)
@@ -151,7 +151,7 @@ inline bool isHTMLElement(const Node& node) { return node.isHTMLElement(); }
 
 template <typename ArgType>
 struct NodeTypeCastTraits<const HTMLElement, ArgType> {
-    static bool is(ArgType& node) { return isHTMLElement(node); }
+    static bool isType(ArgType& node) { return isHTMLElement(node); }
 };
 
 NODE_TYPE_CASTS(HTMLElement)
index 29b7003..28b9256 100644 (file)
@@ -916,7 +916,7 @@ inline bool isHTMLMediaElement(const Node& node) { return node.isElementNode() &
 
 template <typename ArgType>
 struct NodeTypeCastTraits<const HTMLMediaElement, ArgType> {
-    static bool is(ArgType& node) { return isHTMLMediaElement(node); }
+    static bool isType(ArgType& node) { return isHTMLMediaElement(node); }
 };
 
 NODE_TYPE_CASTS(HTMLMediaElement)
index d3004fe..a9eee84 100644 (file)
@@ -163,7 +163,7 @@ inline bool isHTMLPlugInImageElement(const Node& node) { return node.isPluginEle
 
 template <typename ArgType>
 struct NodeTypeCastTraits<const HTMLPlugInImageElement, ArgType> {
-    static bool is(ArgType& node) { return isHTMLPlugInImageElement(node); }
+    static bool isType(ArgType& node) { return isHTMLPlugInImageElement(node); }
 };
 
 NODE_TYPE_CASTS(HTMLPlugInImageElement)
index 4895672..3ce6d04 100644 (file)
@@ -56,7 +56,7 @@ inline bool isLabelableElement(const Node& node) { return node.isHTMLElement() &
 
 template <typename ArgType>
 struct NodeTypeCastTraits<const LabelableElement, ArgType> {
-    static bool is(ArgType& node) { return isLabelableElement(node); }
+    static bool isType(ArgType& node) { return isLabelableElement(node); }
 };
 
 NODE_TYPE_CASTS(LabelableElement)
index 6d05dbf..67cab7b 100644 (file)
@@ -78,7 +78,7 @@ inline bool isMathMLElement(const Node& node) { return node.isMathMLElement(); }
 
 template <typename ArgType>
 struct NodeTypeCastTraits<const MathMLElement, ArgType> {
-    static bool is(ArgType& node) { return isMathMLElement(node); }
+    static bool isType(ArgType& node) { return isMathMLElement(node); }
 };
 
 NODE_TYPE_CASTS(MathMLElement)
index 9d18e7f..7a4fdf8 100644 (file)
@@ -32,7 +32,7 @@ class RenderSVGBlock : public RenderBlockFlow {
 public:
     virtual LayoutRect visualOverflowRect() const override final;
 
-    SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); }
+    SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); }
 
 protected:
     RenderSVGBlock(SVGGraphicsElement&, PassRef<RenderStyle>);
index 3a192a1..e11464f 100644 (file)
@@ -67,8 +67,8 @@ void RenderSVGGradientStop::layout()
 
 SVGGradientElement* RenderSVGGradientStop::gradientElement()
 {
-    if (element().parentElement() && isSVGGradientElement(*element().parentElement()))
-        return &toSVGGradientElement(*element().parentElement());
+    if (element().parentElement() && is<SVGGradientElement>(*element().parentElement()))
+        return &downcast<SVGGradientElement>(*element().parentElement());
     return nullptr;
 }
 
index 41839df..e5da145 100644 (file)
@@ -30,7 +30,7 @@ class RenderSVGInline : public RenderInline {
 public:
     RenderSVGInline(SVGGraphicsElement&, PassRef<RenderStyle>);
 
-    SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(nodeForNonAnonymous()); }
+    SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(nodeForNonAnonymous()); }
 
 private:
     void element() const = delete;
index a039c3b..302bbf9 100644 (file)
@@ -96,7 +96,7 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const
             return false;
         if (!childNode->isSVGElement() || !downcast<SVGElement>(*childNode).isSVGGraphicsElement())
             continue;
-        SVGGraphicsElement& styled = toSVGGraphicsElement(*childNode);
+        SVGGraphicsElement& styled = downcast<SVGGraphicsElement>(*childNode);
         const RenderStyle& style = renderer->style();
         if (style.display() == NONE || style.visibility() != VISIBLE)
              continue;
index 6ae5217..36e747f 100644 (file)
@@ -211,7 +211,7 @@ AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderOb
     if (!object->isSVGShape())
         return resourceTransform;
 
-    SVGGraphicsElement* element = toSVGGraphicsElement(object->node());
+    SVGGraphicsElement* element = downcast<SVGGraphicsElement>(object->node());
     AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
     transform *= resourceTransform;
     return transform;
index 7a37752..5ef48b0 100644 (file)
@@ -49,7 +49,7 @@ public:
     RenderSVGShape(SVGGraphicsElement&, PassRef<RenderStyle>, Path*, bool);
     virtual ~RenderSVGShape();
 
-    SVGGraphicsElement& graphicsElement() const { return toSVGGraphicsElement(RenderSVGModelObject::element()); }
+    SVGGraphicsElement& graphicsElement() const { return downcast<SVGGraphicsElement>(RenderSVGModelObject::element()); }
 
     void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
     virtual void setNeedsBoundariesUpdate() override final { m_needsBoundariesUpdate = true; }
index bebe394..e1d9007 100644 (file)
@@ -30,7 +30,7 @@ class SVGGraphicsElement;
 class RenderSVGTransformableContainer final : public RenderSVGContainer {
 public:
     RenderSVGTransformableContainer(SVGGraphicsElement&, PassRef<RenderStyle>);
-    SVGGraphicsElement& graphicsElement() { return toSVGGraphicsElement(RenderSVGContainer::element()); }
+    SVGGraphicsElement& graphicsElement() { return downcast<SVGGraphicsElement>(RenderSVGContainer::element()); }
 
     virtual bool isSVGTransformableContainer() const { return true; }
     virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
index 277d2b3..f38d296 100644 (file)
@@ -464,7 +464,7 @@ void SVGRenderSupport::updateMaskedAncestorShouldIsolateBlending(const RenderEle
             continue;
 
         if (ancestor->computedStyle()->svgStyle().hasMasker())
-            toSVGGraphicsElement(*ancestor).setShouldIsolateBlending(maskedAncestorShouldIsolateBlending);
+            downcast<SVGGraphicsElement>(*ancestor).setShouldIsolateBlending(maskedAncestorShouldIsolateBlending);
 
         return;
     }
index 4386c8c..f25e349 100644 (file)
@@ -343,8 +343,8 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
         writeNameValuePair(ts, "cx", element.cx().value(lengthContext));
         writeNameValuePair(ts, "cy", element.cy().value(lengthContext));
         writeNameValuePair(ts, "r", element.r().value(lengthContext));
-    } else if (svgElement.hasTagName(SVGNames::polygonTag) || svgElement.hasTagName(SVGNames::polylineTag)) {
-        const SVGPolyElement& element = toSVGPolyElement(svgElement);
+    } else if (is<SVGPolyElement>(svgElement)) {
+        const SVGPolyElement& element = downcast<SVGPolyElement>(svgElement);
         writeNameAndQuotedValue(ts, "points", element.pointList().valueAsString());
     } else if (is<SVGPathElement>(svgElement)) {
         const SVGPathElement& element = downcast<SVGPathElement>(svgElement);
index 0e0ca2e..9f51261 100644 (file)
@@ -105,8 +105,8 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
     bool isolateMaskForBlending = false;
 
 #if ENABLE(CSS_COMPOSITING)
-    if (svgStyle.hasMasker() && downcast<SVGElement>(renderer.element())->isSVGGraphicsElement()) {
-        SVGGraphicsElement& graphicsElement = toSVGGraphicsElement(*renderer.element());
+    if (svgStyle.hasMasker() && is<SVGGraphicsElement>(downcast<SVGElement>(renderer.element()))) {
+        SVGGraphicsElement& graphicsElement = downcast<SVGGraphicsElement>(*renderer.element());
         isolateMaskForBlending = graphicsElement.shouldIsolateBlending();
     }
 #endif
index 570986e..569d2ae 100644 (file)
@@ -143,8 +143,8 @@ static inline String targetReferenceFromResource(SVGElement& element)
     String target;
     if (is<SVGPatternElement>(element))
         target = downcast<SVGPatternElement>(element).href();
-    else if (isSVGGradientElement(element))
-        target = toSVGGradientElement(element).href();
+    else if (is<SVGGradientElement>(element))
+        target = downcast<SVGGradientElement>(element).href();
     else if (is<SVGFilterElement>(element))
         target = downcast<SVGFilterElement>(element).href();
     else
index 0652abc..4ecf52b 100644 (file)
@@ -160,8 +160,8 @@ void SVGAElement::defaultEventHandler(Event* event)
 
             if (url[0] == '#') {
                 Element* targetElement = treeScope().getElementById(url.substringSharingImpl(1));
-                if (targetElement && isSVGSMILElement(*targetElement)) {
-                    toSVGSMILElement(*targetElement).beginByLinkActivation();
+                if (targetElement && is<SVGSMILElement>(*targetElement)) {
+                    downcast<SVGSMILElement>(*targetElement).beginByLinkActivation();
                     event->setDefaultHandled();
                     return;
                 }
index cd09bf3..6354968 100644 (file)
@@ -110,7 +110,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
     ASSERT(m_fromType->type() == m_animatedPropertyType);
     ASSERT(m_toType);
 
-    SVGAnimateElement& resultAnimationElement = toSVGAnimateElement(*resultElement);
+    SVGAnimateElement& resultAnimationElement = downcast<SVGAnimateElement>(*resultElement);
     ASSERT(resultAnimationElement.m_animatedType);
     ASSERT(resultAnimationElement.m_animatedPropertyType == m_animatedPropertyType);
 
@@ -459,12 +459,4 @@ SVGAnimatedTypeAnimator* SVGAnimateElement::ensureAnimator()
     return m_animator.get();
 }
 
-bool isSVGAnimateElement(const Node& node)
-{
-    return node.hasTagName(SVGNames::animateTag)
-        || node.hasTagName(SVGNames::animateColorTag)
-        || node.hasTagName(SVGNames::animateTransformTag)
-        || node.hasTagName(SVGNames::setTag);
-}
-
 }
index b86d9b2..641bff3 100644 (file)
@@ -74,9 +74,14 @@ private:
     std::unique_ptr<SVGAnimatedTypeAnimator> m_animator;
 };
 
-void isSVGAnimateElement(const SVGAnimateElement&); // Catch unnecessary runtime check of type known at compile time.
-bool isSVGAnimateElement(const Node&);
-NODE_TYPE_CASTS(SVGAnimateElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGAnimateElement)
+    static bool isSVGAnimateElement(const SVGElement& element)
+    {
+        return element.hasTagName(SVGNames::animateTag) || element.hasTagName(SVGNames::animateColorTag)
+            || element.hasTagName(SVGNames::animateTransformTag) || element.hasTagName(SVGNames::setTag);
+    }
+    static bool isSVGAnimateElement(const Node& node) { return is<SVGElement>(node) && isSVGAnimateElement(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index 54acc08..d1f3589 100644 (file)
@@ -508,7 +508,7 @@ void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float&
 
     CalcMode calcMode = this->calcMode();
     if (hasTagName(SVGNames::animateTag) || hasTagName(SVGNames::animateColorTag)) {
-        AnimatedPropertyType attributeType = toSVGAnimateElement(*this).determineAnimatedPropertyType(targetElement());
+        AnimatedPropertyType attributeType = downcast<SVGAnimateElement>(*this).determineAnimatedPropertyType(targetElement());
         // Fall back to discrete animations for Strings.
         if (attributeType == AnimatedBoolean
             || attributeType == AnimatedEnumeration
index 70655ad..b2313e6 100644 (file)
@@ -452,8 +452,8 @@ const HashSet<SVGElementInstance*>& SVGElement::instancesForElement() const
 
 bool SVGElement::getBoundingBox(FloatRect& rect, SVGLocatable::StyleUpdateStrategy styleUpdateStrategy)
 {
-    if (isSVGGraphicsElement()) {
-        rect = toSVGGraphicsElement(*this).getBBox(styleUpdateStrategy);
+    if (is<SVGGraphicsElement>(*this)) {
+        rect = downcast<SVGGraphicsElement>(*this).getBBox(styleUpdateStrategy);
         return true;
     }
     return false;
index cdda998..9a2e96c 100644 (file)
@@ -221,15 +221,9 @@ struct SVGAttributeHashTranslator {
     static bool equal(const QualifiedName& a, const QualifiedName& b) { return a.matches(b); }
 };
 
-void isSVGElement(const SVGElement&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isSVGElement(const Node& node) { return node.isSVGElement(); }
-
-template <typename ArgType>
-struct NodeTypeCastTraits<const SVGElement, ArgType> {
-    static bool is(ArgType& node) { return isSVGElement(node); }
-};
-
-NODE_TYPE_CASTS(SVGElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGElement)
+    static bool isSVGElement(const Node& node) { return node.isSVGElement(); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 inline bool Node::hasTagName(const SVGQualifiedName& name) const
 {
index 4f77895..0cb19ef 100644 (file)
@@ -82,17 +82,10 @@ private:
 
 void invalidateFilterPrimitiveParent(SVGElement*);
 
-void isSVGFilterPrimitiveStandardAttributes(const SVGFilterPrimitiveStandardAttributes&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isSVGFilterPrimitiveStandardAttributes(const SVGElement& element) { return element.isFilterEffect(); }
-inline bool isSVGFilterPrimitiveStandardAttributes(const Node& node) { return node.isSVGElement() && downcast<SVGElement>(node).isFilterEffect(); }
-
-template <typename ArgType>
-struct NodeTypeCastTraits<const SVGFilterPrimitiveStandardAttributes, ArgType> {
-    static bool is(ArgType& node) { return isSVGFilterPrimitiveStandardAttributes(node); }
-};
-
-NODE_TYPE_CASTS(SVGFilterPrimitiveStandardAttributes)
-
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGFilterPrimitiveStandardAttributes)
+    static bool isSVGFilterPrimitiveStandardAttributes(const SVGElement& element) { return element.isFilterEffect(); }
+    static bool isSVGFilterPrimitiveStandardAttributes(const Node& node) { return is<SVGElement>(node) && isSVGFilterPrimitiveStandardAttributes(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index 48c16b5..543eef3 100644 (file)
@@ -160,9 +160,4 @@ Vector<Gradient::ColorStop> SVGGradientElement::buildStops()
     return stops;
 }
 
-bool isSVGGradientElement(const Node& node)
-{
-    return node.hasTagName(SVGNames::radialGradientTag) || node.hasTagName(SVGNames::linearGradientTag);
-}
-
 }
index 0634d27..533808f 100644 (file)
@@ -107,9 +107,16 @@ private:
     END_DECLARE_ANIMATED_PROPERTIES
 };
 
-void isSVGGradientElement(const SVGGradientElement&); // Catch unnecessary runtime check of type known at compile time.
-bool isSVGGradientElement(const Node&);
-NODE_TYPE_CASTS(SVGGradientElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGGradientElement)
+static bool isSVGGradientElement(const SVGElement& element)
+{
+    return element.hasTagName(SVGNames::radialGradientTag) || element.hasTagName(SVGNames::linearGradientTag);
+}
+static bool isSVGGradientElement(const Node& node)
+{
+    return is<SVGElement>(node) && isSVGGradientElement(downcast<SVGElement>(node));
+}
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index 0642504..433f31c 100644 (file)
@@ -82,10 +82,10 @@ private:
     bool m_shouldIsolateBlending;
 };
 
-void isSVGGraphicsElement(const SVGGraphicsElement&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isSVGGraphicsElement(const SVGElement& element) { return element.isSVGGraphicsElement(); }
-inline bool isSVGGraphicsElement(const Node& node) { return node.isSVGElement() && downcast<SVGElement>(node).isSVGGraphicsElement(); }
-NODE_TYPE_CASTS(SVGGraphicsElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGGraphicsElement)
+    static bool isSVGGraphicsElement(const SVGElement& element) { return element.isSVGGraphicsElement(); }
+    static bool isSVGGraphicsElement(const Node& node) { return is<SVGElement>(node) && isSVGGraphicsElement(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index 2513456..dc4f2b2 100644 (file)
@@ -173,8 +173,8 @@ bool SVGLinearGradientElement::collectGradientAttributes(LinearGradientAttribute
     while (true) {
         // Respect xlink:href, take attributes from referenced element
         Node* refNode = SVGURIReference::targetElementFromIRIString(current->href(), document());
-        if (refNode && isSVGGradientElement(*refNode)) {
-            current = toSVGGradientElement(refNode);
+        if (refNode && is<SVGGradientElement>(*refNode)) {
+            current = downcast<SVGGradientElement>(refNode);
 
             // Cycle detection
             if (processedGradients.contains(current))
index af17111..ffc4b6c 100644 (file)
@@ -101,8 +101,8 @@ AffineTransform SVGLocatable::getTransformToElement(SVGElement* target, Exceptio
 {
     AffineTransform ctm = getCTM(styleUpdateStrategy);
 
-    if (target && target->isSVGGraphicsElement()) {
-        AffineTransform targetCTM = toSVGGraphicsElement(*target).getCTM(styleUpdateStrategy);
+    if (target && is<SVGGraphicsElement>(target)) {
+        AffineTransform targetCTM = downcast<SVGGraphicsElement>(*target).getCTM(styleUpdateStrategy);
         if (!targetCTM.isInvertible()) {
             ec = SVGException::SVG_MATRIX_NOT_INVERTABLE;
             return ctm;
index 112c20f..484df89 100644 (file)
@@ -132,7 +132,7 @@ void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName)
 void SVGPolyElement::synchronizePoints(SVGElement* contextElement)
 {
     ASSERT(contextElement);
-    SVGPolyElement& ownerType = toSVGPolyElement(*contextElement);
+    SVGPolyElement& ownerType = downcast<SVGPolyElement>(*contextElement);
     if (!ownerType.m_points.shouldSynchronize)
         return;
     ownerType.m_points.synchronize(&ownerType, pointsPropertyInfo()->attributeName, ownerType.m_points.value.valueAsString());
@@ -141,7 +141,7 @@ void SVGPolyElement::synchronizePoints(SVGElement* contextElement)
 PassRefPtr<SVGAnimatedProperty> SVGPolyElement::lookupOrCreatePointsWrapper(SVGElement* contextElement)
 {
     ASSERT(contextElement);
-    SVGPolyElement& ownerType = toSVGPolyElement(*contextElement);
+    SVGPolyElement& ownerType = downcast<SVGPolyElement>(*contextElement);
     return SVGAnimatedProperty::lookupOrCreateWrapper<SVGPolyElement, SVGAnimatedPointList, SVGPointList>
         (&ownerType, pointsPropertyInfo(), ownerType.m_points.value);
 }
@@ -158,9 +158,4 @@ SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::animatedPoints()
     return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal());
 }
 
-bool isSVGPolyElement(const Node& node)
-{
-    return node.hasTagName(SVGNames::polygonTag) || node.hasTagName(SVGNames::polylineTag);
-}
-
 }
index d52ed02..009ae66 100644 (file)
@@ -62,9 +62,10 @@ protected:
     mutable SVGSynchronizableAnimatedProperty<SVGPointList> m_points;
 };
 
-void isSVGPolyElement(const SVGPolyElement&); // Catch unnecessary runtime check of type known at compile time.
-bool isSVGPolyElement(const Node&);
-NODE_TYPE_CASTS(SVGPolyElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGPolyElement)
+    static bool isSVGPolyElement(const SVGElement& element) { return element.hasTagName(SVGNames::polygonTag) || element.hasTagName(SVGNames::polylineTag); }
+    static bool isSVGPolyElement(const Node& node) { return is<SVGElement>(node) && isSVGPolyElement(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index 55b964b..b1f596f 100644 (file)
@@ -191,8 +191,8 @@ bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttribute
     while (true) {
         // Respect xlink:href, take attributes from referenced element
         Node* refNode = SVGURIReference::targetElementFromIRIString(current->href(), document());
-        if (refNode && isSVGGradientElement(*refNode)) {
-            current = toSVGGradientElement(refNode);
+        if (refNode && is<SVGGradientElement>(*refNode)) {
+            current = downcast<SVGGradientElement>(refNode);
 
             // Cycle detection
             if (processedGradients.contains(current))
index 2c4a316..717488a 100644 (file)
@@ -75,7 +75,7 @@ SVGTextContentElement::SVGTextContentElement(const QualifiedName& tagName, Docum
 void SVGTextContentElement::synchronizeTextLength(SVGElement* contextElement)
 {
     ASSERT(contextElement);
-    SVGTextContentElement& ownerType = toSVGTextContentElement(*contextElement);
+    SVGTextContentElement& ownerType = downcast<SVGTextContentElement>(*contextElement);
     if (!ownerType.m_textLength.shouldSynchronize)
         return;
     AtomicString value(SVGPropertyTraits<SVGLength>::toString(ownerType.m_specifiedTextLength));
@@ -85,7 +85,7 @@ void SVGTextContentElement::synchronizeTextLength(SVGElement* contextElement)
 PassRefPtr<SVGAnimatedProperty> SVGTextContentElement::lookupOrCreateTextLengthWrapper(SVGElement* contextElement)
 {
     ASSERT(contextElement);
-    SVGTextContentElement& ownerType = toSVGTextContentElement(*contextElement);
+    SVGTextContentElement& ownerType = downcast<SVGTextContentElement>(*contextElement);
     return SVGAnimatedProperty::lookupOrCreateWrapper<SVGTextContentElement, SVGAnimatedLength, SVGLength>
         (&ownerType, textLengthPropertyInfo(), ownerType.m_textLength.value);
 }
@@ -296,10 +296,10 @@ SVGTextContentElement* SVGTextContentElement::elementFromRenderer(RenderObject*
     SVGElement* element = downcast<SVGElement>(renderer->node());
     ASSERT(element);
 
-    if (!element->isTextContent())
+    if (!is<SVGTextContentElement>(element))
         return nullptr;
 
-    return toSVGTextContentElement(element);
+    return downcast<SVGTextContentElement>(element);
 }
 
 }
index fe36e1d..a592abe 100644 (file)
@@ -119,10 +119,10 @@ private:
     END_DECLARE_ANIMATED_PROPERTIES
 };
 
-void isSVGTextContentElement(const SVGTextContentElement&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isSVGTextContentElement(const SVGElement& element) { return element.isTextContent(); }
-inline bool isSVGTextContentElement(const Node& node) { return node.isSVGElement() && downcast<SVGElement>(node).isTextContent(); }
-NODE_TYPE_CASTS(SVGTextContentElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGTextContentElement)
+    static bool isSVGTextContentElement(const SVGElement& element) { return element.isTextContent(); }
+    static bool isSVGTextContentElement(const Node& node) { return is<SVGElement>(node) && isSVGTextContentElement(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 } // namespace WebCore
 
index a394405..849df89 100644 (file)
@@ -543,16 +543,16 @@ void SVGUseElement::toClipPath(Path& path)
 {
     ASSERT(path.isEmpty());
 
-    Node* node = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : nullptr;
-    if (!node)
+    SVGElement* element = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : nullptr;
+    if (!element)
         return;
 
-    if (node->isSVGElement() && downcast<SVGElement>(*node).isSVGGraphicsElement()) {
-        if (!isDirectReference(downcast<SVGElement>(*node))) {
+    if (is<SVGGraphicsElement>(element)) {
+        if (!isDirectReference(*element)) {
             // Spec: Indirect references are an error (14.3.5)
             document().accessSVGExtensions().reportError("Not allowed to use indirect reference in <clip-path>");
         } else {
-            toSVGGraphicsElement(*node).toClipPath(path);
+            downcast<SVGGraphicsElement>(*element).toClipPath(path);
             // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
             SVGLengthContext lengthContext(this);
             path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
index f0a0851..1049e6b 100644 (file)
@@ -168,7 +168,7 @@ void SVGSMILElement::buildPendingResource()
         target = parentNode() && parentNode()->isElementNode() ? toElement(parentNode()) : nullptr;
     else
         target = SVGURIReference::targetElementFromIRIString(href, document(), &id);
-    SVGElement* svgTarget = target && target->isSVGElement() ? downcast<SVGElement>(target) : nullptr;
+    SVGElement* svgTarget = target && is<SVGElement>(target) ? downcast<SVGElement>(target) : nullptr;
 
     if (svgTarget && !svgTarget->inDocument())
         svgTarget = nullptr;
@@ -536,11 +536,11 @@ void SVGSMILElement::connectConditions()
             condition.m_syncbase = treeScope().getElementById(condition.m_baseID);
             if (!condition.m_syncbase)
                 continue;
-            if (!isSVGSMILElement(*condition.m_syncbase)) {
+            if (!is<SVGSMILElement>(*condition.m_syncbase)) {
                 condition.m_syncbase = nullptr;
                 continue;
             }
-            toSVGSMILElement(*condition.m_syncbase).addTimeDependent(this);
+            downcast<SVGSMILElement>(*condition.m_syncbase).addTimeDependent(this);
         }
     }
 }
@@ -568,7 +568,7 @@ void SVGSMILElement::disconnectConditions()
             condition.m_eventListener = nullptr;
         } else if (condition.m_type == Condition::Syncbase) {
             if (condition.m_syncbase)
-                toSVGSMILElement(condition.m_syncbase.get())->removeTimeDependent(this);
+                downcast<SVGSMILElement>(condition.m_syncbase.get())->removeTimeDependent(this);
         }
         condition.m_syncbase = nullptr;
     }
index 637a056..4d8c31b 100644 (file)
@@ -237,17 +237,10 @@ private:
     friend class ConditionEventListener;
 };
 
-void isSVGSMILElement(const SVGSMILElement&); // Catch unnecessary runtime check of type known at compile time.
-inline bool isSVGSMILElement(const SVGElement& element) { return element.isSMILElement(); }
-inline bool isSVGSMILElement(const Node& node) { return node.isSVGElement() && downcast<SVGElement>(node).isSMILElement(); }
-
-template <typename ArgType>
-struct NodeTypeCastTraits<const SVGSMILElement, ArgType> {
-    static bool is(ArgType& node) { return isSVGSMILElement(node); }
-};
-
-
-NODE_TYPE_CASTS(SVGSMILElement)
+SPECIALIZE_TYPE_TRAITS_BEGIN(SVGSMILElement)
+    static bool isSVGSMILElement(const SVGElement& element) { return element.isSMILElement(); }
+    static bool isSVGSMILElement(const Node& node) { return is<SVGElement>(node) && isSVGSMILElement(downcast<SVGElement>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()
 
 }