15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/animation/SVGSMILElement.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptEventListener.h"
315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XLinkNames.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
33197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/events/Event.h"
3406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/EventListener.h"
3506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/EventSender.h"
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/frame/UseCounter.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGDocumentExtensions.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGSVGElement.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGURIReference.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/animation/SMILTimeContainer.h"
411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/FloatConversion.h"
42f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/MathExtras.h"
43f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/StdLibExtras.h"
44f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/Vector.h"
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
4702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class RepeatEvent FINAL : public Event {
499bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)public:
5007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    static PassRefPtrWillBeRawPtr<RepeatEvent> create(const AtomicString& type, int repeat)
519bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    {
52a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return adoptRefWillBeNoop(new RepeatEvent(type, false, false, repeat));
539bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    }
549bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual ~RepeatEvent() { }
569bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
579bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    int repeat() const { return m_repeat; }
5807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
59aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    virtual void trace(Visitor* visitor) OVERRIDE
60aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    {
61aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        Event::trace(visitor);
62aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    }
6307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
649bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)protected:
659bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    RepeatEvent(const AtomicString& type, bool canBubble, bool cancelable, int repeat = -1)
669bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        : Event(type, canBubble, cancelable)
679bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        , m_repeat(repeat)
689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    {
699bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    }
7007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
719bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)private:
729bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    int m_repeat;
739bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)};
749bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
759bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)inline RepeatEvent* toRepeatEvent(Event* event)
769bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles){
779bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    ASSERT_WITH_SECURITY_IMPLICATION(!event || event->type() == "repeatn");
789bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    return static_cast<RepeatEvent*>(event);
799bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)}
809bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
818abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)static SMILEventSender& smilEndEventSender()
828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    DEFINE_STATIC_LOCAL(SMILEventSender, sender, (EventTypeNames::endEvent));
848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    return sender;
858abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
868abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
878abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)static SMILEventSender& smilBeginEventSender()
888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    DEFINE_STATIC_LOCAL(SMILEventSender, sender, (EventTypeNames::beginEvent));
908abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    return sender;
918abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
928abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
938abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)static SMILEventSender& smilRepeatEventSender()
948abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    DEFINE_STATIC_LOCAL(SMILEventSender, sender, (EventTypeNames::repeatEvent));
968abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    return sender;
978abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
988abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
998abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)static SMILEventSender& smilRepeatNEventSender()
1008abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    DEFINE_STATIC_LOCAL(SMILEventSender, sender, (AtomicString("repeatn", AtomicString::ConstructFromLiteral)));
1028abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    return sender;
1038abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
1048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This is used for duration type time values that can't be negative.
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const double invalidCachedTime = -1.;
10702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class ConditionEventListener FINAL : public EventListener {
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static PassRefPtr<ConditionEventListener> create(SVGSMILElement* animation, SVGSMILElement::Condition* condition)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptRef(new ConditionEventListener(animation, condition));
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const ConditionEventListener* cast(const EventListener* listener)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return listener->type() == ConditionEventListenerType
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ? static_cast<const ConditionEventListener*>(listener)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            : 0;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual bool operator==(const EventListener& other) OVERRIDE;
12302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void disconnectAnimation()
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animation = 0;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
13002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    ConditionEventListener(SVGSMILElement* animation, SVGSMILElement::Condition* condition)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        : EventListener(ConditionEventListenerType)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_animation(animation)
13302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        , m_condition(condition)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGSMILElement* m_animation;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGSMILElement::Condition* m_condition;
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ConditionEventListener::operator==(const EventListener& listener)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (const ConditionEventListener* conditionEventListener = ConditionEventListener::cast(&listener))
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_animation == conditionEventListener->m_animation && m_condition == conditionEventListener->m_condition;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void ConditionEventListener::handleEvent(ExecutionContext*, Event* event)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_animation)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animation->handleConditionEvent(event, m_condition);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
157d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void SVGSMILElement::Condition::setEventListener(PassRefPtr<ConditionEventListener> eventListener)
158d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
159d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_eventListener = eventListener;
160d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
161d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1629bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)SVGSMILElement::Condition::Condition(Type type, BeginOrEnd beginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_type(type)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_beginOrEnd(beginOrEnd)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_baseID(baseID)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_name(name)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_offset(offset)
1689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    , m_repeat(repeat)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1728abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : SVGElement(tagName, doc)
174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , SVGTests(this)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_attributeName(anyQName())
176323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    , m_targetElement(nullptr)
17709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_syncBaseConditionsConnected(false)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_hasEndEventConditions(false)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_isWaitingForFirstInterval(true)
180f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    , m_interval(SMILInterval(SMILTime::unresolved(), SMILTime::unresolved()))
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_previousIntervalBegin(SMILTime::unresolved())
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_activeState(Inactive)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_lastPercent(0)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_lastRepeat(0)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_nextProgressTime(0)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_documentOrderIndex(0)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_cachedDur(invalidCachedTime)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_cachedRepeatDur(invalidCachedTime)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_cachedRepeatCount(invalidCachedTime)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_cachedMin(invalidCachedTime)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_cachedMax(invalidCachedTime)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resolveFirstInterval();
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGSMILElement::~SVGSMILElement()
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
198f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#if !ENABLE(OILPAN)
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    clearResourceAndEventBaseReferences();
200f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
2018abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilEndEventSender().cancelEvent(this);
2028abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilBeginEventSender().cancelEvent(this);
2038abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilRepeatEventSender().cancelEvent(this);
2048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilRepeatNEventSender().cancelEvent(this);
205323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#if !ENABLE(OILPAN)
20609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    clearConditions();
207d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer && m_targetElement && hasValidAttributeName())
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
210323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#endif
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
21309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::clearResourceAndEventBaseReferences()
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
215197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    removeAllOutgoingReferences();
216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::clearConditions()
21909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
22009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    disconnectSyncBaseConditions();
22109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    disconnectEventBaseConditions();
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_conditions.clear();
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGSMILElement::buildPendingResource()
226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    clearResourceAndEventBaseReferences();
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!inDocument()) {
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Reset the target element if we are no longer in the document.
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setTargetElement(0);
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AtomicString id;
23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AtomicString href = getAttribute(XLinkNames::hrefAttr);
237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Element* target;
238926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (href.isEmpty())
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        target = parentNode() && parentNode()->isElementNode() ? toElement(parentNode()) : 0;
240926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else
24110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        target = SVGURIReference::targetElementFromIRIString(href, treeScope(), &id);
242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    SVGElement* svgTarget = target && target->isSVGElement() ? toSVGElement(target) : 0;
243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (svgTarget && !svgTarget->inDocument())
245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        svgTarget = 0;
246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (svgTarget != targetElement())
248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setTargetElement(svgTarget);
249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!svgTarget) {
251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Do not register as pending if we are already pending this resource.
252d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (document().accessSVGExtensions().isElementPendingResource(this, id))
253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return;
254926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
255926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!id.isEmpty()) {
256d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            document().accessSVGExtensions().addPendingResource(id, this);
257926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ASSERT(hasPendingResources());
258926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else {
260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Register us with the target in the dependencies map. Any change of hrefElement
261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // that leads to relayout/repainting now informs us, so we can react to it.
262197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        addReferenceTo(svgTarget);
263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    connectEventBaseConditions();
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
267a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static inline QualifiedName constructQualifiedName(const SVGElement* svgElement, const AtomicString& attributeName)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(svgElement);
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attributeName.isEmpty())
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return anyQName();
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!attributeName.contains(':'))
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return QualifiedName(nullAtom, attributeName, nullAtom);
27402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
275a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    AtomicString prefix;
276a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    AtomicString localName;
277323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!Document::parseQualifiedName(attributeName, prefix, localName, IGNORE_EXCEPTION))
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return anyQName();
27902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
280a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const AtomicString& namespaceURI = svgElement->lookupNamespaceURI(prefix);
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (namespaceURI.isEmpty())
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return anyQName();
28302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return QualifiedName(nullAtom, localName, namespaceURI);
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void clearTimesWithDynamicOrigins(Vector<SMILTimeWithOrigin>& timeList)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = timeList.size() - 1; i >= 0; --i) {
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (timeList[i].originIsScript())
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            timeList.remove(i);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::reset()
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearAnimatedType(m_targetElement);
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_activeState = Inactive;
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_isWaitingForFirstInterval = true;
301f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_interval.begin = SMILTime::unresolved();
302f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_interval.end = SMILTime::unresolved();
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_previousIntervalBegin = SMILTime::unresolved();
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_lastPercent = 0;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_lastRepeat = 0;
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_nextProgressTime = 0;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resolveFirstInterval();
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node::InsertionNotificationRequest SVGSMILElement::insertedInto(ContainerNode* rootParent)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement::insertedInto(rootParent);
31310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rootParent->inDocument())
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InsertionDone;
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
317c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    UseCounter::count(document(), UseCounter::SVGSMILElementInDocument);
318c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setAttributeName(constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr)));
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGSVGElement* owner = ownerSVGElement();
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!owner)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InsertionDone;
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timeContainer = owner->timeContainer();
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_timeContainer);
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_timeContainer->setDocumentOrderIndexesDirty();
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "If no attribute is present, the default begin value (an offset-value of 0) must be evaluated."
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!fastHasAttribute(SVGNames::beginAttr))
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_beginTimes.append(SMILTimeWithOrigin());
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_isWaitingForFirstInterval)
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resolveFirstInterval();
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_timeContainer->notifyIntervalsChanged();
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    buildPendingResource();
339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return InsertionDone;
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::removedFrom(ContainerNode* rootParent)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rootParent->inDocument()) {
34609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        clearResourceAndEventBaseReferences();
34709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        clearConditions();
348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setTargetElement(0);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setAttributeName(anyQName());
350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        animationAttributeChanged();
351d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_timeContainer = nullptr;
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGElement::removedFrom(rootParent);
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGSMILElement::hasValidAttributeName()
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return attributeName() != anyQName();
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::parseOffsetValue(const String& data)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool ok;
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double result = 0;
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String parse = data.stripWhiteSpace();
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parse.endsWith('h'))
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = parse.left(parse.length() - 1).toDouble(&ok) * 60 * 60;
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (parse.endsWith("min"))
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = parse.left(parse.length() - 3).toDouble(&ok) * 60;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (parse.endsWith("ms"))
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = parse.left(parse.length() - 2).toDouble(&ok) / 1000;
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (parse.endsWith('s'))
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = parse.left(parse.length() - 1).toDouble(&ok);
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = parse.toDouble(&ok);
377c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!ok || !SMILTime(result).isFinite())
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return SMILTime::unresolved();
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
38102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::parseClockValue(const String& data)
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (data.isNull())
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return SMILTime::unresolved();
38602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String parse = data.stripWhiteSpace();
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, indefiniteValue, ("indefinite", AtomicString::ConstructFromLiteral));
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parse == indefiniteValue)
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return SMILTime::indefinite();
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double result = 0;
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool ok;
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t doublePointOne = parse.find(':');
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t doublePointTwo = parse.find(':', doublePointOne + 1);
39702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    if (doublePointOne == 2 && doublePointTwo == 5 && parse.length() >= 8) {
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result += parse.substring(0, 2).toUIntStrict(&ok) * 60 * 60;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!ok)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SMILTime::unresolved();
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result += parse.substring(3, 2).toUIntStrict(&ok) * 60;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!ok)
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SMILTime::unresolved();
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result += parse.substring(6).toDouble(&ok);
40506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    } else if (doublePointOne == 2 && doublePointTwo == kNotFound && parse.length() >= 5) {
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result += parse.substring(0, 2).toUIntStrict(&ok) * 60;
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!ok)
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return SMILTime::unresolved();
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result += parse.substring(3).toDouble(&ok);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return parseOffsetValue(parse);
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
413c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!ok || !SMILTime(result).isFinite())
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return SMILTime::unresolved();
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
41702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void sortTimeList(Vector<SMILTimeWithOrigin>& timeList)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    std::sort(timeList.begin(), timeList.end());
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
42202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGSMILElement::parseCondition(const String& value, BeginOrEnd beginOrEnd)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String parseString = value.stripWhiteSpace();
42602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double sign = 1.;
4289bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    bool ok;
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t pos = parseString.find('+');
43006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (pos == kNotFound) {
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pos = parseString.find('-');
43206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (pos != kNotFound)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sign = -1.;
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String conditionString;
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime offset = 0;
43706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (pos == kNotFound)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        conditionString = parseString;
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        conditionString = parseString.left(pos).stripWhiteSpace();
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String offsetString = parseString.substring(pos + 1).stripWhiteSpace();
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        offset = parseOffsetValue(offsetString);
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (offset.isUnresolved())
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        offset = offset * sign;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (conditionString.isEmpty())
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pos = conditionString.find('.');
45002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String baseID;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String nameString;
45306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (pos == kNotFound)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nameString = conditionString;
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        baseID = conditionString.left(pos);
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nameString = conditionString.substring(pos + 1);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (nameString.isEmpty())
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Condition::Type type;
4639bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    int repeat = -1;
4649bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    if (nameString.startsWith("repeat(") && nameString.endsWith(')')) {
4659bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        repeat = nameString.substring(7, nameString.length() - 8).toUIntStrict(&ok);
4669bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        if (!ok)
4679bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)            return false;
4689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        nameString = "repeatn";
4699bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        type = Condition::EventBase;
4709bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    } else if (nameString == "begin" || nameString == "end") {
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (baseID.isEmpty())
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        type = Condition::Syncbase;
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (nameString.startsWith("accesskey(")) {
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: accesskey() support.
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        type = Condition::AccessKey;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        type = Condition::EventBase;
47902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
480d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    m_conditions.append(Condition::create(type, beginOrEnd, baseID, nameString, offset, repeat));
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (type == Condition::EventBase && beginOrEnd == End)
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_hasEndEventConditions = true;
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::parseBeginOrEnd(const String& parseString, BeginOrEnd beginOrEnd)
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<SMILTimeWithOrigin>& timeList = beginOrEnd == Begin ? m_beginTimes : m_endTimes;
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (beginOrEnd == End)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_hasEndEventConditions = false;
4937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    HashSet<SMILTime> existing;
4947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    for (unsigned n = 0; n < timeList.size(); ++n) {
4957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!timeList[n].time().isUnresolved())
4967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            existing.add(timeList[n].time().value());
4977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<String> splitString;
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parseString.split(';', splitString);
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < splitString.size(); ++n) {
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SMILTime value = parseClockValue(splitString[n]);
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (value.isUnresolved())
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            parseCondition(splitString[n], beginOrEnd);
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (!existing.contains(value.value()))
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            timeList.append(SMILTimeWithOrigin(value, SMILTimeWithOrigin::ParserOrigin));
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sortTimeList(timeList);
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGSMILElement::isSupportedAttribute(const QualifiedName& attrName)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (supportedAttributes.isEmpty()) {
514c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        SVGTests::addSupportedAttributes(supportedAttributes);
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::beginAttr);
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::endAttr);
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::durAttr);
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::repeatDurAttr);
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::repeatCountAttr);
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::minAttr);
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::maxAttr);
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::attributeNameAttr);
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(XLinkNames::hrefAttr);
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
525591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGSMILElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == SVGNames::beginAttr) {
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_conditions.isEmpty()) {
53209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            clearConditions();
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            parseBeginOrEnd(fastGetAttribute(SVGNames::endAttr), End);
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
535926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        parseBeginOrEnd(value.string(), Begin);
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (inDocument())
53709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            connectSyncBaseConditions();
538926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (name == SVGNames::endAttr) {
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_conditions.isEmpty()) {
54009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            clearConditions();
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            parseBeginOrEnd(fastGetAttribute(SVGNames::beginAttr), Begin);
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        parseBeginOrEnd(value.string(), End);
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (inDocument())
54509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            connectSyncBaseConditions();
54609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::onbeginAttr) {
5475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        setAttributeEventListener(EventTypeNames::beginEvent, createAttributeEventListener(this, name, value, eventParameterName()));
54809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::onendAttr) {
5495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        setAttributeEventListener(EventTypeNames::endEvent, createAttributeEventListener(this, name, value, eventParameterName()));
55009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else if (name == SVGNames::onrepeatAttr) {
5515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        setAttributeEventListener(EventTypeNames::repeatEvent, createAttributeEventListener(this, name, value, eventParameterName()));
552c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    } else {
553c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        SVGElement::parseAttributeNew(name, value);
554c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::svgAttributeChanged(const QualifiedName& attrName)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSupportedAttribute(attrName)) {
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGElement::svgAttributeChanged(attrName);
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attrName == SVGNames::durAttr)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_cachedDur = invalidCachedTime;
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (attrName == SVGNames::repeatDurAttr)
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_cachedRepeatDur = invalidCachedTime;
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (attrName == SVGNames::repeatCountAttr)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_cachedRepeatCount = invalidCachedTime;
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (attrName == SVGNames::minAttr)
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_cachedMin = invalidCachedTime;
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (attrName == SVGNames::maxAttr)
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_cachedMax = invalidCachedTime;
574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (attrName == SVGNames::attributeNameAttr)
575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        setAttributeName(constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr)));
576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    else if (attrName.matches(XLinkNames::hrefAttr)) {
577323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        SVGElement::InvalidationGuard invalidationGuard(this);
578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        buildPendingResource();
579f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        if (m_targetElement)
580f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            clearAnimatedType(m_targetElement);
581926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    } else if (inDocument()) {
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (attrName == SVGNames::beginAttr)
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            beginListChanged(elapsed());
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (attrName == SVGNames::endAttr)
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            endListChanged(elapsed());
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    animationAttributeChanged();
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
59109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline SVGElement* SVGSMILElement::eventBaseFor(const Condition& condition)
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
593d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Element* eventBase = condition.baseID().isEmpty() ? targetElement() : treeScope().getElementById(AtomicString(condition.baseID()));
59409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (eventBase && eventBase->isSVGElement())
59509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return toSVGElement(eventBase);
59609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return 0;
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
59909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::connectSyncBaseConditions()
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
60109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_syncBaseConditionsConnected)
60209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        disconnectSyncBaseConditions();
60309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_syncBaseConditionsConnected = true;
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < m_conditions.size(); ++n) {
605d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Condition* condition = m_conditions[n].get();
606d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (condition->type() == Condition::Syncbase) {
607d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            ASSERT(!condition->baseID().isEmpty());
608f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            Element* element = treeScope().getElementById(AtomicString(condition->baseID()));
609f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            if (!element || !isSVGSMILElement(*element)) {
610d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                condition->setSyncBase(0);
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
613f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            SVGSMILElement* svgSMILElement = toSVGSMILElement(element);
614f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            condition->setSyncBase(svgSMILElement);
615f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            svgSMILElement->addSyncBaseDependent(this);
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
62009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::disconnectSyncBaseConditions()
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
62209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_syncBaseConditionsConnected)
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
62409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_syncBaseConditionsConnected = false;
62509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (unsigned n = 0; n < m_conditions.size(); ++n) {
626d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Condition* condition = m_conditions[n].get();
627d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (condition->type() == Condition::Syncbase) {
628d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            if (condition->syncBase())
629f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                condition->syncBase()->removeSyncBaseDependent(this);
630d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            condition->setSyncBase(0);
63109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
63209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
63309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
63409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
63509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::connectEventBaseConditions()
63609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
63709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    disconnectEventBaseConditions();
63809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (unsigned n = 0; n < m_conditions.size(); ++n) {
639d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Condition* condition = m_conditions[n].get();
640d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (condition->type() == Condition::EventBase) {
641d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            ASSERT(!condition->syncBase());
642d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            SVGElement* eventBase = eventBaseFor(*condition);
64309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (!eventBase) {
644d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                if (!condition->baseID().isEmpty() && !document().accessSVGExtensions().isElementPendingResource(this, AtomicString(condition->baseID())))
645d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                    document().accessSVGExtensions().addPendingResource(AtomicString(condition->baseID()), this);
64609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                continue;
64709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            }
648d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            ASSERT(!condition->eventListener());
649d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            condition->setEventListener(ConditionEventListener::create(this, condition));
650d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            eventBase->addEventListener(AtomicString(condition->name()), condition->eventListener(), false);
651197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            addReferenceTo(eventBase);
65209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
65309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
65409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
65509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
65609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::disconnectEventBaseConditions()
65709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < m_conditions.size(); ++n) {
659d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Condition* condition = m_conditions[n].get();
660d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (condition->type() == Condition::EventBase) {
661d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            ASSERT(!condition->syncBase());
662d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            if (!condition->eventListener())
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Note: It's a memory optimization to try to remove our condition
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // event listener, but it's not guaranteed to work, since we have
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // no guarantee that eventBaseFor() will be able to find our condition's
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // original eventBase. So, we also have to disconnect ourselves from
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // our condition event listener, in case it later fires.
669d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            SVGElement* eventBase = eventBaseFor(*condition);
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (eventBase)
671d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                eventBase->removeEventListener(AtomicString(condition->name()), condition->eventListener(), false);
672d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            condition->eventListener()->disconnectAnimation();
673d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            condition->setEventListener(nullptr);
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::setAttributeName(const QualifiedName& attributeName)
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer && m_targetElement && m_attributeName != attributeName) {
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (hasValidAttributeName())
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attributeName = attributeName;
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (hasValidAttributeName())
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_timeContainer->schedule(this, m_targetElement, m_attributeName);
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attributeName = attributeName;
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
689926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Only clear the animated type, if we had a target before.
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_targetElement)
691926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        clearAnimatedType(m_targetElement);
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
694926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGSMILElement::setTargetElement(SVGElement* target)
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer && hasValidAttributeName()) {
697926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (m_targetElement)
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (target)
700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            m_timeContainer->schedule(this, target, m_attributeName);
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
703926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (m_targetElement) {
704926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Clear values that may depend on the previous target.
705926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        clearAnimatedType(m_targetElement);
70609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        disconnectSyncBaseConditions();
707926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the animation state is not Inactive, always reset to a clear state before leaving the old target element.
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_activeState != Inactive)
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endedActiveInterval();
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
713926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_targetElement = target;
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::elapsed() const
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_timeContainer ? m_timeContainer->elapsed() : 0;
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGSMILElement::isFrozen() const
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_activeState == Frozen;
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
72502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGSMILElement::Restart SVGSMILElement::restart() const
72702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, never, ("never", AtomicString::ConstructFromLiteral));
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, whenNotActive, ("whenNotActive", AtomicString::ConstructFromLiteral));
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::restartAttr);
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (value == never)
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return RestartNever;
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (value == whenNotActive)
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return RestartWhenNotActive;
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return RestartAlways;
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
73702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGSMILElement::FillMode SVGSMILElement::fill() const
73902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, freeze, ("freeze", AtomicString::ConstructFromLiteral));
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::fillAttr);
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return value == freeze ? FillFreeze : FillRemove;
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
74402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::dur() const
74602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_cachedDur != invalidCachedTime)
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_cachedDur;
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::durAttr);
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime clockValue = parseClockValue(value);
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_cachedDur = clockValue <= 0 ? SMILTime::unresolved() : clockValue;
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::repeatDur() const
75502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_cachedRepeatDur != invalidCachedTime)
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_cachedRepeatDur;
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::repeatDurAttr);
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime clockValue = parseClockValue(value);
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_cachedRepeatDur = clockValue <= 0 ? SMILTime::unresolved() : clockValue;
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_cachedRepeatDur;
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
76302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// So a count is not really a time but let just all pretend we did not notice.
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::repeatCount() const
76602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_cachedRepeatCount != invalidCachedTime)
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_cachedRepeatCount;
76907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SMILTime computedRepeatCount = SMILTime::unresolved();
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::repeatCountAttr);
77107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    if (!value.isNull()) {
77207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        DEFINE_STATIC_LOCAL(const AtomicString, indefiniteValue, ("indefinite", AtomicString::ConstructFromLiteral));
77307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        if (value == indefiniteValue) {
77407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            computedRepeatCount = SMILTime::indefinite();
77507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        } else {
77607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            bool ok;
7777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            double result = value.toDouble(&ok);
77807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            if (ok && result > 0)
77907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                computedRepeatCount = result;
78007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch        }
78107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    }
78207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    m_cachedRepeatCount = computedRepeatCount;
78307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    return m_cachedRepeatCount;
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::maxValue() const
78702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_cachedMax != invalidCachedTime)
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_cachedMax;
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::maxAttr);
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime result = parseClockValue(value);
792f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    return m_cachedMax = (result.isUnresolved() || result <= 0) ? SMILTime::indefinite() : result;
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
79402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::minValue() const
79602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_cachedMin != invalidCachedTime)
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_cachedMin;
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& value = fastGetAttribute(SVGNames::minAttr);
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime result = parseClockValue(value);
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_cachedMin = (result.isUnresolved() || result < 0) ? 0 : result;
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
80302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::simpleDuration() const
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return std::min(dur(), SMILTime::indefinite());
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::addBeginTime(SMILTime eventTime, SMILTime beginTime, SMILTimeWithOrigin::Origin origin)
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_beginTimes.append(SMILTimeWithOrigin(beginTime, origin));
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sortTimeList(m_beginTimes);
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    beginListChanged(eventTime);
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin origin)
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_endTimes.append(SMILTimeWithOrigin(endTime, origin));
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sortTimeList(m_endTimes);
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    endListChanged(eventTime);
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
82309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)inline bool compareTimes(const SMILTimeWithOrigin& left, const SMILTimeWithOrigin& right)
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
82509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return left.time() < right.time();
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::findInstanceTime(BeginOrEnd beginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const Vector<SMILTimeWithOrigin>& list = beginOrEnd == Begin ? m_beginTimes : m_endTimes;
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int sizeOfList = list.size();
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!sizeOfList)
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return beginOrEnd == Begin ? SMILTime::unresolved() : SMILTime::indefinite();
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
83609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const SMILTimeWithOrigin dummyTimeWithOrigin(minimumTime, SMILTimeWithOrigin::ParserOrigin);
83709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const SMILTimeWithOrigin* result = std::lower_bound(list.begin(), list.end(), dummyTimeWithOrigin, compareTimes);
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int indexOfResult = result - list.begin();
83909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (indexOfResult == sizeOfList)
84009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return SMILTime::unresolved();
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const SMILTime& currentTime = list[indexOfResult].time();
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The special value "indefinite" does not yield an instance time in the begin list.
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (currentTime.isIndefinite() && beginOrEnd == Begin)
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return SMILTime::unresolved();
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (currentTime > minimumTime)
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return currentTime;
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(currentTime == minimumTime);
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (equalsMinimumOK)
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return currentTime;
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the equals is not accepted, return the next bigger item in the list.
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime nextTime = currentTime;
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (indexOfResult < sizeOfList - 1) {
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nextTime = list[indexOfResult + 1].time();
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (nextTime > minimumTime)
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return nextTime;
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++indexOfResult;
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return beginOrEnd == Begin ? SMILTime::unresolved() : SMILTime::indefinite();
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::repeatingDuration() const
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Computing the active duration
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime repeatCount = this->repeatCount();
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime repeatDur = this->repeatDur();
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime simpleDuration = this->simpleDuration();
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!simpleDuration || (repeatDur.isUnresolved() && repeatCount.isUnresolved()))
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return simpleDuration;
8757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    repeatDur = std::min(repeatDur, SMILTime::indefinite());
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime repeatCountDuration = simpleDuration * repeatCount;
8777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!repeatCountDuration.isUnresolved())
8787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return std::min(repeatDur, repeatCountDuration);
8797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return repeatDur;
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Computing the active duration
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime preliminaryActiveDuration;
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resolvedEnd.isUnresolved() && dur().isUnresolved() && repeatDur().isUnresolved() && repeatCount().isUnresolved())
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        preliminaryActiveDuration = resolvedEnd - resolvedBegin;
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (!resolvedEnd.isFinite())
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        preliminaryActiveDuration = repeatingDuration();
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
8925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        preliminaryActiveDuration = std::min(repeatingDuration(), resolvedEnd - resolvedBegin);
89302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime minValue = this->minValue();
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime maxValue = this->maxValue();
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (minValue > maxValue) {
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Ignore both.
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#MinMax
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        minValue = 0;
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        maxValue = SMILTime::indefinite();
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return resolvedBegin + std::min(maxValue, std::max(minValue, preliminaryActiveDuration));
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)SMILInterval SVGSMILElement::resolveInterval(ResolveInterval resolveIntervalType) const
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
907f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    bool first = resolveIntervalType == FirstInterval;
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See the pseudocode in http://www.w3.org/TR/SMIL3/smil-timing.html#q90.
9095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    SMILTime beginAfter = first ? -std::numeric_limits<double>::infinity() : m_interval.end;
9105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    SMILTime lastIntervalTempEnd = std::numeric_limits<double>::infinity();
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
912f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        bool equalsMinimumOK = !first || m_interval.end > m_interval.begin;
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SMILTime tempBegin = findInstanceTime(Begin, beginAfter, equalsMinimumOK);
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (tempBegin.isUnresolved())
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SMILTime tempEnd;
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_endTimes.isEmpty())
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tempEnd = resolveActiveEnd(tempBegin, SMILTime::indefinite());
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tempEnd = findInstanceTime(End, tempBegin, true);
921f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            if ((first && tempBegin == tempEnd && tempEnd == lastIntervalTempEnd) || (!first && tempEnd == m_interval.end))
92202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                tempEnd = findInstanceTime(End, tempBegin, false);
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (tempEnd.isUnresolved()) {
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!m_endTimes.isEmpty() && !m_hasEndEventConditions)
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    break;
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tempEnd = resolveActiveEnd(tempBegin, tempEnd);
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
929f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (!first || (tempEnd > 0 || (!tempBegin.value() && !tempEnd.value())))
930f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return SMILInterval(tempBegin, tempEnd);
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        beginAfter = tempEnd;
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        lastIntervalTempEnd = tempEnd;
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
935f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return SMILInterval(SMILTime::unresolved(), SMILTime::unresolved());
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
93702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::resolveFirstInterval()
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
940f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    SMILInterval firstInterval = resolveInterval(FirstInterval);
941f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(!firstInterval.begin.isIndefinite());
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
943f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!firstInterval.begin.isUnresolved() && firstInterval != m_interval) {
944f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        m_interval = firstInterval;
945a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        notifyDependentsIntervalChanged();
9467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_nextProgressTime = m_nextProgressTime.isUnresolved() ? m_interval.begin : std::min(m_nextProgressTime, m_interval.begin);
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_timeContainer)
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_timeContainer->notifyIntervalsChanged();
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
953a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)bool SVGSMILElement::resolveNextInterval()
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    SMILInterval nextInterval = resolveInterval(NextInterval);
956f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(!nextInterval.begin.isIndefinite());
95702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
958f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!nextInterval.begin.isUnresolved() && nextInterval.begin != m_interval.begin) {
959f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        m_interval = nextInterval;
960a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        notifyDependentsIntervalChanged();
9617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_nextProgressTime = m_nextProgressTime.isUnresolved() ? m_interval.begin : std::min(m_nextProgressTime, m_interval.begin);
9629bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        return true;
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9649bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
9659bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)    return false;
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::nextProgressTime() const
9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_nextProgressTime;
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
97202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::beginListChanged(SMILTime eventTime)
9745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_isWaitingForFirstInterval)
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resolveFirstInterval();
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SMILTime newBegin = findInstanceTime(Begin, eventTime, true);
979f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (newBegin.isFinite() && (m_interval.end <= eventTime || newBegin < m_interval.begin)) {
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Begin time changed, re-resolve the interval.
981f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            SMILTime oldBegin = m_interval.begin;
982f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_interval.end = eventTime;
983f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_interval = resolveInterval(NextInterval);
984f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            ASSERT(!m_interval.begin.isUnresolved());
985f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            if (m_interval.begin != oldBegin) {
986f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                if (m_activeState == Active && m_interval.begin > eventTime) {
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    m_activeState = determineActiveState(eventTime);
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (m_activeState != Active)
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        endedActiveInterval();
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
991a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                notifyDependentsIntervalChanged();
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_nextProgressTime = elapsed();
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer)
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_timeContainer->notifyIntervalsChanged();
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::endListChanged(SMILTime)
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime elapsed = this->elapsed();
1004f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (m_isWaitingForFirstInterval) {
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resolveFirstInterval();
1006f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    } else if (elapsed < m_interval.end && m_interval.begin.isFinite()) {
1007f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        SMILTime newEnd = findInstanceTime(End, m_interval.begin, false);
1008f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (newEnd < m_interval.end) {
1009f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            newEnd = resolveActiveEnd(m_interval.begin, newEnd);
1010f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            if (newEnd != m_interval.end) {
1011f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                m_interval.end = newEnd;
1012a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                notifyDependentsIntervalChanged();
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_nextProgressTime = elapsed;
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_timeContainer)
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_timeContainer->notifyIntervalsChanged();
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
102209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGSMILElement::RestartedInterval SVGSMILElement::maybeRestartInterval(SMILTime elapsed)
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_isWaitingForFirstInterval);
1025f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(elapsed >= m_interval.begin);
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Restart restart = this->restart();
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (restart == RestartNever)
102909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return DidNotRestartInterval;
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1031f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (elapsed < m_interval.end) {
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (restart != RestartAlways)
103309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return DidNotRestartInterval;
1034f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        SMILTime nextBegin = findInstanceTime(Begin, m_interval.begin, false);
1035f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (nextBegin < m_interval.end) {
1036f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_interval.end = nextBegin;
1037a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            notifyDependentsIntervalChanged();
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1041f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (elapsed >= m_interval.end) {
1042f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (resolveNextInterval() && elapsed >= m_interval.begin)
104309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return DidRestartInterval;
104409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
104509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return DidNotRestartInterval;
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::seekToIntervalCorrespondingToTime(SMILTime elapsed)
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_isWaitingForFirstInterval);
1051f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(elapsed >= m_interval.begin);
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Manually seek from interval to interval, just as if the animation would run regulary.
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Figure out the next value in the begin time list after the current interval begin.
1056f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        SMILTime nextBegin = findInstanceTime(Begin, m_interval.begin, false);
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the 'nextBegin' time is unresolved (eg. just one defined interval), we're done seeking.
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (nextBegin.isUnresolved())
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the 'nextBegin' time is larger than or equal to the current interval end time, we're done seeking.
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the 'elapsed' time is smaller than the next begin interval time, we're done seeking.
1064f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (nextBegin < m_interval.end && elapsed >= nextBegin) {
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // End current interval, and start a new interval from the 'nextBegin' time.
1066f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_interval.end = nextBegin;
1067a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (!resolveNextInterval())
10689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)                break;
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If the desired 'elapsed' time is past the current interval, advance to the next.
1073f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (elapsed >= m_interval.end) {
1074a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (!resolveNextInterval())
10759bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)                break;
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGSMILElement::calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime simpleDuration = this->simpleDuration();
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    repeat = 0;
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (simpleDuration.isIndefinite()) {
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        repeat = 0;
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0.f;
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!simpleDuration) {
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        repeat = 0;
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 1.f;
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1095f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_interval.begin.isFinite());
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(simpleDuration.isFinite());
1097f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    SMILTime activeTime = elapsed - m_interval.begin;
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime repeatingDuration = this->repeatingDuration();
1099f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (elapsed >= m_interval.end || activeTime > repeatingDuration) {
110083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        repeat = static_cast<unsigned>(repeatingDuration.value() / simpleDuration.value());
110183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch        if (!fmod(repeatingDuration.value(), simpleDuration.value()))
110283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch            repeat--;
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1104f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        double percent = (m_interval.end.value() - m_interval.begin.value()) / simpleDuration.value();
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        percent = percent - floor(percent);
11065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (percent < std::numeric_limits<float>::epsilon() || 1 - percent < std::numeric_limits<float>::epsilon())
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 1.0f;
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return narrowPrecisionToFloat(percent);
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    repeat = static_cast<unsigned>(activeTime.value() / simpleDuration.value());
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime simpleTime = fmod(activeTime.value(), simpleDuration.value());
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return narrowPrecisionToFloat(simpleTime.value() / simpleDuration.value());
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
111402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SMILTime SVGSMILElement::calculateNextProgressTime(SMILTime elapsed) const
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_activeState == Active) {
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If duration is indefinite the value does not actually change over time. Same is true for <set>.
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SMILTime simpleDuration = this->simpleDuration();
1120d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (simpleDuration.isIndefinite() || isSVGSetElement(*this)) {
1121f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            SMILTime repeatingDurationEnd = m_interval.begin + repeatingDuration();
112202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch            // We are supposed to do freeze semantics when repeating ends, even if the element is still active.
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Take care that we get a timer callback at that point.
1124f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            if (elapsed < repeatingDurationEnd && repeatingDurationEnd < m_interval.end && repeatingDurationEnd.isFinite())
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return repeatingDurationEnd;
1126f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return m_interval.end;
112702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        }
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return elapsed + 0.025;
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1130f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return m_interval.begin >= elapsed ? m_interval.begin : SMILTime::unresolved();
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
113202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGSMILElement::ActiveState SVGSMILElement::determineActiveState(SMILTime elapsed) const
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1135f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (elapsed >= m_interval.begin && elapsed < m_interval.end)
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Active;
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fill() == FillFreeze ? Frozen : Inactive;
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
114002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
114102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdochbool SVGSMILElement::isContributing(SMILTime elapsed) const
114202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Animation does not contribute during the active time if it is past its repeating duration and has fill=remove.
1144f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return (m_activeState == Active && (fill() == FillFreeze || elapsed <= m_interval.begin + repeatingDuration())) || m_activeState == Frozen;
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
114602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGSMILElement::progress(SMILTime elapsed, SVGSMILElement* resultElement, bool seekToTime)
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(resultElement);
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_timeContainer);
1151f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_isWaitingForFirstInterval || m_interval.begin.isFinite());
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
115309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_syncBaseConditionsConnected)
115409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        connectSyncBaseConditions();
1155a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
1156f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!m_interval.begin.isFinite()) {
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_activeState == Inactive);
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_nextProgressTime = SMILTime::unresolved();
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1162f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (elapsed < m_interval.begin) {
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_activeState != Active);
1164f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        bool isFrozen = (m_activeState == Frozen);
1165f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (isFrozen) {
116653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            if (this == resultElement)
116753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                resetAnimatedType();
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            updateAnimation(m_lastPercent, m_lastRepeat, resultElement);
116953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
1170f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        m_nextProgressTime = m_interval.begin;
1171f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // If the animation is frozen, it's still contributing.
1172f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return isFrozen;
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    m_previousIntervalBegin = m_interval.begin;
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_isWaitingForFirstInterval) {
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_isWaitingForFirstInterval = false;
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resolveFirstInterval();
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This call may obtain a new interval -- never call calculateAnimationPercentAndRepeat() before!
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (seekToTime) {
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        seekToIntervalCorrespondingToTime(elapsed);
1185f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (elapsed < m_interval.begin) {
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // elapsed is not within an interval.
1187f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_nextProgressTime = m_interval.begin;
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned repeat = 0;
11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float percent = calculateAnimationPercentAndRepeat(elapsed, repeat);
119409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RestartedInterval restartedInterval = maybeRestartInterval(elapsed);
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ActiveState oldActiveState = m_activeState;
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_activeState = determineActiveState(elapsed);
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool animationIsContributing = isContributing(elapsed);
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Only reset the animated type to the base value once for the lowest priority animation that animates and contributes to a particular element/attribute pair.
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (this == resultElement && animationIsContributing)
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resetAnimatedType();
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationIsContributing) {
120509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (oldActiveState == Inactive || restartedInterval == DidRestartInterval) {
12068abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            smilBeginEventSender().dispatchEventSoon(this);
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            startedActiveInterval();
12088abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        }
12098abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
12108abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        if (repeat && repeat != m_lastRepeat)
12118abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            dispatchRepeatEvents(repeat);
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateAnimation(percent, repeat, resultElement);
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_lastPercent = percent;
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_lastRepeat = repeat;
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
121809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if ((oldActiveState == Active && m_activeState != Active) || restartedInterval == DidRestartInterval) {
12198abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        smilEndEventSender().dispatchEventSoon(this);
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endedActiveInterval();
1221d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (!animationIsContributing && this == resultElement)
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            clearAnimatedType(m_targetElement);
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12258abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // Triggering all the pending events if the animation timeline is changed.
12268abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (seekToTime) {
12278abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        if (m_activeState == Inactive)
12288abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            smilBeginEventSender().dispatchEventSoon(this);
12298abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
12308abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        if (repeat) {
12318abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            for (unsigned repeatEventCount = 1; repeatEventCount < repeat; repeatEventCount++)
12328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)                dispatchRepeatEvents(repeatEventCount);
12338abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            if (m_activeState == Inactive)
12348abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)                dispatchRepeatEvents(repeat);
12358abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        }
12368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
12378abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        if (m_activeState == Inactive || m_activeState == Frozen)
12388abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            smilEndEventSender().dispatchEventSoon(this);
12398abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    }
12408abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_nextProgressTime = calculateNextProgressTime(elapsed);
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return animationIsContributing;
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
124402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1245a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void SVGSMILElement::notifyDependentsIntervalChanged()
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1247f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(m_interval.begin.isFinite());
1248f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // |loopBreaker| is used to avoid infinite recursions which may be caused from:
1249f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // |notifyDependentsIntervalChanged| -> |createInstanceTimesFromSyncbase| -> |add{Begin,End}Time| -> |{begin,end}TimeChanged| -> |notifyDependentsIntervalChanged|
1250f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // |loopBreaker| is defined as a Persistent<HeapHashSet<Member<SVGSMILElement> > >. This won't cause leaks because it is guaranteed to be empty after the root |notifyDependentsIntervalChanged| has exited.
1251f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WillBeHeapHashSet<RawPtrWillBeMember<SVGSMILElement> > >, loopBreaker, (adoptPtrWillBeNoop(new WillBeHeapHashSet<RawPtrWillBeMember<SVGSMILElement> >())));
1252f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (!loopBreaker->add(this).isNewEntry)
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
125402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
125509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    TimeDependentSet::iterator end = m_syncBaseDependents.end();
125609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (TimeDependentSet::iterator it = m_syncBaseDependents.begin(); it != end; ++it) {
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGSMILElement* dependent = *it;
1258a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        dependent->createInstanceTimesFromSyncbase(this);
12595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1261f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    loopBreaker->remove(this);
12625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
126302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1264d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void SVGSMILElement::createInstanceTimesFromSyncbase(SVGSMILElement* syncBase)
12655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
126602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // FIXME: To be really correct, this should handle updating exising interval by changing
12675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the associated times instead of creating new ones.
12685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned n = 0; n < m_conditions.size(); ++n) {
1269d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        Condition* condition = m_conditions[n].get();
1270d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (condition->type() == Condition::Syncbase && condition->syncBase() == syncBase) {
1271d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            ASSERT(condition->name() == "begin" || condition->name() == "end");
12725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // No nested time containers in SVG, no need for crazy time space conversions. Phew!
12735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SMILTime time = 0;
1274d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            if (condition->name() == "begin")
1275f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                time = syncBase->m_interval.begin + condition->offset();
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
1277f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                time = syncBase->m_interval.end + condition->offset();
127809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (!time.isFinite())
127909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                continue;
12807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            SMILTime elapsed = this->elapsed();
12817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (elapsed.isUnresolved())
12827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                continue;
1283d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            if (condition->beginOrEnd() == Begin)
12847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                addBeginTime(elapsed, time);
12855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
12867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                addEndTime(elapsed, time);
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
129002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
129109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::addSyncBaseDependent(SVGSMILElement* animation)
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
129309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_syncBaseDependents.add(animation);
1294f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (m_interval.begin.isFinite())
1295a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        animation->createInstanceTimesFromSyncbase(this);
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
129702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
129809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGSMILElement::removeSyncBaseDependent(SVGSMILElement* animation)
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
130009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_syncBaseDependents.remove(animation);
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
130202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13039bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)void SVGSMILElement::handleConditionEvent(Event* event, Condition* condition)
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1305d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (event->type() == "repeatn" && toRepeatEvent(event)->repeat() != condition->repeat())
13069bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        return;
13079bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime elapsed = this->elapsed();
13097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (elapsed.isUnresolved())
13107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
1311d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (condition->beginOrEnd() == Begin)
1312d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        addBeginTime(elapsed, elapsed + condition->offset());
13135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
1314d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        addEndTime(elapsed, elapsed + condition->offset());
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::beginByLinkActivation()
13185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SMILTime elapsed = this->elapsed();
13207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (elapsed.isUnresolved())
13217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addBeginTime(elapsed, elapsed);
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGSMILElement::endedActiveInterval()
13265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearTimesWithDynamicOrigins(m_beginTimes);
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearTimesWithDynamicOrigins(m_endTimes);
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13318abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)void SVGSMILElement::dispatchRepeatEvents(unsigned count)
13328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
13338abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_repeatEventCountList.append(count);
13348abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilRepeatEventSender().dispatchEventSoon(this);
13358abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    smilRepeatNEventSender().dispatchEventSoon(this);
13368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
13378abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
13388abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)void SVGSMILElement::dispatchPendingEvent(SMILEventSender* eventSender)
13398abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles){
13408abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(eventSender == &smilEndEventSender() || eventSender == &smilBeginEventSender() || eventSender == &smilRepeatEventSender() || eventSender == &smilRepeatNEventSender());
13418abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    const AtomicString& eventType = eventSender->eventType();
13428abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (eventType == "repeatn") {
13438abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        unsigned repeatEventCount = m_repeatEventCountList.first();
13448abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_repeatEventCountList.remove(0);
13459bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)        dispatchEvent(RepeatEvent::create(eventType, repeatEventCount));
13468abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    } else {
13478abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        dispatchEvent(Event::create(eventType));
13488abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    }
13498abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)}
13508abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
1351d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)SVGSMILElement::Condition::~Condition()
1352d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
1353d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
1354d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1355d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void SVGSMILElement::Condition::trace(Visitor* visitor)
1356d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
1357d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_syncBase);
1358d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
1359d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1360323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void SVGSMILElement::trace(Visitor* visitor)
1361323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
1362197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(OILPAN)
1363323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    visitor->trace(m_targetElement);
1364d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_timeContainer);
1365d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_conditions);
1366d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_syncBaseDependents);
1367197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif
1368323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGElement::trace(visitor);
1369323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
1370323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1372