- Revision
- 133074
- Author
- [email protected]
- Date
- 2012-10-31 13:54:27 -0700 (Wed, 31 Oct 2012)
Log Message
Cache animationMode() in SVG animations.
https://bugs.webkit.org/show_bug.cgi?id=99694
Reviewed by Eric Seidel.
Source/WebCore:
This patch caches animationMode() which accounted for 25% of the CPU time of a simple
animation benchmark! This is the 3rd patch for WK99694.
Background: SVGAnimationElement contains most of the shared animation logic for <animate>,
<set>, <animateColor>, <animateTransform>, and <animateMotion>. <animateMotion> is the only
animation element that can depend on other elements in the page. For example:
<path id="mypath" d="M0 0 L 100 100Z"/> <!-- note, can be animated! -->
<rect x="0" y="0" width="100" height="100" fill="green">
<animateMotion dur="6s" repeatCount="indefinite">
<mpath xlink:href=""
</animateMotion>
</rect>
See: http://www.w3.org/TR/SVG/single-page.html#animate-AnimateMotionElement
animationMode depends on several properties of an animation element: the set tag, whether
the animation has a path, and the "values", "to", and "by" attributes. animationMode() was
a hot function for two reasons:
1) hasAttribute(SVGNames::valuesAttr) is expensive because we are unable to use
fastHasAttribute. This is cacheable by simply calculating the animationMode when the
"values" attribute changes.
2) In the <animateMotion> case, determining if a path is empty or changed is expensive.
AnimateMotion can have a path attribute, or it can have <mpath> children that reference
a (possibly non-existent) <path> element elsewhere in the page. Before this patch we did
this path lookup on every animation loop in case something changed. After this patch we
only update AnimateMotion's path when it changes.
A previous patch, http://trac.webkit.org/changeset/132847, laid the groundwork for tracking
<path> changes in <mpath>. This patch adds <mpath> to our resource tracking infrastructure
to track when target <path>s change, instead of looking this up every time.
This refactoring is covered by existing tests.
svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg fails after this patch
because our element dependency tracking has a bug with duplicate ids; see WK99893.
* svg/SVGAnimateMotionElement.cpp:
(WebCore::SVGAnimateMotionElement::parseAttribute):
(WebCore::SVGAnimateMotionElement::updateAnimationPath):
animationPath() has been changed to updateAnimationPath() and should only be called
when the animation path (path attribute, or mpath's referenced path) has changed.
(WebCore::SVGAnimateMotionElement::buildTransformForProgress):
(WebCore::SVGAnimateMotionElement::updateAnimationMode):
If an animationPath exists, we use PathAnimation, otherwise we fall back to the normal
updateAnimationMode() codepath.
(WebCore):
* svg/SVGAnimateMotionElement.h:
(SVGAnimateMotionElement):
* svg/SVGAnimationElement.cpp:
(WebCore::SVGAnimationElement::SVGAnimationElement):
(WebCore::SVGAnimationElement::isSupportedAttribute):
(WebCore::SVGAnimationElement::parseAttribute):
The from, by, and to attributes have been added so that we can track when they change
and update the animation mode. Similarly for when the values attribute changes.
(WebCore::SVGAnimationElement::updateAnimationMode):
* svg/SVGAnimationElement.h:
(WebCore::SVGAnimationElement::animationMode):
(SVGAnimationElement):
(WebCore::SVGAnimationElement::setAnimationMode):
(WebCore::SVGAnimationElement::calculateDistance):
* svg/SVGMPathElement.cpp:
(WebCore::SVGMPathElement::buildPendingResource):
It would be nice to move all the duplicated buildPendingResource() logic into a central
place (SVGURIReference?) but for now it is copied. This function is nearly identical to
SVGFEImageElement::buildPendingResource.
(WebCore):
(WebCore::SVGMPathElement::clearResourceReferences):
(WebCore::SVGMPathElement::insertedInto):
(WebCore::SVGMPathElement::removedFrom):
(WebCore::SVGMPathElement::svgAttributeChanged):
(WebCore::SVGMPathElement::targetPathChanged):
(WebCore::SVGMPathElement::notifyParentOfPathChange):
* svg/SVGMPathElement.h:
(SVGMPathElement):
* svg/SVGPathElement.cpp:
When a <path>'s path changes, we need to notify any dependent <mpath> elements. This is
typically handled with RenderSVGResource::markForLayoutAndParentResourceInvalidation
but for the special-case of <mpath> we only need to track when the path's "d" attribute
changes so invalidateMPathDependencies() has been added.
(WebCore::SVGPathElement::svgAttributeChanged):
(WebCore::SVGPathElement::invalidateMPathDependencies):
(WebCore):
(WebCore::SVGPathElement::insertedInto):
(WebCore::SVGPathElement::removedFrom):
* svg/SVGPathElement.h:
(SVGPathElement):
* svg/SVGSetElement.cpp:
(WebCore::SVGSetElement::SVGSetElement):
(WebCore::SVGSetElement::updateAnimationMode):
(WebCore):
* svg/SVGSetElement.h:
(SVGSetElement):
* svg/animation/SVGSMILElement.cpp:
(WebCore::SVGSMILElement::isSupportedAttribute):
LayoutTests:
This refactoring is covered by existing tests.
svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg fails after this patch
because our element dependency tracking has a bug with duplicate ids; see WK99893.
* platform/chromium/TestExpectations:
* platform/mac/TestExpectations:
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (133073 => 133074)
--- trunk/LayoutTests/ChangeLog 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/LayoutTests/ChangeLog 2012-10-31 20:54:27 UTC (rev 133074)
@@ -1,3 +1,17 @@
+2012-10-31 Philip Rogers <[email protected]>
+
+ Cache animationMode() in SVG animations.
+ https://bugs.webkit.org/show_bug.cgi?id=99694
+
+ Reviewed by Eric Seidel.
+
+ This refactoring is covered by existing tests.
+ svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg fails after this patch
+ because our element dependency tracking has a bug with duplicate ids; see WK99893.
+
+ * platform/chromium/TestExpectations:
+ * platform/mac/TestExpectations:
+
2012-10-31 Stephen White <[email protected]>
[Chromium] Unreviewed gardening. Updating TestExpectations for
Modified: trunk/LayoutTests/platform/chromium/TestExpectations (133073 => 133074)
--- trunk/LayoutTests/platform/chromium/TestExpectations 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/LayoutTests/platform/chromium/TestExpectations 2012-10-31 20:54:27 UTC (rev 133074)
@@ -1321,6 +1321,8 @@
webkit.org/b/83183 [ Mac ] svg/as-image/animated-svg-as-image-no-fixed-intrinsic-size.html [ ImageOnlyFailure Pass ]
+webkit.org/b/99893 svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg [ ImageOnlyFailure ]
+
# Appears to be failing on Skia platforms
webkit.org/b/83199 svg/filters/big-sized-filter.svg [ ImageOnlyFailure Pass ]
Modified: trunk/LayoutTests/platform/efl/TestExpectations (133073 => 133074)
--- trunk/LayoutTests/platform/efl/TestExpectations 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/LayoutTests/platform/efl/TestExpectations 2012-10-31 20:54:27 UTC (rev 133074)
@@ -980,6 +980,8 @@
webkit.org/b/98651 svg/text/non-bmp-positioning-lists.svg [ Skip ]
webkit.org/b/98653 svg/text/lengthAdjust-text-metrics.html [ Failure ]
+webkit.org/b/99893 svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg [ ImageOnlyFailure ]
+
webkit.org/b/98718 svg/animations/animate-css-xml-attributeType.html [ Failure Pass ]
# EFL's TestRunner does not implement enableAutoResizeMode
Modified: trunk/LayoutTests/platform/mac/TestExpectations (133073 => 133074)
--- trunk/LayoutTests/platform/mac/TestExpectations 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2012-10-31 20:54:27 UTC (rev 133074)
@@ -1170,6 +1170,8 @@
webkit.org/b/85408 svg/batik/text/longTextOnPath.svg [ Failure Pass ]
+webkit.org/b/99893 svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg [ ImageOnlyFailure ]
+
# Need rebaseline after https://bugs.webkit.org/show_bug.cgi?id=89116
webkit.org/b/89116 svg/W3C-SVG-1.1/filters-specular-01-f.svg [ ImageOnlyFailure Pass ]
webkit.org/b/89116 svg/dynamic-updates/SVGFESpecularLightingElement-dom-in-attr.html [ ImageOnlyFailure Pass ]
Modified: trunk/LayoutTests/platform/qt/TestExpectations (133073 => 133074)
--- trunk/LayoutTests/platform/qt/TestExpectations 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/LayoutTests/platform/qt/TestExpectations 2012-10-31 20:54:27 UTC (rev 133074)
@@ -2486,6 +2486,8 @@
webkit.org/b/98525 plugins/resize-from-plugin.html
webkit.org/b/98640 plugins/refcount-leaks.html
+webkit.org/b/99893 svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg [ ImageOnlyFailure ]
+
# New inspector/profiler/memory-instrumentation-canvas.html fails on JSC platforms
webkit.org/b/99001 inspector/profiler/memory-instrumentation-canvas.html
Modified: trunk/Source/WebCore/ChangeLog (133073 => 133074)
--- trunk/Source/WebCore/ChangeLog 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/ChangeLog 2012-10-31 20:54:27 UTC (rev 133074)
@@ -1,3 +1,113 @@
+2012-10-31 Philip Rogers <[email protected]>
+
+ Cache animationMode() in SVG animations.
+ https://bugs.webkit.org/show_bug.cgi?id=99694
+
+ Reviewed by Eric Seidel.
+
+ This patch caches animationMode() which accounted for 25% of the CPU time of a simple
+ animation benchmark! This is the 3rd patch for WK99694.
+
+ Background: SVGAnimationElement contains most of the shared animation logic for <animate>,
+ <set>, <animateColor>, <animateTransform>, and <animateMotion>. <animateMotion> is the only
+ animation element that can depend on other elements in the page. For example:
+ <path id="mypath" d="M0 0 L 100 100Z"/> <!-- note, can be animated! -->
+ <rect x="0" y="0" width="100" height="100" fill="green">
+ <animateMotion dur="6s" repeatCount="indefinite">
+ <mpath xlink:href=""
+ </animateMotion>
+ </rect>
+ See: http://www.w3.org/TR/SVG/single-page.html#animate-AnimateMotionElement
+
+ animationMode depends on several properties of an animation element: the set tag, whether
+ the animation has a path, and the "values", "to", and "by" attributes. animationMode() was
+ a hot function for two reasons:
+ 1) hasAttribute(SVGNames::valuesAttr) is expensive because we are unable to use
+ fastHasAttribute. This is cacheable by simply calculating the animationMode when the
+ "values" attribute changes.
+ 2) In the <animateMotion> case, determining if a path is empty or changed is expensive.
+ AnimateMotion can have a path attribute, or it can have <mpath> children that reference
+ a (possibly non-existent) <path> element elsewhere in the page. Before this patch we did
+ this path lookup on every animation loop in case something changed. After this patch we
+ only update AnimateMotion's path when it changes.
+
+ A previous patch, http://trac.webkit.org/changeset/132847, laid the groundwork for tracking
+ <path> changes in <mpath>. This patch adds <mpath> to our resource tracking infrastructure
+ to track when target <path>s change, instead of looking this up every time.
+
+ This refactoring is covered by existing tests.
+ svg/animations/mozilla/animateMotion-mpath-targetChange-1.svg fails after this patch
+ because our element dependency tracking has a bug with duplicate ids; see WK99893.
+
+ * svg/SVGAnimateMotionElement.cpp:
+ (WebCore::SVGAnimateMotionElement::parseAttribute):
+ (WebCore::SVGAnimateMotionElement::updateAnimationPath):
+
+ animationPath() has been changed to updateAnimationPath() and should only be called
+ when the animation path (path attribute, or mpath's referenced path) has changed.
+
+ (WebCore::SVGAnimateMotionElement::buildTransformForProgress):
+ (WebCore::SVGAnimateMotionElement::updateAnimationMode):
+
+ If an animationPath exists, we use PathAnimation, otherwise we fall back to the normal
+ updateAnimationMode() codepath.
+
+ (WebCore):
+ * svg/SVGAnimateMotionElement.h:
+ (SVGAnimateMotionElement):
+ * svg/SVGAnimationElement.cpp:
+ (WebCore::SVGAnimationElement::SVGAnimationElement):
+ (WebCore::SVGAnimationElement::isSupportedAttribute):
+ (WebCore::SVGAnimationElement::parseAttribute):
+
+ The from, by, and to attributes have been added so that we can track when they change
+ and update the animation mode. Similarly for when the values attribute changes.
+
+ (WebCore::SVGAnimationElement::updateAnimationMode):
+ * svg/SVGAnimationElement.h:
+ (WebCore::SVGAnimationElement::animationMode):
+ (SVGAnimationElement):
+ (WebCore::SVGAnimationElement::setAnimationMode):
+ (WebCore::SVGAnimationElement::calculateDistance):
+ * svg/SVGMPathElement.cpp:
+ (WebCore::SVGMPathElement::buildPendingResource):
+
+ It would be nice to move all the duplicated buildPendingResource() logic into a central
+ place (SVGURIReference?) but for now it is copied. This function is nearly identical to
+ SVGFEImageElement::buildPendingResource.
+
+ (WebCore):
+ (WebCore::SVGMPathElement::clearResourceReferences):
+ (WebCore::SVGMPathElement::insertedInto):
+ (WebCore::SVGMPathElement::removedFrom):
+ (WebCore::SVGMPathElement::svgAttributeChanged):
+ (WebCore::SVGMPathElement::targetPathChanged):
+ (WebCore::SVGMPathElement::notifyParentOfPathChange):
+ * svg/SVGMPathElement.h:
+ (SVGMPathElement):
+ * svg/SVGPathElement.cpp:
+
+ When a <path>'s path changes, we need to notify any dependent <mpath> elements. This is
+ typically handled with RenderSVGResource::markForLayoutAndParentResourceInvalidation
+ but for the special-case of <mpath> we only need to track when the path's "d" attribute
+ changes so invalidateMPathDependencies() has been added.
+
+ (WebCore::SVGPathElement::svgAttributeChanged):
+ (WebCore::SVGPathElement::invalidateMPathDependencies):
+ (WebCore):
+ (WebCore::SVGPathElement::insertedInto):
+ (WebCore::SVGPathElement::removedFrom):
+ * svg/SVGPathElement.h:
+ (SVGPathElement):
+ * svg/SVGSetElement.cpp:
+ (WebCore::SVGSetElement::SVGSetElement):
+ (WebCore::SVGSetElement::updateAnimationMode):
+ (WebCore):
+ * svg/SVGSetElement.h:
+ (SVGSetElement):
+ * svg/animation/SVGSMILElement.cpp:
+ (WebCore::SVGSMILElement::isSupportedAttribute):
+
2012-10-31 Beth Dakin <[email protected]>
https://bugs.webkit.org/show_bug.cgi?id=100879
Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGAnimateMotionElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -112,6 +112,7 @@
if (attribute.name() == SVGNames::pathAttr) {
m_path = Path();
buildPathFromString(attribute.value(), m_path);
+ updateAnimationPath();
return;
}
@@ -130,21 +131,27 @@
return RotateAngle;
}
-Path SVGAnimateMotionElement::animationPath() const
+void SVGAnimateMotionElement::updateAnimationPath()
{
+ m_animationPath = Path();
+ bool foundMPath = false;
+
for (Node* child = firstChild(); child; child = child->nextSibling()) {
if (child->hasTagName(SVGNames::mpathTag)) {
SVGMPathElement* mPath = static_cast<SVGMPathElement*>(child);
SVGPathElement* pathElement = mPath->pathElement();
- Path path;
- if (pathElement)
- updatePathFromGraphicsElement(pathElement, path);
- return path;
+ if (pathElement) {
+ updatePathFromGraphicsElement(pathElement, m_animationPath);
+ foundMPath = true;
+ break;
+ }
}
}
- if (fastHasAttribute(SVGNames::pathAttr))
- return m_path;
- return Path();
+
+ if (!foundMPath && fastHasAttribute(SVGNames::pathAttr))
+ m_animationPath = m_path;
+
+ updateAnimationMode();
}
static bool parsePoint(const String& s, FloatPoint& point)
@@ -219,19 +226,18 @@
void SVGAnimateMotionElement::buildTransformForProgress(AffineTransform* transform, float percentage)
{
- Path path = animationPath();
- ASSERT(!path.isEmpty());
+ ASSERT(!m_animationPath.isEmpty());
bool ok = false;
- float positionOnPath = path.length() * percentage;
- FloatPoint position = path.pointAtLength(positionOnPath, ok);
+ float positionOnPath = m_animationPath.length() * percentage;
+ FloatPoint position = m_animationPath.pointAtLength(positionOnPath, ok);
if (!ok)
return;
transform->translate(position.x(), position.y());
RotateMode rotateMode = this->rotateMode();
if (rotateMode != RotateAuto && rotateMode != RotateAutoReverse)
return;
- float angle = path.normalAngleAtLength(positionOnPath, ok);
+ float angle = m_animationPath.normalAngleAtLength(positionOnPath, ok);
if (rotateMode == RotateAutoReverse)
angle += 180;
transform->rotate(angle);
@@ -319,5 +325,13 @@
return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
}
+void SVGAnimateMotionElement::updateAnimationMode()
+{
+ if (!m_animationPath.isEmpty())
+ setAnimationMode(PathAnimation);
+ else
+ SVGAnimationElement::updateAnimationMode();
}
+
+}
#endif // ENABLE(SVG)
Modified: trunk/Source/WebCore/svg/SVGAnimateMotionElement.h (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGAnimateMotionElement.h 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGAnimateMotionElement.h 2012-10-31 20:54:27 UTC (rev 133074)
@@ -30,6 +30,7 @@
class SVGAnimateMotionElement : public SVGAnimationElement {
public:
static PassRefPtr<SVGAnimateMotionElement> create(const QualifiedName&, Document*);
+ void updateAnimationPath();
private:
SVGAnimateMotionElement(const QualifiedName&, Document*);
@@ -48,7 +49,6 @@
virtual void calculateAnimatedValue(float percentage, unsigned repeatCount, SVGSMILElement* resultElement);
virtual void applyResultsToTarget();
virtual float calculateDistance(const String& fromString, const String& toString);
- virtual Path animationPath() const;
enum RotateMode {
RotateAngle,
@@ -60,12 +60,15 @@
bool m_hasToPointAtEndOfDuration;
+ virtual void updateAnimationMode() OVERRIDE;
+
// Note: we do not support percentage values for to/from coords as the spec implies we should (opera doesn't either)
FloatPoint m_fromPoint;
FloatPoint m_toPoint;
FloatPoint m_toPointAtEndOfDuration;
Path m_path;
+ Path m_animationPath;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/svg/SVGAnimationElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGAnimationElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGAnimationElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -59,6 +59,7 @@
, m_attributeType(AttributeTypeAuto)
, m_hasInvalidCSSAttributeType(false)
, m_calcMode(CalcModeLinear)
+ , m_animationMode(NoAnimation)
{
registerAnimatedPropertiesForSVGAnimationElement();
}
@@ -151,6 +152,9 @@
supportedAttributes.add(SVGNames::keySplinesAttr);
supportedAttributes.add(SVGNames::attributeTypeAttr);
supportedAttributes.add(SVGNames::calcModeAttr);
+ supportedAttributes.add(SVGNames::fromAttr);
+ supportedAttributes.add(SVGNames::toAttr);
+ supportedAttributes.add(SVGNames::byAttr);
}
return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
}
@@ -169,6 +173,8 @@
attribute.value().string().split(';', m_values);
for (unsigned i = 0; i < m_values.size(); ++i)
m_values[i] = m_values[i].stripWhiteSpace();
+
+ updateAnimationMode();
return;
}
@@ -201,6 +207,11 @@
return;
}
+ if (attribute.name() == SVGNames::fromAttr || attribute.name() == SVGNames::toAttr || attribute.name() == SVGNames::byAttr) {
+ updateAnimationMode();
+ return;
+ }
+
if (SVGTests::parseAttribute(attribute))
return;
if (SVGExternalResourcesRequired::parseAttribute(attribute))
@@ -267,20 +278,17 @@
addEndTime(elapsed, elapsed + offset, SMILTimeWithOrigin::ScriptOrigin);
}
-AnimationMode SVGAnimationElement::animationMode() const
+void SVGAnimationElement::updateAnimationMode()
{
// http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues
- if (hasTagName(SVGNames::setTag))
- return ToAnimation;
- if (!animationPath().isEmpty())
- return PathAnimation;
if (hasAttribute(SVGNames::valuesAttr))
- return ValuesAnimation;
- if (!toValue().isEmpty())
- return fromValue().isEmpty() ? ToAnimation : FromToAnimation;
- if (!byValue().isEmpty())
- return fromValue().isEmpty() ? ByAnimation : FromByAnimation;
- return NoAnimation;
+ setAnimationMode(ValuesAnimation);
+ else if (!toValue().isEmpty())
+ setAnimationMode(fromValue().isEmpty() ? ToAnimation : FromToAnimation);
+ else if (!byValue().isEmpty())
+ setAnimationMode(fromValue().isEmpty() ? ByAnimation : FromByAnimation);
+ else
+ setAnimationMode(NoAnimation);
}
void SVGAnimationElement::setCalcMode(const AtomicString& calcMode)
Modified: trunk/Source/WebCore/svg/SVGAnimationElement.h (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGAnimationElement.h 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGAnimationElement.h 2012-10-31 20:54:27 UTC (rev 133074)
@@ -27,7 +27,6 @@
#if ENABLE(SVG)
#include "ElementTimeControl.h"
-#include "Path.h"
#include "SMILTime.h"
#include "SVGAnimatedBoolean.h"
#include "SVGExternalResourcesRequired.h"
@@ -87,7 +86,7 @@
virtual bool isAdditive() const;
bool isAccumulated() const;
- AnimationMode animationMode() const;
+ AnimationMode animationMode() const { return m_animationMode; }
CalcMode calcMode() const { return m_calcMode; }
enum ShouldApplyAnimation {
@@ -201,6 +200,8 @@
virtual void targetElementWillChange(SVGElement* currentTarget, SVGElement* oldTarget) OVERRIDE;
bool hasInvalidCSSAttributeType() const { return m_hasInvalidCSSAttributeType; }
+ virtual void updateAnimationMode();
+ void setAnimationMode(AnimationMode animationMode) { m_animationMode = animationMode; }
void setCalcMode(CalcMode calcMode) { m_calcMode = calcMode; }
private:
@@ -215,7 +216,6 @@
virtual bool calculateFromAndByValues(const String& fromString, const String& byString) = 0;
virtual void calculateAnimatedValue(float percent, unsigned repeatCount, SVGSMILElement* resultElement) = 0;
virtual float calculateDistance(const String& /*fromString*/, const String& /*toString*/) { return -1.f; }
- virtual Path animationPath() const { return Path(); }
void currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to);
void calculateKeyTimesForCalcModePaced();
@@ -250,6 +250,7 @@
String m_lastValuesAnimationTo;
bool m_hasInvalidCSSAttributeType;
CalcMode m_calcMode;
+ AnimationMode m_animationMode;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/svg/SVGMPathElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGMPathElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGMPathElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -23,6 +23,7 @@
#include "SVGMPathElement.h"
#include "Document.h"
+#include "SVGAnimateMotionElement.h"
#include "SVGNames.h"
#include "SVGPathElement.h"
@@ -49,6 +50,53 @@
return adoptRef(new SVGMPathElement(tagName, document));
}
+void SVGMPathElement::buildPendingResource()
+{
+ clearResourceReferences();
+ if (!inDocument())
+ return;
+
+ String id;
+ Element* target = SVGURIReference::targetElementFromIRIString(href(), document(), &id);
+ if (!target) {
+ if (hasPendingResources())
+ return;
+
+ if (!id.isEmpty()) {
+ document()->accessSVGExtensions()->addPendingResource(id, this);
+ ASSERT(hasPendingResources());
+ }
+ } else if (target->isSVGElement()) {
+ // Register us with the target in the dependencies map. Any change of hrefElement
+ // that leads to relayout/repainting now informs us, so we can react to it.
+ document()->accessSVGExtensions()->addElementReferencingTarget(this, static_cast<SVGElement*>(target));
+ }
+
+ targetPathChanged();
+}
+
+void SVGMPathElement::clearResourceReferences()
+{
+ ASSERT(document());
+ document()->accessSVGExtensions()->removeAllTargetReferencesForElement(this);
+}
+
+Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent)
+{
+ SVGElement::insertedInto(rootParent);
+ if (rootParent->inDocument())
+ buildPendingResource();
+ return InsertionDone;
+}
+
+void SVGMPathElement::removedFrom(ContainerNode* rootParent)
+{
+ SVGElement::removedFrom(rootParent);
+ notifyParentOfPathChange(rootParent);
+ if (rootParent->inDocument())
+ clearResourceReferences();
+}
+
bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName)
{
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
@@ -74,6 +122,26 @@
ASSERT_NOT_REACHED();
}
+void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName)
+{
+ if (!isSupportedAttribute(attrName)) {
+ SVGElement::svgAttributeChanged(attrName);
+ return;
+ }
+
+ SVGElementInstance::InvalidationGuard invalidationGuard(this);
+
+ if (SVGURIReference::isKnownAttribute(attrName)) {
+ buildPendingResource();
+ return;
+ }
+
+ if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
+ return;
+
+ ASSERT_NOT_REACHED();
+}
+
SVGPathElement* SVGMPathElement::pathElement()
{
Element* target = targetElementFromIRIString(href(), document());
@@ -82,6 +150,17 @@
return 0;
}
+void SVGMPathElement::targetPathChanged()
+{
+ notifyParentOfPathChange(parentNode());
+}
+
+void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent)
+{
+ if (parent && parent->hasTagName(SVGNames::animateMotionTag))
+ static_cast<SVGAnimateMotionElement*>(parent)->updateAnimationPath();
+}
+
} // namespace WebCore
#endif // ENABLE(SVG)
Modified: trunk/Source/WebCore/svg/SVGMPathElement.h (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGMPathElement.h 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGMPathElement.h 2012-10-31 20:54:27 UTC (rev 133074)
@@ -23,6 +23,7 @@
#if ENABLE(SVG)
#include "SVGAnimatedBoolean.h"
#include "SVGAnimatedString.h"
+#include "SVGDocumentExtensions.h"
#include "SVGExternalResourcesRequired.h"
#include "SVGURIReference.h"
@@ -37,14 +38,23 @@
static PassRefPtr<SVGMPathElement> create(const QualifiedName&, Document*);
SVGPathElement* pathElement();
-
+
+ void targetPathChanged();
+
private:
SVGMPathElement(const QualifiedName&, Document*);
- // FIXME: svgAttributeChanged missing.
+ void buildPendingResource();
+ void clearResourceReferences();
+ virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+ void removedFrom(ContainerNode*);
+
bool isSupportedAttribute(const QualifiedName&);
virtual void parseAttribute(const Attribute&) OVERRIDE;
+ virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
+ void notifyParentOfPathChange(ContainerNode*);
+
BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGMPathElement)
DECLARE_ANIMATED_STRING(Href, href)
DECLARE_ANIMATED_BOOLEAN(ExternalResourcesRequired, externalResourcesRequired)
Modified: trunk/Source/WebCore/svg/SVGPathElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGPathElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGPathElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -27,6 +27,7 @@
#include "RenderSVGPath.h"
#include "RenderSVGResource.h"
#include "SVGElementInstance.h"
+#include "SVGMPathElement.h"
#include "SVGNames.h"
#include "SVGPathSegArc.h"
#include "SVGPathSegClosePath.h"
@@ -270,12 +271,41 @@
if (renderer)
renderer->setNeedsShapeUpdate();
+
+ invalidateMPathDependencies();
}
if (renderer)
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
}
+void SVGPathElement::invalidateMPathDependencies()
+{
+ // <mpath> can only reference <path> but this dependency is not handled in
+ // markForLayoutAndParentResourceInvalidation so we update any mpath dependencies manually.
+ ASSERT(document());
+ if (HashSet<SVGElement*>* dependencies = document()->accessSVGExtensions()->setOfElementsReferencingTarget(this)) {
+ HashSet<SVGElement*>::iterator end = dependencies->end();
+ for (HashSet<SVGElement*>::iterator it = dependencies->begin(); it != end; ++it) {
+ if ((*it)->hasTagName(SVGNames::mpathTag))
+ static_cast<SVGMPathElement*>(*it)->targetPathChanged();
+ }
+ }
+}
+
+Node::InsertionNotificationRequest SVGPathElement::insertedInto(ContainerNode* rootParent)
+{
+ SVGStyledTransformableElement::insertedInto(rootParent);
+ invalidateMPathDependencies();
+ return InsertionDone;
+}
+
+void SVGPathElement::removedFrom(ContainerNode* rootParent)
+{
+ SVGStyledTransformableElement::removedFrom(rootParent);
+ invalidateMPathDependencies();
+}
+
SVGPathByteStream* SVGPathElement::pathByteStream() const
{
SVGAnimatedProperty* property = SVGAnimatedProperty::lookupWrapper<SVGPathElement, SVGAnimatedPathSegListPropertyTearOff>(this, dPropertyInfo());
Modified: trunk/Source/WebCore/svg/SVGPathElement.h (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGPathElement.h 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGPathElement.h 2012-10-31 20:54:27 UTC (rev 133074)
@@ -128,6 +128,11 @@
RenderObject* createRenderer(RenderArena*, RenderStyle*);
+ virtual Node::InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
+ virtual void removedFrom(ContainerNode*) OVERRIDE;
+
+ void invalidateMPathDependencies();
+
private:
OwnPtr<SVGPathByteStream> m_pathByteStream;
mutable SVGSynchronizableAnimatedProperty<SVGPathSegList> m_pathSegList;
Modified: trunk/Source/WebCore/svg/SVGSetElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGSetElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGSetElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -28,6 +28,7 @@
inline SVGSetElement::SVGSetElement(const QualifiedName& tagName, Document* document)
: SVGAnimateElement(tagName, document)
{
+ setAnimationMode(ToAnimation);
ASSERT(hasTagName(SVGNames::setTag));
}
@@ -36,8 +37,14 @@
return adoptRef(new SVGSetElement(tagName, document));
}
+void SVGSetElement::updateAnimationMode()
+{
+ // No-op, as <set> has a constant animation mode of ToAnimation.
+ // See: http://www.w3.org/TR/SVG/single-page.html#animate-SetElement
}
+}
+
// vim:ts=4:noet
#endif // ENABLE(SVG)
Modified: trunk/Source/WebCore/svg/SVGSetElement.h (133073 => 133074)
--- trunk/Source/WebCore/svg/SVGSetElement.h 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/SVGSetElement.h 2012-10-31 20:54:27 UTC (rev 133074)
@@ -33,6 +33,7 @@
private:
SVGSetElement(const QualifiedName&, Document*);
+ virtual void updateAnimationMode() OVERRIDE;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp (133073 => 133074)
--- trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp 2012-10-31 20:49:22 UTC (rev 133073)
+++ trunk/Source/WebCore/svg/animation/SVGSMILElement.cpp 2012-10-31 20:54:27 UTC (rev 133074)
@@ -421,9 +421,6 @@
supportedAttributes.add(SVGNames::minAttr);
supportedAttributes.add(SVGNames::maxAttr);
supportedAttributes.add(SVGNames::attributeNameAttr);
- supportedAttributes.add(SVGNames::fromAttr);
- supportedAttributes.add(SVGNames::toAttr);
- supportedAttributes.add(SVGNames::byAttr);
supportedAttributes.add(XLinkNames::hrefAttr);
}
return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);