18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2007 Rob Buis <buis@kde.org>
4dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2008 Apple Inc. All rights reserved.
5dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
6dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is free software; you can redistribute it and/or
7dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * modify it under the terms of the GNU Library General Public
8dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * License as published by the Free Software Foundation; either
9dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * version 2 of the License, or (at your option) any later version.
10dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
11dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is distributed in the hope that it will be useful,
12dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of
13dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Library General Public License for more details.
15dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch *
16dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * You should have received a copy of the GNU Library General Public License
17dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * along with this library; see the file COPYING.LIB.  If not, write to
18dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Boston, MA 02110-1301, USA.
20dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch */
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG) && ENABLE(SVG_ANIMATION)
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGAnimateMotionElement.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
27e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "Attribute.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderObject.h"
29967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#include "RenderSVGResource.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGElementInstance.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGMPathElement.h"
32f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGParserUtilities.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGPathElement.h"
35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGPathParserFactory.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGTransformList.h"
37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <wtf/MathExtras.h>
38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h>
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace SVGNames;
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monseninline SVGAnimateMotionElement::SVGAnimateMotionElement(const QualifiedName& tagName, Document* document)
455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    : SVGAnimationElement(tagName, document)
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_baseIndexInTransformList(0)
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_angle(0)
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenPassRefPtr<SVGAnimateMotionElement> SVGAnimateMotionElement::create(const QualifiedName& tagName, Document* document)
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return adoptRef(new SVGAnimateMotionElement(tagName, document));
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool SVGAnimateMotionElement::hasValidAttributeType() const
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGElement* targetElement = this->targetElement();
5981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!targetElement)
6081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return false;
6181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
6281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // We don't have a special attribute name to verify the animation type. Check the element name instead.
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!targetElement->isStyledTransformable() && !targetElement->hasTagName(SVGNames::textTag))
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Spec: SVG 1.1 section 19.2.15
6681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: svgTag is missing. Needs to be checked, if transforming <svg> could cause problems.
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (targetElement->hasTagName(gTag)
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(defsTag)
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(useTag)
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(imageTag)
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(switchTag)
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(pathTag)
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(rectTag)
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(circleTag)
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(ellipseTag)
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(lineTag)
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(polylineTag)
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(polygonTag)
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(textTag)
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(clipPathTag)
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(maskTag)
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(aTag)
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG_FOREIGN_OBJECT)
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        || targetElement->hasTagName(foreignObjectTag)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        )
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
91e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid SVGAnimateMotionElement::parseMappedAttribute(Attribute* attr)
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (attr->name() == SVGNames::pathAttr) {
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_path = Path();
95dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        SVGPathParserFactory* factory = SVGPathParserFactory::self();
96dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        factory->buildPathFromString(attr->value(), m_path);
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGAnimationElement::parseMappedAttribute(attr);
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGAnimateMotionElement::RotateMode SVGAnimateMotionElement::rotateMode() const
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(const AtomicString, autoVal, ("auto"));
104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(const AtomicString, autoReverse, ("auto-reverse"));
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String rotate = getAttribute(SVGNames::rotateAttr);
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (rotate == autoVal)
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return RotateAuto;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (rotate == autoReverse)
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return RotateAutoReverse;
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return RotateAngle;
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPath SVGAnimateMotionElement::animationPath() const
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (Node* child = firstChild(); child; child = child->nextSibling()) {
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (child->hasTagName(SVGNames::mpathTag)) {
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            SVGMPathElement* mPath = static_cast<SVGMPathElement*>(child);
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            SVGPathElement* pathElement = mPath->pathElement();
119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            Path path;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (pathElement)
121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                pathElement->toPathData(path);
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return path;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hasAttribute(SVGNames::pathAttr))
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_path;
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return Path();
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool parsePoint(const String& s, FloatPoint& point)
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (s.isEmpty())
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* cur = s.characters();
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const UChar* end = cur + s.length();
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!skipOptionalSpaces(cur, end))
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float x = 0;
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parseNumber(cur, end, x))
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    float y = 0;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parseNumber(cur, end, y))
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    point = FloatPoint(x, y);
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // disallow anything except spaces at the end
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !skipOptionalSpaces(cur, end);
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimateMotionElement::resetToBaseValue(const String&)
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
15681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!hasValidAttributeType())
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
15881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    AffineTransform* transform = targetElement()->supplementalTransform();
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!transform)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    transform->makeIdentity();
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SVGAnimateMotionElement::calculateFromAndToValues(const String& fromString, const String& toString)
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    parsePoint(fromString, m_fromPoint);
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    parsePoint(toString, m_toPoint);
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SVGAnimateMotionElement::calculateFromAndByValues(const String& fromString, const String& byString)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    parsePoint(fromString, m_fromPoint);
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatPoint byPoint;
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    parsePoint(byString, byPoint);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_toPoint = FloatPoint(m_fromPoint.x() + byPoint.x(), m_fromPoint.y() + byPoint.y());
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid SVGAnimateMotionElement::calculateAnimatedValue(float percentage, unsigned, SVGSMILElement*)
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
18281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    SVGElement* targetElement = this->targetElement();
18381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!targetElement)
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    AffineTransform* transform = targetElement->supplementalTransform();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!transform)
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
18981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (RenderObject* targetRenderer = targetElement->renderer())
19081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        targetRenderer->setNeedsTransformUpdate();
191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!isAdditive())
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        transform->makeIdentity();
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Implement accumulate.
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (animationMode() == PathAnimation) {
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(!animationPath().isEmpty());
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Path path = animationPath();
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float positionOnPath = path.length() * percentage;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool ok;
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FloatPoint position = path.pointAtLength(positionOnPath, ok);
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (ok) {
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            transform->translate(position.x(), position.y());
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            RotateMode rotateMode = this->rotateMode();
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (rotateMode == RotateAuto || rotateMode == RotateAutoReverse) {
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                float angle = path.normalAngleAtLength(positionOnPath, ok);
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (rotateMode == RotateAutoReverse)
20981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    angle += 180;
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                transform->rotate(angle);
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatSize diff = m_toPoint - m_fromPoint;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    transform->translate(diff.width() * percentage + m_fromPoint.x(), diff.height() * percentage + m_fromPoint.y());
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimateMotionElement::applyResultsToTarget()
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We accumulate to the target element transform list so there is not much to do here.
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGElement* targetElement = this->targetElement();
223967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (!targetElement)
224967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        return;
225967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
226967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (RenderObject* renderer = targetElement->renderer())
227967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
228967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
2295abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    AffineTransform* t = targetElement->supplementalTransform();
2305abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    if (!t)
2315abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        return;
2325abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ...except in case where we have additional instances in <use> trees.
234d0825bca7fe65beaee391d30da42e937db621564Steve Block    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
235d0825bca7fe65beaee391d30da42e937db621564Steve Block    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
236d0825bca7fe65beaee391d30da42e937db621564Steve Block    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(shadowTreeElement);
2398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        AffineTransform* transform = shadowTreeElement->supplementalTransform();
2405abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        if (!transform)
2415abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            continue;
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f());
243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (RenderObject* renderer = shadowTreeElement->renderer()) {
244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            renderer->setNeedsTransformUpdate();
245967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimateMotionElement::calculateDistance(const String& fromString, const String& toString)
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatPoint from;
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatPoint to;
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parsePoint(fromString, from))
25581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return -1;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parsePoint(toString, to))
25781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return -1;
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatSize diff = to - from;
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(SVG)
264