15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved.
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGAnimationElement.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/CSSPropertyNames.h"
305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/SVGNames.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/CSSComputedStyleDeclaration.h"
327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/css/parser/CSSParser.h"
3351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "core/frame/UseCounter.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGAnimateElement.h"
35f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/svg/SVGElement.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGParserUtilities.h"
371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/FloatConversion.h"
38f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/MathExtras.h"
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
428abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)SVGAnimationElement::SVGAnimationElement(const QualifiedName& tagName, Document& document)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : SVGSMILElement(tagName, document)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_fromPropertyValueType(RegularPropertyValue)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_toPropertyValueType(RegularPropertyValue)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_animationValid(false)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_attributeType(AttributeTypeAuto)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_hasInvalidCSSAttributeType(false)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_calcMode(CalcModeLinear)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_animationMode(NoAnimation)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    UseCounter::count(document, UseCounter::SVGAnimationElement);
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic void parseKeyTimes(const String& string, Vector<float>& result, bool verifyOrder)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.clear();
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> parseList;
59591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    string.split(';', parseList);
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < parseList.size(); ++n) {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String timeString = parseList[n];
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool ok;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float time = timeString.toFloat(&ok);
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!ok || time < 0 || time > 1)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            goto fail;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (verifyOrder) {
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!n) {
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (time)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    goto fail;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else if (time < result.last())
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                goto fail;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.append(time);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)fail:
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result.clear();
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
80591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochtemplate<typename CharType>
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic bool parseKeySplinesInternal(const String& string, Vector<UnitBezier>& result)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
83591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const CharType* ptr = string.getCharacters<CharType>();
84591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const CharType* end = ptr + string.length();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
86591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    skipOptionalSVGSpaces(ptr, end);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
88591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    while (ptr < end) {
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float posA = 0;
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!parseNumber(ptr, end, posA))
917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return false;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float posB = 0;
947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!parseNumber(ptr, end, posB))
957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return false;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float posC = 0;
987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!parseNumber(ptr, end, posC))
997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return false;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float posD = 0;
1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!parseNumber(ptr, end, posD, DisallowWhitespace))
1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return false;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        skipOptionalSVGSpaces(ptr, end);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (ptr < end && *ptr == ';')
108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            ptr++;
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        skipOptionalSVGSpaces(ptr, end);
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result.append(UnitBezier(posA, posB, posC, posD));
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return ptr == end;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic bool parseKeySplines(const String& string, Vector<UnitBezier>& result)
118591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
119591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    result.clear();
120591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (string.isEmpty())
1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return true;
1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool parsed = true;
123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (string.is8Bit())
1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        parsed = parseKeySplinesInternal<LChar>(string, result);
125591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    else
1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        parsed = parseKeySplinesInternal<UChar>(string, result);
1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!parsed) {
1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        result.clear();
1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return false;
1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return true;
132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimationElement::isSupportedAttribute(const QualifiedName& attrName)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (supportedAttributes.isEmpty()) {
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::valuesAttr);
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::keyTimesAttr);
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::keyPointsAttr);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::keySplinesAttr);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::attributeTypeAttr);
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::calcModeAttr);
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::fromAttr);
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::toAttr);
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::byAttr);
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGAnimationElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!isSupportedAttribute(name)) {
154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        SVGSMILElement::parseAttribute(name, value);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
158926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::valuesAttr) {
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Per the SMIL specification, leading and trailing white space,
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // and white space before and after semicolon separators, is allowed and will be ignored.
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // http://www.w3.org/TR/SVG11/animate.html#ValuesAttribute
162926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        value.string().split(';', m_values);
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < m_values.size(); ++i)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_values[i] = m_values[i].stripWhiteSpace();
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateAnimationMode();
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::keyTimesAttr) {
171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        parseKeyTimes(value, m_keyTimes, true);
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::keyPointsAttr) {
176d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (isSVGAnimateMotionElement(*this)) {
17702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch            // This is specified to be an animateMotion attribute only but it is simpler to put it here
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // where the other timing calculatations are.
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            parseKeyTimes(value, m_keyPoints, false);
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::keySplinesAttr) {
1857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!parseKeySplines(value, m_keySplines))
1867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            reportAttributeParsingError(ParsingAttributeFailedError, name, value);
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::attributeTypeAttr) {
191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setAttributeType(value);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::calcModeAttr) {
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setCalcMode(value);
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::fromAttr || name == SVGNames::toAttr || name == SVGNames::byAttr) {
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateAnimationMode();
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::svgAttributeChanged(const QualifiedName& attrName)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSupportedAttribute(attrName)) {
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGSMILElement::svgAttributeChanged(attrName);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    animationAttributeChanged();
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::animationAttributeChanged()
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Assumptions may not hold after an attribute change.
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationValid = false;
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_lastValuesAnimationFrom = String();
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_lastValuesAnimationTo = String();
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setInactive();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimationElement::getStartTime() const
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return narrowPrecisionToFloat(intervalBegin().value());
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimationElement::getCurrentTime() const
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return narrowPrecisionToFloat(elapsed().value());
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)float SVGAnimationElement::getSimpleDuration() const
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return narrowPrecisionToFloat(simpleDuration().value());
24002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch}
24102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::beginElement()
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    beginElementAt(0);
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::beginElementAt(float offset)
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2496f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    if (!std::isfinite(offset))
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime elapsed = this->elapsed();
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addBeginTime(elapsed, elapsed + offset, SMILTimeWithOrigin::ScriptOrigin);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::endElement()
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    endElementAt(0);
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::endElementAt(float offset)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    if (!std::isfinite(offset))
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime elapsed = this->elapsed();
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addEndTime(elapsed, elapsed + offset, SMILTimeWithOrigin::ScriptOrigin);
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::updateAnimationMode()
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasAttribute(SVGNames::valuesAttr))
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAnimationMode(ValuesAnimation);
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!toValue().isEmpty())
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAnimationMode(fromValue().isEmpty() ? ToAnimation : FromToAnimation);
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!byValue().isEmpty())
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAnimationMode(fromValue().isEmpty() ? ByAnimation : FromByAnimation);
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAnimationMode(NoAnimation);
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::setCalcMode(const AtomicString& calcMode)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, discrete, ("discrete", AtomicString::ConstructFromLiteral));
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, linear, ("linear", AtomicString::ConstructFromLiteral));
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, paced, ("paced", AtomicString::ConstructFromLiteral));
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, spline, ("spline", AtomicString::ConstructFromLiteral));
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode == discrete)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setCalcMode(CalcModeDiscrete);
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (calcMode == linear)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setCalcMode(CalcModeLinear);
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (calcMode == paced)
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setCalcMode(CalcModePaced);
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (calcMode == spline)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setCalcMode(CalcModeSpline);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        setCalcMode(isSVGAnimateMotionElement(*this) ? CalcModePaced : CalcModeLinear);
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::setAttributeType(const AtomicString& attributeType)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, css, ("CSS", AtomicString::ConstructFromLiteral));
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, xml, ("XML", AtomicString::ConstructFromLiteral));
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attributeType == css)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attributeType = AttributeTypeCSS;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (attributeType == xml)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attributeType = AttributeTypeXML;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attributeType = AttributeTypeAuto;
309926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    checkInvalidCSSAttributeType(targetElement());
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String SVGAnimationElement::toValue() const
31302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastGetAttribute(SVGNames::toAttr);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String SVGAnimationElement::byValue() const
31802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastGetAttribute(SVGNames::byAttr);
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String SVGAnimationElement::fromValue() const
32302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastGetAttribute(SVGNames::fromAttr);
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
327f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)bool SVGAnimationElement::isAdditive()
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum", AtomicString::ConstructFromLiteral));
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::additiveAttr);
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return value == sum || animationMode() == ByAnimation;
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimationElement::isAccumulated() const
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum", AtomicString::ConstructFromLiteral));
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::accumulateAttr);
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return value == sum && animationMode() != ToAnimation;
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGAnimationElement::isTargetAttributeCSSProperty(SVGElement* targetElement, const QualifiedName& attributeName)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(targetElement);
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return SVGElement::isAnimatableCSSProperty(attributeName);
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGAnimationElement::ShouldApplyAnimation SVGAnimationElement::shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasValidAttributeType() || !targetElement || attributeName == anyQName())
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return DontApplyAnimation;
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Always animate CSS properties, using the ApplyCSSAnimation code path, regardless of the attributeType value.
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isTargetAttributeCSSProperty(targetElement, attributeName))
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ApplyCSSAnimation;
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If attributeType="CSS" and attributeName doesn't point to a CSS property, ignore the animation.
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attributeType() == AttributeTypeCSS)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return DontApplyAnimation;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ApplyXMLAnimation;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::calculateKeyTimesForCalcModePaced()
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(calcMode() == CalcModePaced);
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(animationMode() == ValuesAnimation);
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned valuesCount = m_values.size();
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(valuesCount >= 1);
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (valuesCount == 1)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
373926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // FIXME, webkit.org/b/109010: m_keyTimes should not be modified in this function.
375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_keyTimes.clear();
376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<float> keyTimesForPaced;
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float totalDistance = 0;
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    keyTimesForPaced.append(0);
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < valuesCount - 1; ++n) {
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Distance in any units
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float distance = calculateDistance(m_values[n], m_values[n + 1]);
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (distance < 0)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        totalDistance += distance;
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        keyTimesForPaced.append(distance);
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!totalDistance)
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Normalize.
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 1; n < keyTimesForPaced.size() - 1; ++n)
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        keyTimesForPaced[n] = keyTimesForPaced[n - 1] + keyTimesForPaced[n] / totalDistance;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    keyTimesForPaced[keyTimesForPaced.size() - 1] = 1;
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use key times calculated based on pacing instead of the user provided ones.
397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_keyTimes = keyTimesForPaced;
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline double solveEpsilon(double duration) { return 1 / (200 * duration); }
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned SVGAnimationElement::calculateKeyTimesIndex(float percent) const
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned index;
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned keyTimesCount = m_keyTimes.size();
406d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // For linear and spline animations, the last value must be '1'. In those
407d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // cases we don't need to consider the last value, since |percent| is never
408d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // greater than one.
409d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (keyTimesCount && calcMode() != CalcModeDiscrete)
410d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        keyTimesCount--;
411d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (index = 1; index < keyTimesCount; ++index) {
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_keyTimes[index] > percent)
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return --index;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimationElement::calculatePercentForSpline(float percent, unsigned splineIndex) const
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(calcMode() == CalcModeSpline);
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT_WITH_SECURITY_IMPLICATION(splineIndex < m_keySplines.size());
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    UnitBezier bezier = m_keySplines[splineIndex];
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime duration = simpleDuration();
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!duration.isFinite())
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        duration = 100.0;
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return narrowPrecisionToFloat(bezier.solve(percent, solveEpsilon(duration.value())));
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_keyPoints.isEmpty());
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(calcMode() != CalcModePaced);
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_keyTimes.size() > 1);
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_keyPoints.size() == m_keyTimes.size());
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (percent == 1)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_keyPoints[m_keyPoints.size() - 1];
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned index = calculateKeyTimesIndex(percent);
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float fromKeyPoint = m_keyPoints[index];
44102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode() == CalcModeDiscrete)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return fromKeyPoint;
44402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
445d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(index + 1 < m_keyTimes.size());
446d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float fromPercent = m_keyTimes[index];
447d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float toPercent = m_keyTimes[index + 1];
448d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float toKeyPoint = m_keyPoints[index + 1];
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float keyPointPercent = (percent - fromPercent) / (toPercent - fromPercent);
45002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode() == CalcModeSpline) {
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_keySplines.size() == m_keyPoints.size() - 1);
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        keyPointPercent = calculatePercentForSpline(keyPointPercent, index);
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return (toKeyPoint - fromKeyPoint) * keyPointPercent + fromKeyPoint;
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGAnimationElement::calculatePercentForFromTo(float percent) const
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode() == CalcModeDiscrete && m_keyTimes.size() == 2)
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return percent > m_keyTimes[1] ? 1 : 0;
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return percent;
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
46502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_keyPoints.isEmpty());
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_keyPoints.size() == m_keyTimes.size());
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(calcMode() != CalcModePaced);
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    effectivePercent = calculatePercentFromKeyPoints(percent);
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned index = effectivePercent == 1 ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1));
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    from = m_values[index];
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to = m_values[index + 1];
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
47602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned valuesCount = m_values.size();
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_animationValid);
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(valuesCount >= 1);
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (percent == 1 || valuesCount == 1) {
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        from = m_values[valuesCount - 1];
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        to = m_values[valuesCount - 1];
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = 1;
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CalcMode calcMode = this->calcMode();
491f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (isSVGAnimateElement(*this)) {
492f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        SVGAnimateElement& animateElement = toSVGAnimateElement(*this);
493f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (!animateElement.animatedPropertyTypeSupportsAddition()) {
494f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            ASSERT(animateElement.animatedPropertyType() != AnimatedTransformList || isSVGAnimateTransformElement(*this));
495f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            ASSERT(animateElement.animatedPropertyType() != AnimatedUnknown);
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            calcMode = CalcModeDiscrete;
497f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        }
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return currentValuesFromKeyPoints(percent, effectivePercent, from, to);
50102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned keyTimesCount = m_keyTimes.size();
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!keyTimesCount || valuesCount == keyTimesCount);
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!keyTimesCount || (keyTimesCount > 1 && !m_keyTimes[0]));
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned index = calculateKeyTimesIndex(percent);
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode == CalcModeDiscrete) {
50802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        if (!keyTimesCount)
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            index = static_cast<unsigned>(percent * valuesCount);
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        from = m_values[index];
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        to = m_values[index];
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = 0;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
51502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float fromPercent;
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float toPercent;
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (keyTimesCount) {
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fromPercent = m_keyTimes[index];
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        toPercent = m_keyTimes[index + 1];
52102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    } else {
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        index = static_cast<unsigned>(floorf(percent * (valuesCount - 1)));
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fromPercent =  static_cast<float>(index) / (valuesCount - 1);
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        toPercent =  static_cast<float>(index + 1) / (valuesCount - 1);
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
52602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (index == valuesCount - 1)
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        --index;
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    from = m_values[index];
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to = m_values[index + 1];
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(toPercent > fromPercent);
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    effectivePercent = (percent - fromPercent) / (toPercent - fromPercent);
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode == CalcModeSpline) {
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_keySplines.size() == m_values.size() - 1);
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = calculatePercentForSpline(effectivePercent, index);
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
53902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::startedActiveInterval()
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationValid = false;
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
544c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!isValid())
545c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
546c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasValidAttributeType())
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // These validations are appropriate for all animation modes.
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fastHasAttribute(SVGNames::keyPointsAttr) && m_keyPoints.size() != m_keyTimes.size())
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AnimationMode animationMode = this->animationMode();
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CalcMode calcMode = this->calcMode();
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (calcMode == CalcModeSpline) {
557e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        unsigned splinesCount = m_keySplines.size();
558e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!splinesCount
559e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            || (fastHasAttribute(SVGNames::keyPointsAttr) && m_keyPoints.size() - 1 != splinesCount)
560e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            || (animationMode == ValuesAnimation && m_values.size() - 1 != splinesCount)
561e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            || (fastHasAttribute(SVGNames::keyTimesAttr) && m_keyTimes.size() - 1 != splinesCount))
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String from = fromValue();
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String to = toValue();
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String by = byValue();
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationMode == NoAnimation)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5709e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if ((animationMode == FromToAnimation || animationMode == FromByAnimation || animationMode == ToAnimation || animationMode == ByAnimation)
5719e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        && (fastHasAttribute(SVGNames::keyPointsAttr) && fastHasAttribute(SVGNames::keyTimesAttr) && (m_keyTimes.size() < 2 || m_keyTimes.size() != m_keyPoints.size())))
5729e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return;
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationMode == FromToAnimation)
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = calculateFromAndToValues(from, to);
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (animationMode == ToAnimation) {
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For to-animations the from value is the current accumulated value from lower priority animations.
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The value is not static and is determined during the animation.
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = calculateFromAndToValues(emptyString(), to);
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (animationMode == FromByAnimation)
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = calculateFromAndByValues(from, by);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (animationMode == ByAnimation)
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = calculateFromAndByValues(emptyString(), by);
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (animationMode == ValuesAnimation) {
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = m_values.size() >= 1
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            && (calcMode == CalcModePaced || !fastHasAttribute(SVGNames::keyTimesAttr) || fastHasAttribute(SVGNames::keyPointsAttr) || (m_values.size() == m_keyTimes.size()))
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            && (calcMode == CalcModeDiscrete || !m_keyTimes.size() || m_keyTimes.last() == 1)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            && (calcMode != CalcModeSpline || ((m_keySplines.size() && (m_keySplines.size() == m_values.size() - 1)) || m_keySplines.size() == m_keyPoints.size() - 1))
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            && (!fastHasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size()));
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_animationValid)
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_animationValid = calculateToAtEndOfDurationValue(m_values.last());
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (calcMode == CalcModePaced && m_animationValid)
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            calculateKeyTimesForCalcModePaced();
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (animationMode == PathAnimation)
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationValid = calcMode == CalcModePaced || !fastHasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size());
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::updateAnimation(float percent, unsigned repeatCount, SVGSMILElement* resultElement)
59802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_animationValid)
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float effectivePercent;
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CalcMode calcMode = this->calcMode();
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AnimationMode animationMode = this->animationMode();
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationMode == ValuesAnimation) {
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String from;
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String to;
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentValuesForValuesAnimation(percent, effectivePercent, from, to);
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (from != m_lastValuesAnimationFrom || to != m_lastValuesAnimationTo) {
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_animationValid = calculateFromAndToValues(from, to);
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!m_animationValid)
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_lastValuesAnimationFrom = from;
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_lastValuesAnimationTo = to;
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced)
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = calculatePercentFromKeyPoints(percent);
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (m_keyPoints.isEmpty() && calcMode == CalcModeSpline && m_keyTimes.size() > 1)
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = calculatePercentForSpline(percent, calculateKeyTimesIndex(percent));
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (animationMode == FromToAnimation || animationMode == ToAnimation)
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = calculatePercentForFromTo(percent);
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectivePercent = percent;
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    calculateAnimatedValue(effectivePercent, repeatCount, resultElement);
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::computeCSSPropertyValue(SVGElement* element, CSSPropertyID id, String& value)
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(element);
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Don't include any properties resulting from CSS Transitions/Animations or SMIL animations, as we want to retrieve the "base value".
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    element->setUseOverrideComputedStyle(true);
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    value = CSSComputedStyleDeclaration::create(element)->getPropertyValue(id);
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    element->setUseOverrideComputedStyle(false);
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::adjustForInheritance(SVGElement* targetElement, const QualifiedName& attributeName, String& value)
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: At the moment the computed style gets returned as a String and needs to get parsed again.
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // In the future we might want to work with the value type directly to avoid the String parsing.
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(targetElement);
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Element* parent = targetElement->parentElement();
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parent || !parent->isSVGElement())
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SVGElement* svgParent = toSVGElement(parent);
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    computeCSSPropertyValue(svgParent, cssPropertyID(attributeName.localName()), value);
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool inheritsFromProperty(SVGElement* targetElement, const QualifiedName& attributeName, const String& value)
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(targetElement);
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, inherit, ("inherit", AtomicString::ConstructFromLiteral));
65602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
657f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (value.isEmpty() || value != inherit)
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
659f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return SVGElement::isAnimatableCSSProperty(attributeName);
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::determinePropertyValueTypes(const String& from, const String& to)
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement* targetElement = this->targetElement();
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(targetElement);
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const QualifiedName& attributeName = this->attributeName();
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (inheritsFromProperty(targetElement, attributeName, from))
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_fromPropertyValueType = InheritValue;
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (inheritsFromProperty(targetElement, attributeName, to))
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_toPropertyValueType = InheritValue;
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGAnimationElement::setTargetElement(SVGElement* target)
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
676926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SVGSMILElement::setTargetElement(target);
677926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    checkInvalidCSSAttributeType(target);
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::setAttributeName(const QualifiedName& attributeName)
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGSMILElement::setAttributeName(attributeName);
683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    checkInvalidCSSAttributeType(targetElement());
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGAnimationElement::checkInvalidCSSAttributeType(SVGElement* target)
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_hasInvalidCSSAttributeType = target && hasValidAttributeName() && attributeType() == AttributeTypeCSS && !isTargetAttributeCSSProperty(target, attributeName());
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
692