18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> 3dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 4dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2007 Eric Seidel <eric@webkit.org> 5dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2008 Apple Inc. All rights reserved. 6dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> 7dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Copyright (C) Research In Motion Limited 2010. All rights reserved. 8dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 9dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is free software; you can redistribute it and/or 10dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * modify it under the terms of the GNU Library General Public 11dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * License as published by the Free Software Foundation; either 12dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * version 2 of the License, or (at your option) any later version. 13dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 14dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * This library is distributed in the hope that it will be useful, 15dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 16dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Library General Public License for more details. 18dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * 19dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * You should have received a copy of the GNU Library General Public License 20dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * along with this library; see the file COPYING.LIB. If not, write to 21dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch * Boston, MA 02110-1301, USA. 23dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch */ 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG_ANIMATION) 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGAnimationElement.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 30e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "Attribute.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSComputedStyleDeclaration.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSParser.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSPropertyNames.h" 34e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "Color.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h" 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Event.h" 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EventListener.h" 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatConversion.h" 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "PlatformString.h" 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGElementInstance.h" 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGNames.h" 43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGParserUtilities.h" 4481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "SVGStyledElement.h" 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGURIReference.h" 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGUseElement.h" 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "XLinkNames.h" 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h> 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Animated property definitions 55f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochDEFINE_ANIMATED_BOOLEAN(SVGAnimationElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenSVGAnimationElement::SVGAnimationElement(const QualifiedName& tagName, Document* document) 585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen : SVGSMILElement(tagName, document) 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_animationValid(false) 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void parseKeyTimes(const String& parse, Vector<float>& result, bool verifyOrder) 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.clear(); 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<String> parseList; 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parse.split(';', parseList); 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned n = 0; n < parseList.size(); ++n) { 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String timeString = parseList[n]; 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool ok; 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float time = timeString.toFloat(&ok); 7281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!ok || time < 0 || time > 1) 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto fail; 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (verifyOrder) { 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!n) { 76f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (time) 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto fail; 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (time < result.last()) 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto fail; 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.append(time); 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfail: 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.clear(); 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void parseKeySplines(const String& parse, Vector<UnitBezier>& result) 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result.clear(); 91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (parse.isEmpty()) 92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block const UChar* cur = parse.characters(); 94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block const UChar* end = cur + parse.length(); 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block skipOptionalSpaces(cur, end); 97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool delimParsed = false; 99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block while (cur < end) { 100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block delimParsed = false; 10181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float posA = 0; 102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!parseNumber(cur, end, posA)) { 103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.clear(); 104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 10781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float posB = 0; 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!parseNumber(cur, end, posB)) { 109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.clear(); 110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 11381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float posC = 0; 114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!parseNumber(cur, end, posC)) { 115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.clear(); 116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 11981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float posD = 0; 120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!parseNumber(cur, end, posD, false)) { 121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.clear(); 122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block skipOptionalSpaces(cur, end); 126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (cur < end && *cur == ';') { 128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block delimParsed = true; 129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block cur++; 130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block skipOptionalSpaces(cur, end); 132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.append(UnitBezier(posA, posB, posC, posD)); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!(cur == end && !delimParsed)) 136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block result.clear(); 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 139e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid SVGAnimationElement::parseMappedAttribute(Attribute* attr) 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (attr->name() == SVGNames::valuesAttr) 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project attr->value().string().split(';', m_values); 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (attr->name() == SVGNames::keyTimesAttr) 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parseKeyTimes(attr->value(), m_keyTimes, true); 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else if (attr->name() == SVGNames::keyPointsAttr && hasTagName(SVGNames::animateMotionTag)) { 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This is specified to be an animateMotion attribute only but it is simpler to put it here 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // where the other timing calculatations are. 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parseKeyTimes(attr->value(), m_keyPoints, false); 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (attr->name() == SVGNames::keySplinesAttr) 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project parseKeySplines(attr->value(), m_keySplines); 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (SVGTests::parseMappedAttribute(attr)) 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SVGSMILElement::parseMappedAttribute(attr); 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::attributeChanged(Attribute* attr, bool preserveDecls) 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Assumptions may not hold after an attribute change. 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_animationValid = false; 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SVGSMILElement::attributeChanged(attr, preserveDecls); 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 167d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid SVGAnimationElement::synchronizeProperty(const QualifiedName& attrName) 168d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 169d0825bca7fe65beaee391d30da42e937db621564Steve Block SVGSMILElement::synchronizeProperty(attrName); 170d0825bca7fe65beaee391d30da42e937db621564Steve Block 1714576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (attrName == anyQName()) { 172d0825bca7fe65beaee391d30da42e937db621564Steve Block synchronizeExternalResourcesRequired(); 1734576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang SVGTests::synchronizeProperties(this, attrName); 1744576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang return; 1754576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang } 1764576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang 1774576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 1784576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang synchronizeExternalResourcesRequired(); 1794576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang else if (SVGTests::isKnownAttribute(attrName)) 1804576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang SVGTests::synchronizeProperties(this, attrName); 181d0825bca7fe65beaee391d30da42e937db621564Steve Block} 182d0825bca7fe65beaee391d30da42e937db621564Steve Block 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimationElement::getStartTime() const 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return narrowPrecisionToFloat(intervalBegin().value()); 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimationElement::getCurrentTime() const 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return narrowPrecisionToFloat(elapsed().value()); 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimationElement::getSimpleDuration(ExceptionCode&) const 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return narrowPrecisionToFloat(simpleDuration().value()); 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SVGAnimationElement::beginElement() 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block beginElementAt(0); 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 203231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SVGAnimationElement::beginElementAt(float offset) 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project addBeginTime(elapsed() + offset); 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 208231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SVGAnimationElement::endElement() 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 210231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block endElementAt(0); 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 213231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SVGAnimationElement::endElementAt(float offset) 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project addEndTime(elapsed() + offset); 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGAnimationElement::AnimationMode SVGAnimationElement::animationMode() const 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hasTagName(SVGNames::setTag)) 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ToAnimation; 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!animationPath().isEmpty()) 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return PathAnimation; 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hasAttribute(SVGNames::valuesAttr)) 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return ValuesAnimation; 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!toValue().isEmpty()) 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return fromValue().isEmpty() ? ToAnimation : FromToAnimation; 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!byValue().isEmpty()) 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return fromValue().isEmpty() ? ByAnimation : FromByAnimation; 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NoAnimation; 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGAnimationElement::CalcMode SVGAnimationElement::calcMode() const 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, discrete, ("discrete")); 237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, linear, ("linear")); 238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, paced, ("paced")); 239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, spline, ("spline")); 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const AtomicString& value = getAttribute(SVGNames::calcModeAttr); 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == discrete) 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return CalcModeDiscrete; 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == linear) 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return CalcModeLinear; 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == paced) 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return CalcModePaced; 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == spline) 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return CalcModeSpline; 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return hasTagName(SVGNames::animateMotionTag) ? CalcModePaced : CalcModeLinear; 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGAnimationElement::AttributeType SVGAnimationElement::attributeType() const 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, css, ("CSS")); 255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, xml, ("XML")); 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const AtomicString& value = getAttribute(SVGNames::attributeTypeAttr); 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == css) 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return AttributeTypeCSS; 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (value == xml) 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return AttributeTypeXML; 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return AttributeTypeAuto; 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString SVGAnimationElement::toValue() const 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return getAttribute(SVGNames::toAttr); 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString SVGAnimationElement::byValue() const 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return getAttribute(SVGNames::byAttr); 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString SVGAnimationElement::fromValue() const 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return getAttribute(SVGNames::fromAttr); 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SVGAnimationElement::isAdditive() const 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 281635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum")); 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const AtomicString& value = getAttribute(SVGNames::additiveAttr); 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return value == sum || animationMode() == ByAnimation; 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool SVGAnimationElement::isAccumulated() const 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum")); 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const AtomicString& value = getAttribute(SVGNames::accumulateAttr); 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return value == sum && animationMode() != ToAnimation; 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 29381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochbool SVGAnimationElement::isTargetAttributeCSSProperty(SVGElement* targetElement, const QualifiedName& attributeName) 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 29581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch ASSERT(targetElement); 29681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!targetElement->isStyled()) 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 29881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 29981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return SVGStyledElement::isAnimatableCSSProperty(attributeName); 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value) 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 30481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!hasValidAttributeType()) 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 30681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch SVGElement* targetElement = this->targetElement(); 30781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch QualifiedName attributeName = this->attributeName(); 30881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!targetElement || attributeName == anyQName() || value.isNull()) 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // We don't want the instance tree to get rebuild. Instances are updated in the loop below. 31281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (targetElement->isStyled()) 31381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(true); 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 31581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch bool attributeIsCSSProperty = isTargetAttributeCSSProperty(targetElement, attributeName); 31681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch // Stop animation, if attributeType is set to CSS by the user, but the attribute itself is not a CSS property. 31781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!attributeIsCSSProperty && attributeType() == AttributeTypeCSS) 31881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return; 31981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ExceptionCode ec; 32181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (attributeIsCSSProperty) { 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This should set the override style, not the inline style. 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Sadly override styles are not yet implemented. 32481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch targetElement->style()->setProperty(attributeName.localName(), value, "", ec); 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: This should set the 'presentation' value, not the actual 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // attribute value. Whatever that means in practice. 32881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch targetElement->setAttribute(attributeName, value, ec); 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 33181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (targetElement->isStyled()) 33281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(false); 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If the target element is used in an <use> instance tree, update that as well. 33581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); 336d0825bca7fe65beaee391d30da42e937db621564Steve Block const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); 337d0825bca7fe65beaee391d30da42e937db621564Steve Block for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); 339cad810f21b803229eb11403f9209855525a25d57Steve Block if (!shadowTreeElement) 340cad810f21b803229eb11403f9209855525a25d57Steve Block continue; 34181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (attributeIsCSSProperty) 34281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch shadowTreeElement->style()->setProperty(attributeName.localName(), value, "", ec); 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project shadowTreeElement->setAttribute(attributeName, value, ec); 3455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian (*it)->correspondingUseElement()->setNeedsStyleRecalc(); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::calculateKeyTimesForCalcModePaced() 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(calcMode() == CalcModePaced); 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(animationMode() == ValuesAnimation); 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned valuesCount = m_values.size(); 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(valuesCount > 1); 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<float> keyTimesForPaced; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float totalDistance = 0; 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project keyTimesForPaced.append(0); 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned n = 0; n < valuesCount - 1; ++n) { 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Distance in any units 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float distance = calculateDistance(m_values[n], m_values[n + 1]); 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (distance < 0) 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project totalDistance += distance; 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project keyTimesForPaced.append(distance); 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!totalDistance) 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Normalize. 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (unsigned n = 1; n < keyTimesForPaced.size() - 1; ++n) 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project keyTimesForPaced[n] = keyTimesForPaced[n - 1] + keyTimesForPaced[n] / totalDistance; 37381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch keyTimesForPaced[keyTimesForPaced.size() - 1] = 1; 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Use key times calculated based on pacing instead of the user provided ones. 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_keyTimes.swap(keyTimesForPaced); 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 37981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic inline double solveEpsilon(double duration) { return 1 / (200 * duration); } 3806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 3816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerunsigned SVGAnimationElement::calculateKeyTimesIndex(float percent) const 3826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{ 3836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner unsigned index; 3846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner unsigned keyTimesCount = m_keyTimes.size(); 3856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner for (index = 1; index < keyTimesCount; ++index) { 3866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (m_keyTimes[index] >= percent) 3876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner break; 3886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 3896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return --index; 3906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} 3916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimationElement::calculatePercentForSpline(float percent, unsigned splineIndex) const 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(calcMode() == CalcModeSpline); 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(splineIndex < m_keySplines.size()); 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UnitBezier bezier = m_keySplines[splineIndex]; 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SMILTime duration = simpleDuration(); 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!duration.isFinite()) 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project duration = 100.0; 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return narrowPrecisionToFloat(bezier.solve(percent, solveEpsilon(duration.value()))); 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_keyPoints.isEmpty()); 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(calcMode() != CalcModePaced); 4076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner ASSERT(m_keyTimes.size() > 1); 4086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner ASSERT(m_keyPoints.size() == m_keyTimes.size()); 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner unsigned index = calculateKeyTimesIndex(percent); 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float fromPercent = m_keyTimes[index]; 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float toPercent = m_keyTimes[index + 1]; 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float fromKeyPoint = m_keyPoints[index]; 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float toKeyPoint = m_keyPoints[index + 1]; 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calcMode() == CalcModeDiscrete) 41781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return percent == 1 ? toKeyPoint : fromKeyPoint; 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 41981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch float keyPointPercent = percent == 1 ? 1 : (percent - fromPercent) / (toPercent - fromPercent); 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calcMode() == CalcModeSpline) { 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_keySplines.size() == m_keyPoints.size() - 1); 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project keyPointPercent = calculatePercentForSpline(keyPointPercent, index); 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return (toKeyPoint - fromKeyPoint) * keyPointPercent + fromKeyPoint; 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_keyPoints.isEmpty()); 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_keyPoints.size() == m_keyTimes.size()); 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(calcMode() != CalcModePaced); 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project effectivePercent = calculatePercentFromKeyPoints(percent); 43481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch unsigned index = effectivePercent == 1 ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1)); 4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project from = m_values[index]; 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project to = m_values[index + 1]; 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to) const 4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned valuesCount = m_values.size(); 4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_animationValid); 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(valuesCount > 1); 4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CalcMode calcMode = this->calcMode(); 4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced) 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return currentValuesFromKeyPoints(percent, effectivePercent, from, to); 4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned keyTimesCount = m_keyTimes.size(); 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!keyTimesCount || valuesCount == keyTimesCount); 451f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(!keyTimesCount || (keyTimesCount > 1 && !m_keyTimes[0])); 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner unsigned index = calculateKeyTimesIndex(percent); 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calcMode == CalcModeDiscrete) { 4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!keyTimesCount) 45681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch index = percent == 1 ? valuesCount - 1 : static_cast<unsigned>(percent * valuesCount); 4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project from = m_values[index]; 4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project to = m_values[index]; 45981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch effectivePercent = 0; 4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float fromPercent; 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float toPercent; 4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (keyTimesCount) { 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fromPercent = m_keyTimes[index]; 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project toPercent = m_keyTimes[index + 1]; 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else { 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project index = static_cast<unsigned>(percent * (valuesCount - 1)); 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fromPercent = static_cast<float>(index) / (valuesCount - 1); 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project toPercent = static_cast<float>(index + 1) / (valuesCount - 1); 4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (index == valuesCount - 1) 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project --index; 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project from = m_values[index]; 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project to = m_values[index + 1]; 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(toPercent > fromPercent); 47981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch effectivePercent = percent == 1 ? 1 : (percent - fromPercent) / (toPercent - fromPercent); 4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calcMode == CalcModeSpline) { 4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_keySplines.size() == m_values.size() - 1); 4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project effectivePercent = calculatePercentForSpline(effectivePercent, index); 4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::startedActiveInterval() 4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_animationValid = false; 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 49181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (!hasValidAttributeType()) 4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // These validations are appropriate for all animation modes. 495dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (hasAttribute(SVGNames::keyPointsAttr) && m_keyPoints.size() != m_keyTimes.size()) 496dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 497dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 4986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner AnimationMode animationMode = this->animationMode(); 499dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block CalcMode calcMode = this->calcMode(); 500dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (calcMode == CalcModeSpline) { 5016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner unsigned splinesCount = m_keySplines.size() + 1; 5026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if ((hasAttribute(SVGNames::keyPointsAttr) && m_keyPoints.size() != splinesCount) 5036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner || (animationMode == ValuesAnimation && m_values.size() != splinesCount)) 504dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 505dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 506dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 507dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block String from = fromValue(); 508dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block String to = toValue(); 509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block String by = byValue(); 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (animationMode == NoAnimation) 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (animationMode == FromToAnimation) 513dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_animationValid = calculateFromAndToValues(from, to); 5142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (animationMode == ToAnimation) { 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For to-animations the from value is the current accumulated value from lower priority animations. 5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The value is not static and is determined during the animation. 517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_animationValid = calculateFromAndToValues(String(), to); 5182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else if (animationMode == FromByAnimation) 519dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_animationValid = calculateFromAndByValues(from, by); 5202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (animationMode == ByAnimation) 521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_animationValid = calculateFromAndByValues(String(), by); 5222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (animationMode == ValuesAnimation) { 5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_animationValid = m_values.size() > 1 5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && (calcMode == CalcModePaced || !hasAttribute(SVGNames::keyTimesAttr) || hasAttribute(SVGNames::keyPointsAttr) || (m_values.size() == m_keyTimes.size())) 5252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block && (calcMode == CalcModeDiscrete || !m_keyTimes.size() || m_keyTimes.last() == 1) 526643ca7872b450ea4efacab6188849e5aac2ba161Steve Block && (calcMode != CalcModeSpline || ((m_keySplines.size() && (m_keySplines.size() == m_values.size() - 1)) || m_keySplines.size() == m_keyPoints.size() - 1)) 5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project && (!hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size())); 5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (calcMode == CalcModePaced && m_animationValid) 5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project calculateKeyTimesForCalcModePaced(); 5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else if (animationMode == PathAnimation) 531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_animationValid = calcMode == CalcModePaced || !hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size()); 5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_animationValid) 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float effectivePercent; 5406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner CalcMode mode = calcMode(); 5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (animationMode() == ValuesAnimation) { 5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String from; 5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project String to; 5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project currentValuesForValuesAnimation(percent, effectivePercent, from, to); 545f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (from != m_lastValuesAnimationFrom || to != m_lastValuesAnimationTo) { 5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_animationValid = calculateFromAndToValues(from, to); 5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_animationValid) 5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastValuesAnimationFrom = from; 5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_lastValuesAnimationTo = to; 5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } else if (!m_keyPoints.isEmpty() && mode != CalcModePaced) 5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project effectivePercent = calculatePercentFromKeyPoints(percent); 5546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner else if (m_keyPoints.isEmpty() && mode == CalcModeSpline && m_keyTimes.size() > 1) 5556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner effectivePercent = calculatePercentForSpline(percent, calculateKeyTimesIndex(percent)); 5566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner else 5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project effectivePercent = percent; 5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project calculateAnimatedValue(effectivePercent, repeat, resultElement); 5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid SVGAnimationElement::endedActiveInterval() 5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(SVG_ANIMATION) 5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 569