1/*
2 * Copyright (C) Research In Motion Limited 2010, 2012. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#ifndef SVGAnimatedPathSegListPropertyTearOff_h
21#define SVGAnimatedPathSegListPropertyTearOff_h
22
23#include "SVGAnimatedListPropertyTearOff.h"
24#include "SVGPathByteStream.h"
25#include "SVGPathElement.h"
26#include "SVGPathSegList.h"
27#include "SVGPathSegListPropertyTearOff.h"
28#include "SVGPathUtilities.h"
29
30namespace WebCore {
31
32class SVGAnimatedPathSegListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGPathSegList> {
33public:
34    virtual SVGListProperty<SVGPathSegList>* baseVal() override
35    {
36        if (!m_baseVal)
37            m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, PathSegUnalteredRole, m_values, m_wrappers);
38        return static_cast<SVGListProperty<SVGPathSegList>*>(m_baseVal.get());
39    }
40
41    virtual SVGListProperty<SVGPathSegList>* animVal() override
42    {
43        if (!m_animVal)
44            m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, PathSegUnalteredRole, m_values, m_wrappers);
45        return static_cast<SVGListProperty<SVGPathSegList>*>(m_animVal.get());
46    }
47
48    int findItem(const RefPtr<SVGPathSeg>& segment) const
49    {
50        // This should ever be called for our baseVal, as animVal can't modify the list.
51        ASSERT(m_baseVal);
52        return static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->findItem(segment);
53    }
54
55    void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers)
56    {
57        // This should ever be called for our baseVal, as animVal can't modify the list.
58        ASSERT(m_baseVal);
59        static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers);
60    }
61
62    static PassRefPtr<SVGAnimatedPathSegListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegList& values)
63    {
64        ASSERT(contextElement);
65        return adoptRef(new SVGAnimatedPathSegListPropertyTearOff(contextElement, attributeName, animatedPropertyType, values));
66    }
67
68    using SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationStarted;
69    void animationStarted(SVGPathByteStream* byteStream, const SVGPathSegList* baseValue)
70    {
71        ASSERT(byteStream);
72        ASSERT(baseValue);
73        ASSERT(!m_animatedPathByteStream);
74        m_animatedPathByteStream = byteStream;
75
76        // Pass shouldOwnValues=true, as the SVGPathSegList lifetime is solely managed by its tear off class.
77        SVGPathSegList* copy = new SVGPathSegList(*baseValue);
78        SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationStarted(copy, true);
79    }
80
81    void animationEnded()
82    {
83        ASSERT(m_animatedPathByteStream);
84        m_animatedPathByteStream = 0;
85        SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationEnded();
86    }
87
88    void animValDidChange()
89    {
90        ASSERT(m_animatedPathByteStream);
91        SVGPathElement* pathElement = toSVGPathElement(contextElement());
92
93        // If the animVal is observed from JS, we have to update it on each animation step.
94        // This is an expensive operation and only done, if someone actually observes the animatedPathSegList() while an animation is running.
95        if (pathElement->isAnimValObserved()) {
96            SVGPathSegList& animatedList = currentAnimatedValue();
97            animatedList.clear();
98            buildSVGPathSegListFromByteStream(m_animatedPathByteStream, pathElement, animatedList, UnalteredParsing);
99        }
100
101        SVGAnimatedListPropertyTearOff<SVGPathSegList>::animValDidChange();
102    }
103
104    SVGPathByteStream* animatedPathByteStream() const { return m_animatedPathByteStream; }
105
106private:
107    SVGAnimatedPathSegListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegList& values)
108        : SVGAnimatedListPropertyTearOff<SVGPathSegList>(contextElement, attributeName, animatedPropertyType, values)
109        , m_animatedPathByteStream(0)
110    {
111    }
112
113    SVGPathByteStream* m_animatedPathByteStream;
114};
115
116}
117
118#endif // SVGAnimatedPathSegListPropertyTearOff_h
119