15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGAnimateMotionElement.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/SVGNames.h"
27197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/ElementTraversal.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderObject.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResource.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGPathData.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGMPathElement.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGParserUtilities.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGPathElement.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGPathUtilities.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
36f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/MathExtras.h"
37f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/StdLibExtras.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
4002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace SVGNames;
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)inline SVGAnimateMotionElement::SVGAnimateMotionElement(Document& document)
4451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    : SVGAnimationElement(animateMotionTag, document)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_hasToPointAtEndOfDuration(false)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setCalcMode(CalcModePaced);
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)DEFINE_NODE_FACTORY(SVGAnimateMotionElement)
515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
52f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)SVGAnimateMotionElement::~SVGAnimateMotionElement()
53f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
54f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
55f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimateMotionElement::hasValidAttributeType()
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement* targetElement = this->targetElement();
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!targetElement)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We don't have a special attribute name to verify the animation type. Check the element name instead.
63591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!targetElement->isSVGGraphicsElement())
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: SVG 1.1 section 19.2.15
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: svgTag is missing. Needs to be checked, if transforming <svg> could cause problems.
67d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return (isSVGGElement(*targetElement)
68d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGDefsElement(*targetElement)
69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGUseElement(*targetElement)
70d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGImageElement(*targetElement)
71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGSwitchElement(*targetElement)
72d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGPathElement(*targetElement)
73d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGRectElement(*targetElement)
74d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGCircleElement(*targetElement)
75d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGEllipseElement(*targetElement)
76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGLineElement(*targetElement)
77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGPolylineElement(*targetElement)
78d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGPolygonElement(*targetElement)
79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGTextElement(*targetElement)
80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGClipPathElement(*targetElement)
81d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGMaskElement(*targetElement)
82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGAElement(*targetElement)
83d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        || isSVGForeignObjectElement(*targetElement)
84d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        );
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimateMotionElement::hasValidAttributeName()
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // AnimateMotion does not use attributeName so it is always valid.
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGAnimateMotionElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::pathAttr) {
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_path = Path();
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        buildPathFromString(value, m_path);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateAnimationPath();
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SVGAnimationElement::parseAttribute(name, value);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGAnimateMotionElement::RotateMode SVGAnimateMotionElement::rotateMode() const
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, autoVal, ("auto", AtomicString::ConstructFromLiteral));
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, autoReverse, ("auto-reverse", AtomicString::ConstructFromLiteral));
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& rotate = getAttribute(SVGNames::rotateAttr);
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rotate == autoVal)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return RotateAuto;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rotate == autoReverse)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return RotateAutoReverse;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return RotateAngle;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::updateAnimationPath()
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationPath = Path();
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool foundMPath = false;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (SVGMPathElement* mpath = Traversal<SVGMPathElement>::firstChild(*this); mpath; mpath = Traversal<SVGMPathElement>::nextSibling(*mpath)) {
123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (SVGPathElement* pathElement = mpath->pathElement()) {
124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            updatePathFromGraphicsElement(pathElement, m_animationPath);
125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            foundMPath = true;
126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!foundMPath && fastHasAttribute(SVGNames::pathAttr))
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationPath = m_path;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateAnimationMode();
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochtemplate<typename CharType>
137591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool parsePointInternal(const String& string, FloatPoint& point)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const CharType* ptr = string.getCharacters<CharType>();
140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const CharType* end = ptr + string.length();
14102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!skipOptionalSVGSpaces(ptr, end))
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
14402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float x = 0;
146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!parseNumber(ptr, end, x))
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
14802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float y = 0;
150591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!parseNumber(ptr, end, y))
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
15202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    point = FloatPoint(x, y);
15402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // disallow anything except spaces at the end
156591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return !skipOptionalSVGSpaces(ptr, end);
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
158591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
159591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool parsePoint(const String& string, FloatPoint& point)
160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (string.isEmpty())
162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return false;
163591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (string.is8Bit())
164591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return parsePointInternal<LChar>(string, point);
165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return parsePointInternal<UChar>(string, point);
166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
167591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::resetAnimatedType()
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasValidAttributeType())
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement* targetElement = this->targetElement();
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!targetElement)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (AffineTransform* transform = targetElement->supplementalTransform())
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        transform->makeIdentity();
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::clearAnimatedType(SVGElement* targetElement)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!targetElement)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
183f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
184f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    AffineTransform* transform = targetElement->supplementalTransform();
185f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (!transform)
186f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return;
187f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
188f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    transform->makeIdentity();
189f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
190f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (RenderObject* targetRenderer = targetElement->renderer()) {
191f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        targetRenderer->setNeedsTransformUpdate();
192f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        RenderSVGResource::markForLayoutAndParentResourceInvalidation(targetRenderer);
193f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    }
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimateMotionElement::calculateToAtEndOfDurationValue(const String& toAtEndOfDurationString)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parsePoint(toAtEndOfDurationString, m_toPointAtEndOfDuration);
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_hasToPointAtEndOfDuration = true;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimateMotionElement::calculateFromAndToValues(const String& fromString, const String& toString)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_hasToPointAtEndOfDuration = false;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parsePoint(fromString, m_fromPoint);
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parsePoint(toString, m_toPoint);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
21002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimateMotionElement::calculateFromAndByValues(const String& fromString, const String& byString)
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_hasToPointAtEndOfDuration = false;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationMode() == ByAnimation && !isAdditive())
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parsePoint(fromString, m_fromPoint);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint byPoint;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parsePoint(byString, byPoint);
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_toPoint = FloatPoint(m_fromPoint.x() + byPoint.x(), m_fromPoint.y() + byPoint.y());
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGSMILElement*)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement* targetElement = this->targetElement();
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!targetElement)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform* transform = targetElement->supplementalTransform();
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!transform)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderObject* targetRenderer = targetElement->renderer())
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        targetRenderer->setNeedsTransformUpdate();
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isAdditive())
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        transform->makeIdentity();
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationMode() != PathAnimation) {
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatPoint toPointAtEndOfDuration = m_toPoint;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isAccumulated() && repeatCount && m_hasToPointAtEndOfDuration)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            toPointAtEndOfDuration = m_toPointAtEndOfDuration;
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float animatedX = 0;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animateAdditiveNumber(percentage, repeatCount, m_fromPoint.x(), m_toPoint.x(), toPointAtEndOfDuration.x(), animatedX);
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float animatedY = 0;
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animateAdditiveNumber(percentage, repeatCount, m_fromPoint.y(), m_toPoint.y(), toPointAtEndOfDuration.y(), animatedY);
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        transform->translate(animatedX, animatedY);
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    ASSERT(!m_animationPath.isEmpty());
2540019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch
2550019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    float positionOnPath = m_animationPath.length() * percentage;
2567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    FloatPoint position;
2577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    float angle;
25809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool ok = m_animationPath.pointAndNormalAtLength(positionOnPath, position, angle);
2590019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    if (!ok)
2600019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        return;
2617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // Handle accumulate="sum".
2637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    if (isAccumulated() && repeatCount) {
2647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        FloatPoint positionAtEndOfDuration = m_animationPath.pointAtLength(m_animationPath.length(), ok);
2657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (ok)
2667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            position.move(positionAtEndOfDuration.x() * repeatCount, positionAtEndOfDuration.y() * repeatCount);
2677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    }
2687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    transform->translate(position.x(), position.y());
2700019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    RotateMode rotateMode = this->rotateMode();
2710019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    if (rotateMode != RotateAuto && rotateMode != RotateAutoReverse)
2720019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        return;
2730019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    if (rotateMode == RotateAutoReverse)
2740019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch        angle += 180;
2750019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    transform->rotate(angle);
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::applyResultsToTarget()
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We accumulate to the target element transform list so there is not much to do here.
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement* targetElement = this->targetElement();
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!targetElement)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderObject* renderer = targetElement->renderer())
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform* t = targetElement->supplementalTransform();
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!t)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ...except in case where we have additional instances in <use> trees.
293323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instances = targetElement->instancesForElement();
294323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = instances.end();
295323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = instances.begin(); it != end; ++it) {
296323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        SVGElement* shadowTreeElement = *it;
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(shadowTreeElement);
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        AffineTransform* transform = shadowTreeElement->supplementalTransform();
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!transform)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f());
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (RenderObject* renderer = shadowTreeElement->renderer()) {
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            renderer->setNeedsTransformUpdate();
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimateMotionElement::calculateDistance(const String& fromString, const String& toString)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint from;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint to;
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parsePoint(fromString, from))
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -1;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parsePoint(toString, to))
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -1;
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize diff = to - from;
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimateMotionElement::updateAnimationMode()
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_animationPath.isEmpty())
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAnimationMode(PathAnimation);
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGAnimationElement::updateAnimationMode();
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
330