Remove the SVG tear off objects for SVGColorAnimator
authorsaid@apple.com <said@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 23:51:47 +0000 (23:51 +0000)
committersaid@apple.com <said@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 23:51:47 +0000 (23:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196025

Reviewed by Simon Fraser.

SVG attributes like "fill" and "stroke" do not have reflecting properties
in SVGElement but they are animatable by SMIL. Animating such attributes
is different from animating the SVG animated properties. These new classes
will be added to handle the first type of this kind of attribute: the Color:

-- SVGPropertyAnimatorCreator is added to SVGElement. It is responsible
   for creating SVGPropertyAnimators for the attribute which do not have
   reflecting animated properties stored by SVGElement. It will maintain
   a HashMap for the animated values for these attributes which is indexed
   by the attribute name. The animated values has to be RefCounted because
   the same attribute can be animated by multiple animators. So the values
   of this HashMap will be of type Ref<SVGProperty>, e.g.
    <circle cx="80" cy="120" r="35">
        <animate attributeName="fill" values="#080" begin="2s" />
        <animate attributeName="fill" values="#602;#004" begin="4s" dur="5s"/>
    </circle>

-- SVGPropertyAnimator is the a new type which animates an attribute with
   no reflecting animated property.

-- SVGPrimitivePropertyAnimator is a template class which is responsible
   for animating attributes with primitive types, e.g. Color, string and
   float. It is derived form SVGPropertyAnimator and it is initialized
   with a Ref<SVGValueProperty<PropertyType>> which is created and maintained
   by SVGPropertyAnimatorFactory.

-- SVGAnimationColorFunction is the animation function that animates the
   attributes whose type are Color. Note the conversion form String to
   Color in this class has to handle the case when its value is "attributeName="
   e.g. <animate attributeName="fill" from="attributeName="r"/>

-- SVGColorAnimator will be defined to be
   SVGPrimitivePropertyAnimator<Color, SVGAnimationColorFunction>.

The life cycle of the RefCounted properties can be explained as follows:

-- SVGPropertyAnimatorFactory checks whether its HashMap has an entry
   for the given attribute name. If it does not have, it will create a
   new value through the value creation method for this attribute.

-- SVGPropertyAnimatorFactory passes the shared animated value to the
   animator creation method. So multiple animators will be accessing the
   same value through their RefCounted pointers.

-- When the animator is about to be deleted, it will notify the target
   SVGElement which will notify its SVGPropertyAnimatorFactory.
   SVGPropertyAnimatorFactory will check its HashMap and retrieves the
   entry for the given attribute name. If the refCount is 2, it is going
   to remove the entry form the HashMap.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* svg/SVGAnimateColorElement.cpp:
(WebCore::attributeValueIsCurrentColor): Deleted.
(WebCore::SVGAnimateColorElement::determinePropertyValueTypes): Deleted.
* svg/SVGAnimateColorElement.h:
* svg/SVGAnimateElementBase.cpp:
(WebCore::SVGAnimateElementBase::attributeAnimationController):
* svg/SVGAnimatedColor.cpp: Removed.
* svg/SVGAnimatedColor.h: Removed.
* svg/SVGAnimatorFactory.h:
(WebCore::SVGAnimatorFactory::create):
* svg/SVGAttributeAnimationController.cpp:
(WebCore::SVGAttributeAnimationController::~SVGAttributeAnimationController):
* svg/SVGAttributeAnimationController.h:
* svg/SVGElement.cpp:
(WebCore::SVGElement::SVGElement):
(WebCore::SVGElement::isAnimatedAttribute const):
(WebCore::SVGElement::createAnimator):
(WebCore::SVGElement::animatorWillBeDeleted):
* svg/SVGElement.h:
(WebCore::SVGElement::propertyAnimatorFactory):
* svg/SVGFitToViewBox.h:
* svg/SVGMPathElement.cpp:
* svg/graphics/filters/SVGFEImage.h:
* svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp: Added.
(WebCore::SVGAnimationColorFunction::colorFromString):
* svg/properties/SVGAnimationAdditiveValueFunctionImpl.h:
(WebCore::SVGAnimationColorFunction::progress):
* svg/properties/SVGAnimationFunction.h:
* svg/properties/SVGAttributeAnimator.cpp:
(WebCore::SVGAttributeAnimator::applyAnimatedStylePropertyChange):
(WebCore::SVGAttributeAnimator::removeAnimatedStyleProperty):
* svg/properties/SVGAttributeAnimator.h:
* svg/properties/SVGPrimitivePropertyAnimator.h: Added.
(WebCore::SVGPrimitivePropertyAnimator::create):
(WebCore::SVGPrimitivePropertyAnimator::SVGPrimitivePropertyAnimator):
* svg/properties/SVGPrimitivePropertyAnimatorImpl.h: Added.
* svg/properties/SVGPropertyAnimator.h: Added.
(WebCore::SVGPropertyAnimator::SVGPropertyAnimator):
(WebCore::SVGPropertyAnimator::adjustForInheritance const):
(WebCore::SVGPropertyAnimator::computeCSSPropertyValue const):
(WebCore::SVGPropertyAnimator::computeInheritedCSSPropertyValue const):
* svg/properties/SVGPropertyAnimatorFactory.h: Added.
(WebCore::SVGPropertyAnimatorFactory::isKnownAttribute):
(WebCore::SVGPropertyAnimatorFactory::createAnimator):
(WebCore::SVGPropertyAnimatorFactory::animatorWillBeDeleted):
(WebCore::SVGPropertyAnimatorFactory::createColorAnimator):
(WebCore::SVGPropertyAnimatorFactory::attributeAnimatorCreator):

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

25 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/svg/SVGAnimateColorElement.cpp
Source/WebCore/svg/SVGAnimateColorElement.h
Source/WebCore/svg/SVGAnimateElementBase.cpp
Source/WebCore/svg/SVGAnimatedColor.cpp [deleted file]
Source/WebCore/svg/SVGAnimatedColor.h [deleted file]
Source/WebCore/svg/SVGAnimatorFactory.h
Source/WebCore/svg/SVGAttributeAnimationController.cpp
Source/WebCore/svg/SVGAttributeAnimationController.h
Source/WebCore/svg/SVGElement.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGFitToViewBox.h
Source/WebCore/svg/SVGMPathElement.cpp
Source/WebCore/svg/graphics/filters/SVGFEImage.h
Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp [new file with mode: 0644]
Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.h
Source/WebCore/svg/properties/SVGAnimationFunction.h
Source/WebCore/svg/properties/SVGAttributeAnimator.cpp
Source/WebCore/svg/properties/SVGAttributeAnimator.h
Source/WebCore/svg/properties/SVGPrimitivePropertyAnimator.h [new file with mode: 0644]
Source/WebCore/svg/properties/SVGPrimitivePropertyAnimatorImpl.h [new file with mode: 0644]
Source/WebCore/svg/properties/SVGPropertyAnimator.h [new file with mode: 0644]
Source/WebCore/svg/properties/SVGPropertyAnimatorFactory.h [new file with mode: 0644]

index b8bfa47..b68f6b5 100644 (file)
@@ -1,3 +1,110 @@
+2019-03-20  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        Remove the SVG tear off objects for SVGColorAnimator
+        https://bugs.webkit.org/show_bug.cgi?id=196025
+
+        Reviewed by Simon Fraser.
+
+        SVG attributes like "fill" and "stroke" do not have reflecting properties
+        in SVGElement but they are animatable by SMIL. Animating such attributes
+        is different from animating the SVG animated properties. These new classes
+        will be added to handle the first type of this kind of attribute: the Color:
+
+        -- SVGPropertyAnimatorCreator is added to SVGElement. It is responsible 
+           for creating SVGPropertyAnimators for the attribute which do not have
+           reflecting animated properties stored by SVGElement. It will maintain
+           a HashMap for the animated values for these attributes which is indexed
+           by the attribute name. The animated values has to be RefCounted because
+           the same attribute can be animated by multiple animators. So the values
+           of this HashMap will be of type Ref<SVGProperty>, e.g.
+            <circle cx="80" cy="120" r="35">
+                <animate attributeName="fill" values="#080" begin="2s" />
+                <animate attributeName="fill" values="#602;#004" begin="4s" dur="5s"/>
+            </circle>
+
+        -- SVGPropertyAnimator is the a new type which animates an attribute with
+           no reflecting animated property.
+
+        -- SVGPrimitivePropertyAnimator is a template class which is responsible
+           for animating attributes with primitive types, e.g. Color, string and 
+           float. It is derived form SVGPropertyAnimator and it is initialized 
+           with a Ref<SVGValueProperty<PropertyType>> which is created and maintained
+           by SVGPropertyAnimatorFactory.
+
+        -- SVGAnimationColorFunction is the animation function that animates the
+           attributes whose type are Color. Note the conversion form String to 
+           Color in this class has to handle the case when its value is "attributeName="
+           e.g. <animate attributeName="fill" from="attributeName="r"/>
+
+        -- SVGColorAnimator will be defined to be
+           SVGPrimitivePropertyAnimator<Color, SVGAnimationColorFunction>.
+
+        The life cycle of the RefCounted properties can be explained as follows:
+
+        -- SVGPropertyAnimatorFactory checks whether its HashMap has an entry
+           for the given attribute name. If it does not have, it will create a
+           new value through the value creation method for this attribute.
+
+        -- SVGPropertyAnimatorFactory passes the shared animated value to the
+           animator creation method. So multiple animators will be accessing the
+           same value through their RefCounted pointers.
+
+        -- When the animator is about to be deleted, it will notify the target
+           SVGElement which will notify its SVGPropertyAnimatorFactory.
+           SVGPropertyAnimatorFactory will check its HashMap and retrieves the
+           entry for the given attribute name. If the refCount is 2, it is going
+           to remove the entry form the HashMap.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * svg/SVGAnimateColorElement.cpp:
+        (WebCore::attributeValueIsCurrentColor): Deleted.
+        (WebCore::SVGAnimateColorElement::determinePropertyValueTypes): Deleted.
+        * svg/SVGAnimateColorElement.h:
+        * svg/SVGAnimateElementBase.cpp:
+        (WebCore::SVGAnimateElementBase::attributeAnimationController):
+        * svg/SVGAnimatedColor.cpp: Removed.
+        * svg/SVGAnimatedColor.h: Removed.
+        * svg/SVGAnimatorFactory.h:
+        (WebCore::SVGAnimatorFactory::create):
+        * svg/SVGAttributeAnimationController.cpp:
+        (WebCore::SVGAttributeAnimationController::~SVGAttributeAnimationController):
+        * svg/SVGAttributeAnimationController.h:
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::SVGElement):
+        (WebCore::SVGElement::isAnimatedAttribute const):
+        (WebCore::SVGElement::createAnimator):
+        (WebCore::SVGElement::animatorWillBeDeleted):
+        * svg/SVGElement.h:
+        (WebCore::SVGElement::propertyAnimatorFactory):
+        * svg/SVGFitToViewBox.h:
+        * svg/SVGMPathElement.cpp:
+        * svg/graphics/filters/SVGFEImage.h:
+        * svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp: Added.
+        (WebCore::SVGAnimationColorFunction::colorFromString):
+        * svg/properties/SVGAnimationAdditiveValueFunctionImpl.h:
+        (WebCore::SVGAnimationColorFunction::progress):
+        * svg/properties/SVGAnimationFunction.h:
+        * svg/properties/SVGAttributeAnimator.cpp:
+        (WebCore::SVGAttributeAnimator::applyAnimatedStylePropertyChange):
+        (WebCore::SVGAttributeAnimator::removeAnimatedStyleProperty):
+        * svg/properties/SVGAttributeAnimator.h:
+        * svg/properties/SVGPrimitivePropertyAnimator.h: Added.
+        (WebCore::SVGPrimitivePropertyAnimator::create):
+        (WebCore::SVGPrimitivePropertyAnimator::SVGPrimitivePropertyAnimator):
+        * svg/properties/SVGPrimitivePropertyAnimatorImpl.h: Added.
+        * svg/properties/SVGPropertyAnimator.h: Added.
+        (WebCore::SVGPropertyAnimator::SVGPropertyAnimator):
+        (WebCore::SVGPropertyAnimator::adjustForInheritance const):
+        (WebCore::SVGPropertyAnimator::computeCSSPropertyValue const):
+        (WebCore::SVGPropertyAnimator::computeInheritedCSSPropertyValue const):
+        * svg/properties/SVGPropertyAnimatorFactory.h: Added.
+        (WebCore::SVGPropertyAnimatorFactory::isKnownAttribute):
+        (WebCore::SVGPropertyAnimatorFactory::createAnimator):
+        (WebCore::SVGPropertyAnimatorFactory::animatorWillBeDeleted):
+        (WebCore::SVGPropertyAnimatorFactory::createColorAnimator):
+        (WebCore::SVGPropertyAnimatorFactory::attributeAnimatorCreator):
+
 2019-03-20  Alex Christensen  <achristensen@webkit.org>
 
         Use WeakPtr instead of storing raw pointers in WebSocket code
index f8a799f..455de0f 100644 (file)
@@ -2270,7 +2270,6 @@ svg/SVGAnimateElementBase.cpp
 svg/SVGAnimateMotionElement.cpp
 svg/SVGAnimateTransformElement.cpp
 svg/SVGAnimatedAngle.cpp
-svg/SVGAnimatedColor.cpp
 svg/SVGAnimatedEnumeration.cpp
 svg/SVGAnimatedLength.cpp
 svg/SVGAnimatedLengthList.cpp
@@ -2422,6 +2421,7 @@ svg/graphics/filters/SVGFilterBuilder.cpp
 
 svg/properties/SVGAnimatedPathSegListPropertyTearOff.cpp
 svg/properties/SVGAnimatedProperty.cpp
+svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp
 svg/properties/SVGAttributeAnimator.cpp
 svg/properties/SVGAttributeOwnerProxy.cpp
 svg/properties/SVGLegacyAnimatedProperty.cpp
index 3a20c0f..fe97813 100644 (file)
                439D334313A6911C00C20F4F /* SVGAnimatedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 439D334013A6911C00C20F4F /* SVGAnimatedType.h */; };
                439D334413A6911C00C20F4F /* SVGAnimatedTypeAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = 439D334113A6911C00C20F4F /* SVGAnimatedTypeAnimator.h */; };
                439D334513A6911C00C20F4F /* SVGAnimatorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 439D334213A6911C00C20F4F /* SVGAnimatorFactory.h */; };
-               43A625F813B3304000AC94B8 /* SVGAnimatedColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A625F613B3304000AC94B8 /* SVGAnimatedColor.h */; };
                43B85ED418CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43B85ED218CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.cpp */; };
                43B9336913B261B1004584BF /* SVGAnimatedPointList.h in Headers */ = {isa = PBXBuildFile; fileRef = 43B9336713B261B1004584BF /* SVGAnimatedPointList.h */; };
                43C092BC12D9E4EE00A989C3 /* RenderSVGForeignObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C092BA12D9E4EE00A989C3 /* RenderSVGForeignObject.h */; };
                439D334113A6911C00C20F4F /* SVGAnimatedTypeAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedTypeAnimator.h; sourceTree = "<group>"; };
                439D334213A6911C00C20F4F /* SVGAnimatorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatorFactory.h; sourceTree = "<group>"; };
                43A0F0B013AC7D6D00A5F0A7 /* SVGAnimatedNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedNumber.cpp; sourceTree = "<group>"; };
-               43A625F613B3304000AC94B8 /* SVGAnimatedColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedColor.h; sourceTree = "<group>"; };
-               43A625F713B3304000AC94B8 /* SVGAnimatedColor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedColor.cpp; sourceTree = "<group>"; };
                43A6266613B3D11000AC94B8 /* SVGAnimatedString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedString.cpp; sourceTree = "<group>"; };
                43B85ED018CBEACE00E31AF4 /* makeSelectorPseudoClassAndCompatibilityElementMap.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = makeSelectorPseudoClassAndCompatibilityElementMap.py; sourceTree = "<group>"; };
                43B85ED218CBEC5200E31AF4 /* SelectorPseudoClassAndCompatibilityElementMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SelectorPseudoClassAndCompatibilityElementMap.cpp; path = DerivedSources/WebCore/SelectorPseudoClassAndCompatibilityElementMap.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
                724ED3301A3A8B2300F5F13C /* JSEXTBlendMinMax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEXTBlendMinMax.h; sourceTree = "<group>"; };
                724EE54E1DC7F25B00A91FFB /* ActivityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivityState.h; sourceTree = "<group>"; };
                724EE54F1DC7F25B00A91FFB /* ActivityStateChangeObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivityStateChangeObserver.h; sourceTree = "<group>"; };
+               7266F0132241BCE200833975 /* SVGPropertyAnimatorFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGPropertyAnimatorFactory.h; sourceTree = "<group>"; };
+               7266F0142241BFB200833975 /* SVGPrimitivePropertyAnimatorImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGPrimitivePropertyAnimatorImpl.h; sourceTree = "<group>"; };
+               7266F0152241C09800833975 /* SVGPrimitivePropertyAnimator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGPrimitivePropertyAnimator.h; sourceTree = "<group>"; };
+               7266F0162241C0FE00833975 /* SVGPropertyAnimator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGPropertyAnimator.h; sourceTree = "<group>"; };
+               7266F01822429CFD00833975 /* SVGAnimationAdditiveValueFunctionImpl.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimationAdditiveValueFunctionImpl.cpp; sourceTree = "<group>"; };
                727AFED11A2EA6A0000442E8 /* EXTsRGB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTsRGB.cpp; sourceTree = "<group>"; };
                727AFED21A2EA6A0000442E8 /* EXTsRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTsRGB.h; sourceTree = "<group>"; };
                727AFED31A2EA6A0000442E8 /* EXTsRGB.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EXTsRGB.idl; sourceTree = "<group>"; };
                                721443452240C8BA00F12FF7 /* SVGAnimatedValueProperty.h */,
                                55BE025F223B29C50032F08A /* SVGAnimationAdditiveFunction.h */,
                                55EE535E223B2A0E00FBA944 /* SVGAnimationAdditiveValueFunction.h */,
+                               7266F01822429CFD00833975 /* SVGAnimationAdditiveValueFunctionImpl.cpp */,
                                55BE0259223B29C10032F08A /* SVGAnimationAdditiveValueFunctionImpl.h */,
                                55DCC51D2240615500C26E32 /* SVGAnimationDiscreteFunction.h */,
                                55DCC51C2240605E00C26E32 /* SVGAnimationDiscreteFunctionImpl.h */,
                                55EE5354223B29E900FBA944 /* SVGMemberAccessor.h */,
                                55BE025A223B29C20032F08A /* SVGPointerMemberAccessor.h */,
                                55DCC5252240749E00C26E32 /* SVGPrimitiveList.h */,
+                               7266F0152241C09800833975 /* SVGPrimitivePropertyAnimator.h */,
+                               7266F0142241BFB200833975 /* SVGPrimitivePropertyAnimatorImpl.h */,
                                55EE5363223B2A2400FBA944 /* SVGProperty.h */,
                                55DCC526224074FA00C26E32 /* SVGPropertyAccessor.h */,
                                55DCC5272240750B00C26E32 /* SVGPropertyAccessorImpl.h */,
+                               7266F0162241C0FE00833975 /* SVGPropertyAnimator.h */,
+                               7266F0132241BCE200833975 /* SVGPropertyAnimatorFactory.h */,
                                55EE5360223B2A2100FBA944 /* SVGPropertyOwner.h */,
                                55BE025C223B29C30032F08A /* SVGPropertyOwnerRegistry.h */,
                                55BE0257223B29C00032F08A /* SVGPropertyRegistry.h */,
                                087B84951272CEC700A14417 /* SVGAnimatedAngle.h */,
                                B22277E60D00BF1F0071B782 /* SVGAnimatedAngle.idl */,
                                B22277E70D00BF1F0071B782 /* SVGAnimatedBoolean.idl */,
-                               43A625F713B3304000AC94B8 /* SVGAnimatedColor.cpp */,
-                               43A625F613B3304000AC94B8 /* SVGAnimatedColor.h */,
                                71CC7A1F152A0BFE009EEAF9 /* SVGAnimatedEnumeration.cpp */,
                                08D46CE2127AD5FC0089694B /* SVGAnimatedEnumeration.h */,
                                B22277E80D00BF1F0071B782 /* SVGAnimatedEnumeration.idl */,
                                B22279770D00BF220071B782 /* SVGAngle.h in Headers */,
                                B222797A0D00BF220071B782 /* SVGAnimateColorElement.h in Headers */,
                                087B84961272CEC800A14417 /* SVGAnimatedAngle.h in Headers */,
-                               43A625F813B3304000AC94B8 /* SVGAnimatedColor.h in Headers */,
                                08D46CE3127AD5FC0089694B /* SVGAnimatedEnumeration.h in Headers */,
                                71FB967B1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h in Headers */,
                                089021A9126EF5DE0092D5EA /* SVGAnimatedLength.h in Headers */,
index 0b82c1a..9ccc64d 100644 (file)
@@ -40,19 +40,4 @@ Ref<SVGAnimateColorElement> SVGAnimateColorElement::create(const QualifiedName&
     return adoptRef(*new SVGAnimateColorElement(tagName, document));
 }
 
-static bool attributeValueIsCurrentColor(const String& value)
-{
-    static NeverDestroyed<const AtomicString> currentColor("currentColor", AtomicString::ConstructFromLiteral);
-    return value == currentColor;
-}
-
-void SVGAnimateColorElement::determinePropertyValueTypes(const String& from, const String& to)
-{
-    SVGAnimateElementBase::determinePropertyValueTypes(from, to);
-    if (attributeValueIsCurrentColor(from))
-        m_fromPropertyValueType = CurrentColorValue;
-    if (attributeValueIsCurrentColor(to))
-        m_toPropertyValueType = CurrentColorValue;
-}
-
 }
index 87ba96c..e38aa74 100644 (file)
@@ -32,7 +32,6 @@ public:
 
 private:
     SVGAnimateColorElement(const QualifiedName&, Document&);
-    void determinePropertyValueTypes(const String& from, const String& to) override;
 };
 
 } // namespace WebCore
index 6b09a7f..8a34704 100644 (file)
@@ -49,7 +49,7 @@ SVGAttributeAnimationControllerBase& SVGAnimateElementBase::attributeAnimationCo
     ASSERT(!hasInvalidCSSAttributeType());
 
     if (!m_attributeAnimationController) {
-        if (targetElement()->isAnimatedPropertyAttribute(attributeName()))
+        if (targetElement()->isAnimatedAttribute(attributeName()))
             m_attributeAnimationController = std::make_unique<SVGAttributeAnimationController>(*this, *targetElement());
         else
             m_attributeAnimationController = std::make_unique<SVGLegacyAttributeAnimationController>(*this, *targetElement());
diff --git a/Source/WebCore/svg/SVGAnimatedColor.cpp b/Source/WebCore/svg/SVGAnimatedColor.cpp
deleted file mode 100644 (file)
index c46a775..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) Research In Motion Limited 2011. All rights reserved.
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "SVGAnimatedColor.h"
-
-#include "CSSParser.h"
-#include "RenderElement.h"
-#include "SVGAnimateElementBase.h"
-
-namespace WebCore {
-
-SVGAnimatedColorAnimator::SVGAnimatedColorAnimator(SVGAnimationElement& animationElement, SVGElement& contextElement)
-    : SVGAnimatedTypeAnimator(AnimatedColor, &animationElement, &contextElement)
-{
-}
-
-std::unique_ptr<SVGAnimatedType> SVGAnimatedColorAnimator::constructFromString(const String& string)
-{
-    return SVGAnimatedType::create(SVGPropertyTraits<Color>::fromString(string));
-}
-
-void SVGAnimatedColorAnimator::addAnimatedTypes(SVGAnimatedType* from, SVGAnimatedType* to)
-{
-    ASSERT(from);
-    ASSERT(to);
-    ASSERT(from->type() == AnimatedColor);
-    ASSERT(to->type() == AnimatedColor);
-
-    // Ignores any alpha and sets alpha on result to 100% opaque.
-    const auto& fromColor = from->as<Color>();
-    auto& toColor = to->as<Color>();
-    toColor = { roundAndClampColorChannel(toColor.red() + fromColor.red()),
-        roundAndClampColorChannel(toColor.green() + fromColor.green()),
-        roundAndClampColorChannel(toColor.blue() + fromColor.blue()) };
-}
-
-static inline Color currentColor(SVGElement& targetElement)
-{
-    RenderElement* targetRenderer = targetElement.renderer();
-    if (!targetRenderer)
-        return { };
-    return targetRenderer->style().visitedDependentColor(CSSPropertyColor);
-}
-
-static Color parseColorFromString(SVGAnimationElement*, const String& string)
-{
-    return CSSParser::parseColor(string.stripWhiteSpace());
-}
-
-void SVGAnimatedColorAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated)
-{
-    ASSERT(m_animationElement);
-    ASSERT(m_contextElement);
-
-    auto fromColor = (m_animationElement->animationMode() == AnimationMode::To ? animated : from)->as<Color>();
-    auto toColor = to->as<Color>();
-
-    // Apply CSS inheritance rules.
-    m_animationElement->adjustForInheritance<Color>(parseColorFromString, m_animationElement->fromPropertyValueType(), fromColor, m_contextElement);
-    m_animationElement->adjustForInheritance<Color>(parseColorFromString, m_animationElement->toPropertyValueType(), toColor, m_contextElement);
-
-    // Apply <animateColor> rules.
-    if (m_animationElement->fromPropertyValueType() == CurrentColorValue)
-        fromColor = currentColor(*m_contextElement);
-    if (m_animationElement->toPropertyValueType() == CurrentColorValue)
-        toColor = currentColor(*m_contextElement);
-
-    const auto& toAtEndOfDurationColor = toAtEndOfDuration->as<Color>();
-    auto& animatedColor = animated->as<Color>();
-
-    // FIXME: ExtendedColor - this will need to handle blending between colors in different color spaces,
-    // as well as work with non [0-255] Colors.
-    float red = animatedColor.red();
-    m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.red(), toColor.red(), toAtEndOfDurationColor.red(), red);
-
-    float green = animatedColor.green();
-    m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.green(), toColor.green(), toAtEndOfDurationColor.green(), green);
-
-    float blue = animatedColor.blue();
-    m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.blue(), toColor.blue(), toAtEndOfDurationColor.blue(), blue);
-
-    float alpha = animatedColor.alpha();
-    m_animationElement->animateAdditiveNumber(percentage, repeatCount, fromColor.alpha(), toColor.alpha(), toAtEndOfDurationColor.alpha(), alpha);
-
-    animatedColor = { roundAndClampColorChannel(red), roundAndClampColorChannel(green), roundAndClampColorChannel(blue), roundAndClampColorChannel(alpha) };
-}
-
-float SVGAnimatedColorAnimator::calculateDistance(const String& fromString, const String& toString)
-{
-    Color from = CSSParser::parseColor(fromString.stripWhiteSpace());
-    if (!from.isValid())
-        return -1;
-    Color to = CSSParser::parseColor(toString.stripWhiteSpace());
-    if (!to.isValid())
-        return -1;
-    float red = from.red() - to.red();
-    float green = from.green() - to.green();
-    float blue = from.blue() - to.blue();
-    return sqrtf(red * red + green * green + blue * blue);
-}
-
-}
diff --git a/Source/WebCore/svg/SVGAnimatedColor.h b/Source/WebCore/svg/SVGAnimatedColor.h
deleted file mode 100644 (file)
index 1e4041b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) Research In Motion Limited 2011. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include "SVGAnimatedTypeAnimator.h"
-
-namespace WebCore {
-
-class SVGAnimatedColorAnimator final : public SVGAnimatedTypeAnimator {
-public:
-    SVGAnimatedColorAnimator(SVGAnimationElement&, SVGElement&);
-
-private:
-    std::unique_ptr<SVGAnimatedType> constructFromString(const String&) final;
-    std::unique_ptr<SVGAnimatedType> startAnimValAnimation(const SVGElementAnimatedPropertyList&) final { return nullptr; }
-    void stopAnimValAnimation(const SVGElementAnimatedPropertyList&) final { }
-    void resetAnimValToBaseVal(const SVGElementAnimatedPropertyList&, SVGAnimatedType&) final { }
-    void animValWillChange(const SVGElementAnimatedPropertyList&) final { }
-    void animValDidChange(const SVGElementAnimatedPropertyList&) final { }
-    void addAnimatedTypes(SVGAnimatedType*, SVGAnimatedType*) final;
-    void calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*) final;
-    float calculateDistance(const String& fromString, const String& toString) final;
-};
-
-} // namespace WebCore
index 511a22c..381fc57 100644 (file)
@@ -20,7 +20,6 @@
 #pragma once
 
 #include "SVGAnimatedAngle.h"
-#include "SVGAnimatedColor.h"
 #include "SVGAnimatedEnumeration.h"
 #include "SVGAnimatedLength.h"
 #include "SVGAnimatedLengthList.h"
@@ -44,18 +43,18 @@ public:
         ASSERT(contextElement);
 
         switch (attributeType) {
-        case AnimatedAngle:
-            return std::make_unique<SVGAnimatedAngleAnimator>(animationElement, contextElement);
         case AnimatedBoolean:
-            return nullptr;
         case AnimatedColor:
-            return std::make_unique<SVGAnimatedColorAnimator>(*animationElement, *contextElement);
-        case AnimatedEnumeration:
-            return std::make_unique<SVGAnimatedEnumerationAnimator>(animationElement, contextElement);
         case AnimatedInteger:
-            return nullptr;
         case AnimatedIntegerOptionalInteger:
+        case AnimatedPreserveAspectRatio:
+        case AnimatedRect:
             return nullptr;
+
+        case AnimatedAngle:
+            return std::make_unique<SVGAnimatedAngleAnimator>(animationElement, contextElement);
+        case AnimatedEnumeration:
+            return std::make_unique<SVGAnimatedEnumerationAnimator>(animationElement, contextElement);
         case AnimatedLength:
             return std::make_unique<SVGAnimatedLengthAnimator>(animationElement, contextElement);
         case AnimatedLengthList:
@@ -70,10 +69,6 @@ public:
             return std::make_unique<SVGAnimatedPathAnimator>(animationElement, contextElement);
         case AnimatedPoints:
             return std::make_unique<SVGAnimatedPointListAnimator>(animationElement, contextElement);
-        case AnimatedPreserveAspectRatio:
-            return nullptr;
-        case AnimatedRect:
-            return nullptr;
         case AnimatedString:
             return std::make_unique<SVGAnimatedStringAnimator>(animationElement, contextElement);
         case AnimatedTransformList:
index 4ca362d..f9ccb67 100644 (file)
@@ -37,6 +37,12 @@ SVGAttributeAnimationController::SVGAttributeAnimationController(SVGAnimationEle
     : SVGAttributeAnimationControllerBase(animationElement, targetElement)
 {
 }
+    
+SVGAttributeAnimationController::~SVGAttributeAnimationController()
+{
+    if (m_animator)
+        m_targetElement.animatorWillBeDeleted(m_animationElement.attributeName());
+}
 
 SVGAttributeAnimator* SVGAttributeAnimationController::animator() const
 {
index 32bca5d..1ec02d3 100644 (file)
@@ -37,6 +37,7 @@ class SVGSMILElement;
 class SVGAttributeAnimationController : public SVGAttributeAnimationControllerBase {
 public:
     SVGAttributeAnimationController(SVGAnimationElement&, SVGElement&);
+    ~SVGAttributeAnimationController();
     
 private:
     SVGAttributeAnimator* animator() const;
index 0c86598..9d35870 100644 (file)
@@ -44,6 +44,7 @@
 #include "SVGGraphicsElement.h"
 #include "SVGImageElement.h"
 #include "SVGNames.h"
+#include "SVGPropertyAnimatorFactory.h"
 #include "SVGRenderStyle.h"
 #include "SVGRenderSupport.h"
 #include "SVGSVGElement.h"
@@ -275,6 +276,7 @@ static inline const HashMap<QualifiedName::QualifiedNameImpl*, AnimatedPropertyT
 SVGElement::SVGElement(const QualifiedName& tagName, Document& document)
     : StyledElement(tagName, document, CreateSVGElement)
     , SVGLangSpace(this)
+    , m_propertyAnimatorFactory(std::make_unique<SVGPropertyAnimatorFactory>())
 {
     registerAttributes();
 }
@@ -756,11 +758,16 @@ bool SVGElement::isAnimatedPropertyAttribute(const QualifiedName& attributeName)
 
 bool SVGElement::isAnimatedAttribute(const QualifiedName& attributeName) const
 {
-    return isAnimatedPropertyAttribute(attributeName);
+    return SVGPropertyAnimatorFactory::isKnownAttribute(attributeName) || isAnimatedPropertyAttribute(attributeName);
 }
 
 std::unique_ptr<SVGAttributeAnimator> SVGElement::createAnimator(const QualifiedName& attributeName, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
 {
+    // Property animator, e.g. "fill" or "fill-opacity".
+    if (auto animator = propertyAnimatorFactory().createAnimator(attributeName, animationMode, calcMode, isAccumulated, isAdditive))
+        return animator;
+    
+    // Animated property animator.
     auto animator = propertyRegistry().createAnimator(attributeName, animationMode, calcMode, isAccumulated, isAdditive);
     if (!animator)
         return animator;
@@ -768,6 +775,11 @@ std::unique_ptr<SVGAttributeAnimator> SVGElement::createAnimator(const Qualified
         instance->propertyRegistry().appendAnimatedInstance(attributeName, *animator);
     return animator;
 }
+    
+void SVGElement::animatorWillBeDeleted(const QualifiedName& attributeName)
+{
+    propertyAnimatorFactory().animatorWillBeDeleted(attributeName);
+}
 
 Optional<ElementStyle> SVGElement::resolveCustomStyle(const RenderStyle& parentStyle, const RenderStyle*)
 {
index ff03dd3..c8bb1ba 100644 (file)
@@ -42,6 +42,7 @@ class DeprecatedCSSOMValue;
 class Document;
 class SVGDocumentExtensions;
 class SVGElementRareData;
+class SVGPropertyAnimatorFactory;
 class SVGSVGElement;
 class SVGUseElement;
 
@@ -161,7 +162,9 @@ public:
     void commitPropertyChange(SVGAnimatedProperty&);
 
     const SVGElement* attributeContextElement() const override { return this; }
+    SVGPropertyAnimatorFactory& propertyAnimatorFactory() { return *m_propertyAnimatorFactory; }
     std::unique_ptr<SVGAttributeAnimator> createAnimator(const QualifiedName&, AnimationMode, CalcMode, bool isAccumulated, bool isAdditive);
+    void animatorWillBeDeleted(const QualifiedName&);
 
     // These are needed for the RenderTree, animation and DOM.
     const auto& className() const { return m_className.currentValue(attributeOwnerProxy()); }
@@ -215,6 +218,8 @@ private:
 
     HashSet<SVGElement*> m_elementsWithRelativeLengths;
 
+    std::unique_ptr<SVGPropertyAnimatorFactory> m_propertyAnimatorFactory;
+
     AttributeOwnerProxy m_attributeOwnerProxy { *this };
     PropertyRegistry m_propertyRegistry { *this };
     SVGAnimatedStringAttribute m_className;
index 0e1efe7..3b0c434 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
  * Copyright (C) 2004, 2005, 2006, 2007, 2010 Rob Buis <buis@kde.org>
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 #include "FloatRect.h"
 #include "QualifiedName.h"
+#include "SVGAnimatedPropertyImpl.h"
+#include "SVGAttributeOwnerProxyImpl.h"
 #include "SVGAttributeRegistry.h"
 #include "SVGNames.h"
 #include "SVGPreserveAspectRatio.h"
+#include "SVGPropertyOwnerRegistry.h"
 #include <wtf/HashSet.h>
 
 namespace WebCore {
index 60ba714..53765d9 100644 (file)
@@ -26,6 +26,7 @@
 #include "SVGDocumentExtensions.h"
 #include "SVGNames.h"
 #include "SVGPathElement.h"
+#include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
 
index 6874fdf..ac160ed 100644 (file)
@@ -30,6 +30,7 @@ namespace WebCore {
 class Document;
 class Image;
 class RenderElement;
+class TreeScope;
 
 class FEImage final : public FilterEffect {
 public:
diff --git a/Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp b/Source/WebCore/svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp
new file mode 100644 (file)
index 0000000..1b1cbeb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SVGAnimationAdditiveValueFunctionImpl.h"
+
+#include "RenderElement.h"
+#include "SVGElement.h"
+
+namespace WebCore {
+
+Color SVGAnimationColorFunction::colorFromString(SVGElement* targetElement, const String& string)
+{
+    static NeverDestroyed<const AtomicString> currentColor("currentColor", AtomicString::ConstructFromLiteral);
+
+    if (string != currentColor.get())
+        return SVGPropertyTraits<Color>::fromString(string);
+
+    if (auto* renderer = targetElement->renderer())
+        return renderer->style().visitedDependentColor(CSSPropertyColor);
+
+    return { };
+}
+
+}
index 5d74710..127443f 100644 (file)
 
 namespace WebCore {
 
+class SVGAnimationColorFunction : public SVGAnimationAdditiveValueFunction<Color> {
+public:
+    using Base = SVGAnimationAdditiveValueFunction<Color>;
+    using Base::Base;
+
+    void setFromAndToValues(SVGElement* targetElement, const String& from, const String& to) override
+    {
+        m_from = colorFromString(targetElement, from);
+        m_to = colorFromString(targetElement, to);
+    }
+
+    void setToAtEndOfDurationValue(const String& toAtEndOfDuration) override
+    {
+        m_toAtEndOfDuration = SVGPropertyTraits<Color>::fromString(toAtEndOfDuration);
+    }
+
+    void progress(SVGElement*, float percentage, unsigned repeatCount, Color& animated)
+    {
+        Color from = m_animationMode == AnimationMode::To ? animated : m_from;
+        
+        float red = Base::progress(percentage, repeatCount, from.red(), m_to.red(), toAtEndOfDuration().red(), animated.red());
+        float green = Base::progress(percentage, repeatCount, from.green(), m_to.green(), toAtEndOfDuration().green(), animated.green());
+        float blue = Base::progress(percentage, repeatCount, from.blue(), m_to.blue(), toAtEndOfDuration().blue(), animated.blue());
+        float alpha = Base::progress(percentage, repeatCount, from.alpha(), m_to.alpha(), toAtEndOfDuration().alpha(), animated.alpha());
+        
+        animated = { roundAndClampColorChannel(red), roundAndClampColorChannel(green), roundAndClampColorChannel(blue), roundAndClampColorChannel(alpha) };
+    }
+
+    float calculateDistance(SVGElement*, const String& from, const String& to) const override
+    {
+        Color fromColor = CSSParser::parseColor(from.stripWhiteSpace());
+        if (!fromColor.isValid())
+            return -1;
+        Color toColor = CSSParser::parseColor(to.stripWhiteSpace());
+        if (!toColor.isValid())
+            return -1;
+        float red = fromColor.red() - toColor.red();
+        float green = fromColor.green() - toColor.green();
+        float blue = fromColor.blue() - toColor.blue();
+        return sqrtf(red * red + green * green + blue * blue);
+    }
+
+private:
+    void addFromAndToValues(SVGElement*) override
+    {
+        // Ignores any alpha and sets alpha on result to 100% opaque.
+        m_to = {
+            roundAndClampColorChannel(m_to.red() + m_from.red()),
+            roundAndClampColorChannel(m_to.green() + m_from.green()),
+            roundAndClampColorChannel(m_to.blue() + m_from.blue())
+        };
+    }
+
+    static Color colorFromString(SVGElement*, const String&);
+};
+
 class SVGAnimationIntegerFunction : public SVGAnimationAdditiveValueFunction<int> {
     friend class SVGAnimatedIntegerPairAnimator;
 
index 4aeb71c..858c948 100644 (file)
 
 #pragma once
 
+#include "SVGAttributeAnimator.h"
+
 namespace WebCore {
 
+class SVGElement;
+
 class SVGAnimationFunction {
 public:
     virtual ~SVGAnimationFunction() = default;
index d92a6c5..dc46a0f 100644 (file)
 
 namespace WebCore {
 
+void SVGAttributeAnimator::applyAnimatedStylePropertyChange(SVGElement* element, CSSPropertyID id, const String& value)
+{
+    ASSERT(element);
+    ASSERT(!element->m_deletionHasBegun);
+    
+    if (!element->ensureAnimatedSMILStyleProperties().setProperty(id, value, false))
+        return;
+    element->invalidateStyle();
+}
+
+void SVGAttributeAnimator::applyAnimatedStylePropertyChange(SVGElement* targetElement, const String& value)
+{
+    ASSERT(targetElement);
+    ASSERT(m_attributeName != anyQName());
+    
+    // FIXME: Do we really need to check both isConnected and !parentNode?
+    if (!targetElement->isConnected() || !targetElement->parentNode())
+        return;
+    
+    CSSPropertyID id = cssPropertyID(m_attributeName.localName());
+    
+    SVGElement::InstanceUpdateBlocker blocker(*targetElement);
+    applyAnimatedStylePropertyChange(targetElement, id, value);
+    
+    // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
+    for (auto* instance : targetElement->instances())
+        applyAnimatedStylePropertyChange(instance, id, value);
+}
+    
+void SVGAttributeAnimator::removeAnimatedStyleProperty(SVGElement* element, CSSPropertyID id)
+{
+    ASSERT(element);
+    ASSERT(!element->m_deletionHasBegun);
+
+    element->ensureAnimatedSMILStyleProperties().removeProperty(id);
+    element->invalidateStyle();
+}
+
+void SVGAttributeAnimator::removeAnimatedStyleProperty(SVGElement* targetElement)
+{
+    ASSERT(targetElement);
+    ASSERT(m_attributeName != anyQName());
+
+    // FIXME: Do we really need to check both isConnected and !parentNode?
+    if (!targetElement->isConnected() || !targetElement->parentNode())
+        return;
+
+    CSSPropertyID id = cssPropertyID(m_attributeName.localName());
+
+    SVGElement::InstanceUpdateBlocker blocker(*targetElement);
+    removeAnimatedStyleProperty(targetElement, id);
+
+    // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
+    for (auto* instance : targetElement->instances())
+        removeAnimatedStyleProperty(instance, id);
+}
+    
 void SVGAttributeAnimator::applyAnimatedPropertyChange(SVGElement* element, const QualifiedName& attributeName)
 {
     ASSERT(!element->m_deletionHasBegun);
index 8492465..894d5e7 100644 (file)
@@ -74,8 +74,12 @@ public:
     virtual float calculateDistance(SVGElement*, const String&, const String&) const { return -1; }
 
 protected:
+    static void applyAnimatedStylePropertyChange(SVGElement*, CSSPropertyID, const String& value);
+    static void removeAnimatedStyleProperty(SVGElement*, CSSPropertyID);
     static void applyAnimatedPropertyChange(SVGElement*, const QualifiedName&);
 
+    void applyAnimatedStylePropertyChange(SVGElement*, const String& value);
+    void removeAnimatedStyleProperty(SVGElement*);
     void applyAnimatedPropertyChange(SVGElement*);
 
     const QualifiedName& m_attributeName;
diff --git a/Source/WebCore/svg/properties/SVGPrimitivePropertyAnimator.h b/Source/WebCore/svg/properties/SVGPrimitivePropertyAnimator.h
new file mode 100644 (file)
index 0000000..bbf33a9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "SVGPropertyAnimator.h"
+#include "SVGPropertyTraits.h"
+#include "SVGValueProperty.h"
+
+namespace WebCore {
+
+template<typename PropertyType, typename AnimationFunction>
+class SVGPrimitivePropertyAnimator : public SVGPropertyAnimator<AnimationFunction> {
+    using Base = SVGPropertyAnimator<AnimationFunction>;
+    using ValuePropertyType = SVGValueProperty<PropertyType>;
+    using Base::Base;
+    using Base::applyAnimatedStylePropertyChange;
+    using Base::computeCSSPropertyValue;
+    using Base::m_attributeName;
+    using Base::m_function;
+    
+public:
+    static auto create(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
+    {
+        return std::make_unique<SVGPrimitivePropertyAnimator>(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
+    }
+    
+    template<typename... Arguments>
+    SVGPrimitivePropertyAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, Arguments&&... arguments)
+        : Base(attributeName, std::forward<Arguments>(arguments)...)
+        , m_property(static_reference_cast<ValuePropertyType>(WTFMove(property)))
+    {
+    }
+
+    void start(SVGElement* targetElement) override
+    {
+        String baseValue = computeCSSPropertyValue(targetElement, cssPropertyID(m_attributeName.localName()));
+        m_property->setValue(SVGPropertyTraits<PropertyType>::fromString(baseValue));
+    }
+
+    void progress(SVGElement* targetElement, float percentage, unsigned repeatCount) override
+    {
+        PropertyType& animated = m_property->value();
+        m_function.progress(targetElement, percentage, repeatCount, animated);
+    }
+
+    void apply(SVGElement* targetElement) override
+    {
+        applyAnimatedStylePropertyChange(targetElement, SVGPropertyTraits<PropertyType>::toString(m_property->value()));
+    }
+
+protected:
+    Ref<ValuePropertyType> m_property;
+};
+    
+}
diff --git a/Source/WebCore/svg/properties/SVGPrimitivePropertyAnimatorImpl.h b/Source/WebCore/svg/properties/SVGPrimitivePropertyAnimatorImpl.h
new file mode 100644 (file)
index 0000000..7300f0a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "SVGAnimationFunction.h"
+#include "SVGPrimitivePropertyAnimator.h"
+
+namespace WebCore {
+
+using SVGColorAnimator = SVGPrimitivePropertyAnimator<Color, SVGAnimationColorFunction>;
+
+}
diff --git a/Source/WebCore/svg/properties/SVGPropertyAnimator.h b/Source/WebCore/svg/properties/SVGPropertyAnimator.h
new file mode 100644 (file)
index 0000000..9906b1d
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CSSComputedStyleDeclaration.h"
+#include "CSSPropertyParser.h"
+#include "SVGAttributeAnimator.h"
+#include "SVGElement.h"
+
+namespace WebCore {
+    
+template<typename AnimationFunction>
+class SVGPropertyAnimator : public SVGAttributeAnimator {
+public:
+    bool isDiscrete() const override { return m_function.isDiscrete(); }
+
+    void setFromAndToValues(SVGElement* targetElement, const String& from, const String& to) override
+    {
+        m_function.setFromAndToValues(targetElement, adjustForInheritance(targetElement, from), adjustForInheritance(targetElement, to));
+    }
+
+    void setFromAndByValues(SVGElement* targetElement, const String& from, const String& by) override
+    {
+        m_function.setFromAndByValues(targetElement, from, by);
+    }
+
+    void setToAtEndOfDurationValue(const String& toAtEndOfDuration) override
+    {
+        m_function.setToAtEndOfDurationValue(toAtEndOfDuration);
+    }
+
+protected:
+    template<typename... Arguments>
+    SVGPropertyAnimator(const QualifiedName& attributeName, Arguments&&... arguments)
+        : SVGAttributeAnimator(attributeName)
+        , m_function(std::forward<Arguments>(arguments)...)
+    {
+    }
+
+    void stop(SVGElement* targetElement) override
+    {
+        removeAnimatedStyleProperty(targetElement);
+    }
+
+    float calculateDistance(SVGElement* targetElement, const String& from, const String& to) const override
+    {
+        return m_function.calculateDistance(targetElement, from, to);
+    }
+
+    String adjustForInheritance(SVGElement* targetElement, const String& value) const
+    {
+        static NeverDestroyed<const AtomicString> inherit("inherit", AtomicString::ConstructFromLiteral);
+        return value == inherit ? computeInheritedCSSPropertyValue(targetElement) : value;
+    }
+
+    String computeCSSPropertyValue(SVGElement* targetElement, CSSPropertyID id) const
+    {
+        ASSERT(targetElement);
+
+        // Don't include any properties resulting from CSS Transitions/Animations or SMIL animations, as we want to retrieve the "base value".
+        targetElement->setUseOverrideComputedStyle(true);
+        RefPtr<CSSValue> value = ComputedStyleExtractor(targetElement).propertyValue(id);
+        targetElement->setUseOverrideComputedStyle(false);
+        return value ? value->cssText() : String();
+    }
+
+    String computeInheritedCSSPropertyValue(SVGElement* targetElement) const
+    {
+        ASSERT(targetElement);
+        auto parent = makeRefPtr(targetElement->parentElement());
+        if (!parent || !parent->isSVGElement())
+            return emptyString();
+        
+        SVGElement& svgParent = downcast<SVGElement>(*parent);
+        return computeCSSPropertyValue(&svgParent, cssPropertyID(m_attributeName.localName()));
+    }
+
+    AnimationFunction m_function;
+};
+    
+}
diff --git a/Source/WebCore/svg/properties/SVGPropertyAnimatorFactory.h b/Source/WebCore/svg/properties/SVGPropertyAnimatorFactory.h
new file mode 100644 (file)
index 0000000..a48ef00
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "SVGNames.h"
+#include "SVGPrimitivePropertyAnimatorImpl.h"
+
+namespace WebCore {
+
+class SVGPropertyAnimatorFactory {
+public:
+    SVGPropertyAnimatorFactory() = default;
+
+    static bool isKnownAttribute(const QualifiedName& attributeName)
+    {
+        return attributeAnimatorCreator().contains(attributeName.impl());
+    }
+
+    std::unique_ptr<SVGAttributeAnimator> createAnimator(const QualifiedName& attributeName, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
+    {
+        auto iterator = attributeAnimatorCreator().find(attributeName.impl());
+        if (iterator == attributeAnimatorCreator().end())
+            return nullptr;
+
+        auto addResult = m_attributeProperty.ensure(attributeName, [&iterator]() {
+            return iterator->value.first();
+        });
+        
+        return iterator->value.second(attributeName, addResult.iterator->value.copyRef(), animationMode, calcMode, isAccumulated, isAdditive);
+    }
+
+    void animatorWillBeDeleted(const QualifiedName& attributeName)
+    {
+        auto iterator = m_attributeProperty.find(attributeName);
+        if (iterator == m_attributeProperty.end())
+            return;
+
+        // If refCount = 1 (in the animator) + 1 (in m_attributeProperty) = 2, the entry can be deleted.
+        if (iterator->value->refCount() == 2)
+            m_attributeProperty.remove(iterator);
+    }
+
+private:
+    // This HashMap maps an attribute name to a pair of static methods. The first one creates a shared
+    // Ref<SVGProperty> for the value type of this attribute. The second creates the animator given the
+    // attribute name and the shared Ref<SVGProperty>.
+    using AttributeAnimatorCreator = HashMap<
+        QualifiedName::QualifiedNameImpl*,
+        std::pair<
+            std::function<Ref<SVGProperty>()>,
+            std::function<std::unique_ptr<SVGAttributeAnimator>(const QualifiedName&, Ref<SVGProperty>&&, AnimationMode, CalcMode, bool, bool)>
+        >
+    >;
+
+    static auto createColorAnimator(const QualifiedName& attributeName, Ref<SVGProperty>&& property, AnimationMode animationMode, CalcMode calcMode, bool isAccumulated, bool isAdditive)
+    {
+        return SVGColorAnimator::create(attributeName, WTFMove(property), animationMode, calcMode, isAccumulated, isAdditive);
+    }
+
+    static const AttributeAnimatorCreator& attributeAnimatorCreator()
+    {
+        static NeverDestroyed<AttributeAnimatorCreator> map = AttributeAnimatorCreator({
+            { SVGNames::colorAttr->impl(),          std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+            { SVGNames::fillAttr->impl(),           std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+            { SVGNames::flood_colorAttr->impl(),    std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+            { SVGNames::lighting_colorAttr->impl(), std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+            { SVGNames::stop_colorAttr->impl(),     std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+            { SVGNames::strokeAttr->impl(),         std::make_pair(SVGValueProperty<Color>::create, SVGPropertyAnimatorFactory::createColorAnimator) },
+        });
+        return map;
+    }
+
+    using AttributeProperty = HashMap<QualifiedName, Ref<SVGProperty>>;
+    AttributeProperty m_attributeProperty;
+};
+    
+}