1 | /* |
2 | * Copyright (C) 2018-2019 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include "SVGAnimatedProperty.h" |
29 | |
30 | namespace WebCore { |
31 | |
32 | template<typename PropertyType> |
33 | class SVGAnimatedValueProperty : public SVGAnimatedProperty { |
34 | public: |
35 | using ValueType = typename PropertyType::ValueType; |
36 | |
37 | template<typename... Arguments> |
38 | static Ref<SVGAnimatedValueProperty> create(SVGElement* contextElement, Arguments&&... arguments) |
39 | { |
40 | return adoptRef(*new SVGAnimatedValueProperty(contextElement, std::forward<Arguments>(arguments)...)); |
41 | } |
42 | |
43 | ~SVGAnimatedValueProperty() |
44 | { |
45 | m_baseVal->detach(); |
46 | if (m_animVal) |
47 | m_animVal->detach(); |
48 | } |
49 | |
50 | // Used by SVGElement::parseAttribute(). |
51 | void setBaseValInternal(const ValueType& baseVal) |
52 | { |
53 | m_baseVal->setValue(baseVal); |
54 | if (m_animVal) |
55 | m_animVal->setValue(baseVal); |
56 | } |
57 | |
58 | // Used by the DOM. |
59 | const Ref<PropertyType>& baseVal() const { return m_baseVal; } |
60 | |
61 | Ref<PropertyType>& baseVal() { return m_baseVal; } |
62 | |
63 | // Used by SVGAnimator::progress. |
64 | void setAnimVal(const ValueType& animVal) |
65 | { |
66 | ASSERT(isAnimating() && m_animVal); |
67 | m_animVal->setValue(animVal); |
68 | } |
69 | |
70 | // Used by the DOM. |
71 | const RefPtr<PropertyType>& animVal() const { return const_cast<SVGAnimatedValueProperty*>(this)->ensureAnimVal(); } |
72 | |
73 | // Called by SVGAnimatedPropertyAnimator to pass the animVal to the SVGAnimationFunction::progress. |
74 | RefPtr<PropertyType>& animVal() { return ensureAnimVal(); } |
75 | |
76 | // Used when committing a change from the SVGAnimatedProperty to the attribute. |
77 | String baseValAsString() const override { return m_baseVal->valueAsString(); } |
78 | |
79 | // Used to apply the SVGAnimator change to the target element. |
80 | String animValAsString() const override |
81 | { |
82 | ASSERT(isAnimating() && m_animVal); |
83 | return m_animVal->valueAsString(); |
84 | } |
85 | |
86 | // Managing the relationship with the owner. |
87 | void setDirty() override { m_baseVal->setDirty(); } |
88 | bool isDirty() const override { return m_baseVal->isDirty(); } |
89 | Optional<String> synchronize() override { return m_baseVal->synchronize(); } |
90 | |
91 | // Used by RenderSVGElements and DumpRenderTree. |
92 | const ValueType& currentValue() const |
93 | { |
94 | ASSERT_IMPLIES(isAnimating(), m_animVal); |
95 | return (isAnimating() ? *m_animVal : m_baseVal.get()).value(); |
96 | } |
97 | |
98 | // Controlling the animation. |
99 | void startAnimation() override |
100 | { |
101 | if (m_animVal) |
102 | m_animVal->setValue(m_baseVal->value()); |
103 | else |
104 | ensureAnimVal(); |
105 | SVGAnimatedProperty::startAnimation(); |
106 | } |
107 | |
108 | void stopAnimation() override |
109 | { |
110 | if (m_animVal) |
111 | m_animVal->setValue(m_baseVal->value()); |
112 | SVGAnimatedProperty::stopAnimation(); |
113 | } |
114 | |
115 | // Controlling the instance animation. |
116 | void instanceStartAnimation(SVGAnimatedProperty& animated) override |
117 | { |
118 | m_animVal = static_cast<SVGAnimatedValueProperty&>(animated).animVal(); |
119 | SVGAnimatedProperty::instanceStartAnimation(animated); |
120 | } |
121 | |
122 | void instanceStopAnimation() override |
123 | { |
124 | m_animVal = nullptr; |
125 | SVGAnimatedProperty::instanceStopAnimation(); |
126 | } |
127 | |
128 | protected: |
129 | // The packed arguments are used in PropertyType creation, for example passing |
130 | // SVGLengthMode to SVGLength. |
131 | template<typename... Arguments> |
132 | SVGAnimatedValueProperty(SVGElement* contextElement, Arguments&&... arguments) |
133 | : SVGAnimatedProperty(contextElement) |
134 | , m_baseVal(PropertyType::create(this, SVGPropertyAccess::ReadWrite, ValueType(std::forward<Arguments>(arguments)...))) |
135 | { |
136 | } |
137 | |
138 | template<typename... Arguments> |
139 | SVGAnimatedValueProperty(SVGElement* contextElement, SVGPropertyAccess access, Arguments&&... arguments) |
140 | : SVGAnimatedProperty(contextElement) |
141 | , m_baseVal(PropertyType::create(this, access, ValueType(std::forward<Arguments>(arguments)...))) |
142 | { |
143 | } |
144 | |
145 | RefPtr<PropertyType>& ensureAnimVal() |
146 | { |
147 | if (!m_animVal) |
148 | m_animVal = PropertyType::create(this, SVGPropertyAccess::ReadOnly, m_baseVal->value()); |
149 | return m_animVal; |
150 | } |
151 | |
152 | // Called when m_baseVal changes. |
153 | void commitPropertyChange(SVGProperty* property) override |
154 | { |
155 | if (m_animVal) |
156 | m_animVal->setValue(m_baseVal->value()); |
157 | SVGAnimatedProperty::commitPropertyChange(property); |
158 | } |
159 | |
160 | Ref<PropertyType> m_baseVal; |
161 | mutable RefPtr<PropertyType> m_animVal; |
162 | }; |
163 | |
164 | } |
165 | |