OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 G* * Redistributions in binary form must reproduce the above | 10 G* * Redistributions in binary form must reproduce the above |
(...skipping 15 matching lines...) Expand all Loading... |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #ifndef NewSVGAnimatedProperty_h | 31 #ifndef NewSVGAnimatedProperty_h |
32 #define NewSVGAnimatedProperty_h | 32 #define NewSVGAnimatedProperty_h |
33 | 33 |
34 #include "bindings/v8/ExceptionStatePlaceholder.h" | 34 #include "bindings/v8/ExceptionStatePlaceholder.h" |
35 #include "bindings/v8/ScriptWrappable.h" | 35 #include "bindings/v8/ScriptWrappable.h" |
| 36 #include "core/dom/ExceptionCode.h" |
36 #include "core/svg/SVGParsingError.h" | 37 #include "core/svg/SVGParsingError.h" |
37 #include "core/svg/properties/NewSVGPropertyTearOff.h" | 38 #include "core/svg/properties/NewSVGPropertyTearOff.h" |
38 #include "core/svg/properties/SVGPropertyInfo.h" | 39 #include "core/svg/properties/SVGPropertyInfo.h" |
39 #include "wtf/Noncopyable.h" | 40 #include "wtf/Noncopyable.h" |
40 #include "wtf/PassRefPtr.h" | 41 #include "wtf/PassRefPtr.h" |
41 #include "wtf/RefCounted.h" | 42 #include "wtf/RefCounted.h" |
42 | 43 |
43 namespace WebCore { | 44 namespace WebCore { |
44 | 45 |
45 class SVGElement; | 46 class SVGElement; |
46 | 47 |
47 class NewSVGAnimatedPropertyBase : public RefCounted<NewSVGAnimatedPropertyBase>
{ | 48 class NewSVGAnimatedPropertyBase : public RefCounted<NewSVGAnimatedPropertyBase>
{ |
48 public: | 49 public: |
49 virtual ~NewSVGAnimatedPropertyBase(); | 50 virtual ~NewSVGAnimatedPropertyBase(); |
50 | 51 |
51 virtual NewSVGPropertyBase* baseValueBase() = 0; | 52 virtual NewSVGPropertyBase* baseValueBase() = 0; |
52 virtual NewSVGPropertyBase* currentValueBase() = 0; | 53 virtual NewSVGPropertyBase* currentValueBase() = 0; |
53 | 54 |
54 virtual void animationStarted() = 0; | 55 virtual void animationStarted(); |
55 virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() = 0; | 56 virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() = 0; |
56 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase>) = 0; | 57 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase>) = 0; |
57 virtual void animationEnded() = 0; | 58 virtual void animationEnded(); |
58 virtual void animValWillChange() = 0; | 59 virtual void animValWillChange(); |
59 virtual void animValDidChange() = 0; | 60 virtual void animValDidChange(); |
60 | 61 |
61 virtual bool needsSynchronizeAttribute() = 0; | 62 virtual bool needsSynchronizeAttribute() = 0; |
62 void synchronizeAttribute(); | 63 virtual void synchronizeAttribute(); |
63 | 64 |
64 AnimatedPropertyType type() const | 65 AnimatedPropertyType type() const |
65 { | 66 { |
66 return m_type; | 67 return m_type; |
67 } | 68 } |
68 | 69 |
69 SVGElement* contextElement() | 70 SVGElement* contextElement() |
70 { | 71 { |
71 return m_contextElement; | 72 return m_contextElement; |
72 } | 73 } |
73 | 74 |
74 const QualifiedName& attributeName() const | 75 const QualifiedName& attributeName() const |
75 { | 76 { |
76 return m_attributeName; | 77 return m_attributeName; |
77 } | 78 } |
78 | 79 |
| 80 bool isAnimating() const |
| 81 { |
| 82 return m_isAnimating; |
| 83 } |
| 84 |
| 85 bool isReadOnly() const |
| 86 { |
| 87 return m_isReadOnly; |
| 88 } |
| 89 |
| 90 void setReadOnly() |
| 91 { |
| 92 m_isReadOnly = true; |
| 93 } |
| 94 |
79 protected: | 95 protected: |
80 NewSVGAnimatedPropertyBase(AnimatedPropertyType, SVGElement*, const Qualifie
dName& attributeName); | 96 NewSVGAnimatedPropertyBase(AnimatedPropertyType, SVGElement*, const Qualifie
dName& attributeName); |
| 97 void commitChange(); |
81 | 98 |
82 private: | 99 private: |
83 const AnimatedPropertyType m_type; | 100 const AnimatedPropertyType m_type; |
| 101 bool m_isReadOnly; |
| 102 bool m_isAnimating; |
84 | 103 |
85 // This reference is kept alive from V8 wrapper | 104 // This reference is kept alive from V8 wrapper |
86 SVGElement* m_contextElement; | 105 SVGElement* m_contextElement; |
87 | 106 |
88 const QualifiedName& m_attributeName; | 107 const QualifiedName& m_attributeName; |
89 | 108 |
90 WTF_MAKE_NONCOPYABLE(NewSVGAnimatedPropertyBase); | 109 WTF_MAKE_NONCOPYABLE(NewSVGAnimatedPropertyBase); |
91 }; | 110 }; |
92 | 111 |
93 template <typename Property> | 112 template <typename Property> |
94 class NewSVGAnimatedProperty : public NewSVGAnimatedPropertyBase { | 113 class NewSVGAnimatedPropertyCommon : public NewSVGAnimatedPropertyBase { |
95 public: | 114 public: |
96 typedef typename Property::TearOffType TearOffType; | |
97 | |
98 static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* cont
extElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValu
e) | |
99 { | |
100 return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, att
ributeName, initialValue)); | |
101 } | |
102 | |
103 ~NewSVGAnimatedProperty() | |
104 { | |
105 ASSERT(!isAnimating()); | |
106 } | |
107 | |
108 bool isReadOnly() const | |
109 { | |
110 return m_isReadOnly; | |
111 } | |
112 | |
113 void setReadOnly() | |
114 { | |
115 m_isReadOnly = true; | |
116 } | |
117 | |
118 Property* baseValue() | 115 Property* baseValue() |
119 { | 116 { |
120 return m_baseValue.get(); | 117 return m_baseValue.get(); |
121 } | 118 } |
122 | 119 |
123 virtual NewSVGPropertyBase* baseValueBase() | 120 virtual NewSVGPropertyBase* baseValueBase() OVERRIDE |
124 { | 121 { |
125 return baseValue(); | 122 return baseValue(); |
126 } | 123 } |
127 | 124 |
128 Property* currentValue() | 125 Property* currentValue() |
129 { | 126 { |
130 return m_currentValue ? m_currentValue.get() : m_baseValue.get(); | 127 return m_currentValue ? m_currentValue.get() : m_baseValue.get(); |
131 } | 128 } |
132 | 129 |
133 virtual NewSVGPropertyBase* currentValueBase() | 130 virtual NewSVGPropertyBase* currentValueBase() OVERRIDE |
134 { | 131 { |
135 return currentValue(); | 132 return currentValue(); |
136 } | 133 } |
137 | 134 |
138 void setBaseValueAsString(const String& value, SVGParsingError& parseError) | 135 void setBaseValueAsString(const String& value, SVGParsingError& parseError) |
139 { | 136 { |
140 TrackExceptionState es; | 137 TrackExceptionState es; |
141 | 138 |
142 m_baseValue->setValueAsString(value, es); | 139 m_baseValue->setValueAsString(value, es); |
| 140 commitChange(); |
143 | 141 |
144 if (es.hadException()) | 142 if (es.hadException()) |
145 parseError = ParsingAttributeFailedError; | 143 parseError = ParsingAttributeFailedError; |
146 } | 144 } |
147 | 145 |
148 bool isAnimating() const | 146 virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() OVERRIDE |
149 { | |
150 return m_isAnimating; | |
151 } | |
152 | |
153 virtual void animationStarted() | |
154 { | |
155 ASSERT(!isAnimating()); | |
156 m_isAnimating = true; | |
157 } | |
158 | |
159 virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() | |
160 { | 147 { |
161 return m_baseValue->clone(); | 148 return m_baseValue->clone(); |
162 } | 149 } |
163 | 150 |
164 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) | 151 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> passValue) OVER
RIDE |
165 { | 152 { |
166 ASSERT(isAnimating()); | 153 ASSERT(isAnimating()); |
167 | 154 |
168 // FIXME: add type check | 155 RefPtr<NewSVGPropertyBase> value = passValue; |
169 m_currentValue = static_pointer_cast<Property>(value); | 156 ASSERT(value->type() == Property::classType()); |
170 | 157 m_currentValue = static_pointer_cast<Property>(value.release()); |
171 if (m_animValTearOff) | |
172 m_animValTearOff->setTarget(m_currentValue); | |
173 } | 158 } |
174 | 159 |
175 virtual void animationEnded() | 160 virtual void animationEnded() OVERRIDE |
176 { | 161 { |
177 ASSERT(isAnimating()); | 162 NewSVGAnimatedPropertyBase::animationEnded(); |
178 m_isAnimating = false; | |
179 | 163 |
180 ASSERT(m_currentValue); | 164 ASSERT(m_currentValue); |
181 m_currentValue.clear(); | 165 m_currentValue.clear(); |
182 | |
183 if (m_animValTearOff) | |
184 m_animValTearOff->setTarget(m_baseValue); | |
185 } | 166 } |
186 | 167 |
187 virtual void animValWillChange() | 168 protected: |
| 169 NewSVGAnimatedPropertyCommon(SVGElement* contextElement, const QualifiedName
& attributeName, PassRefPtr<Property> initialValue) |
| 170 : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attr
ibuteName) |
| 171 , m_baseValue(initialValue) |
188 { | 172 { |
189 ASSERT(isAnimating()); | |
190 } | 173 } |
191 | 174 |
192 virtual void animValDidChange() | 175 private: |
| 176 RefPtr<Property> m_baseValue; |
| 177 RefPtr<Property> m_currentValue; |
| 178 }; |
| 179 |
| 180 // Implementation of SVGAnimatedProperty which has tear-off value types. |
| 181 // This is for classes which return special type for its "animVal". |
| 182 // Examples are SVGAnimatedLength, SVGAnimatedRect, SVGAnimated*List, etc. |
| 183 template <typename Property, typename TearOffType = typename Property::TearOffTy
pe> |
| 184 class NewSVGAnimatedProperty : public NewSVGAnimatedPropertyCommon<Property> { |
| 185 public: |
| 186 static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* cont
extElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValu
e) |
193 { | 187 { |
194 ASSERT(isAnimating()); | 188 return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, att
ributeName, initialValue)); |
195 } | 189 } |
196 | 190 |
197 virtual bool needsSynchronizeAttribute() | 191 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) OVERRIDE |
| 192 { |
| 193 NewSVGAnimatedPropertyCommon<Property>::setAnimatedValue(value); |
| 194 updateAnimValTearOffIfNeeded(); |
| 195 } |
| 196 |
| 197 virtual void animationEnded() OVERRIDE |
| 198 { |
| 199 NewSVGAnimatedPropertyCommon<Property>::animationEnded(); |
| 200 updateAnimValTearOffIfNeeded(); |
| 201 } |
| 202 |
| 203 virtual bool needsSynchronizeAttribute() OVERRIDE |
198 { | 204 { |
199 // DOM attribute synchronization is only needed if tear-off is being tou
ched from javascript or the property is being animated. | 205 // DOM attribute synchronization is only needed if tear-off is being tou
ched from javascript or the property is being animated. |
200 // This prevents unnecessary attribute creation on target element. | 206 // This prevents unnecessary attribute creation on target element. |
201 return m_baseValTearOff || isAnimating(); | 207 return m_baseValTearOff || this->isAnimating(); |
202 } | 208 } |
203 | 209 |
204 // SVGAnimated* DOM Spec implementations: | 210 // SVGAnimated* DOM Spec implementations: |
205 | 211 |
206 // baseVal()/animVal() are only to be used from SVG DOM implementation. | 212 // baseVal()/animVal() are only to be used from SVG DOM implementation. |
207 // Use currentValue() from C++ code. | 213 // Use currentValue() from C++ code. |
208 virtual TearOffType* baseVal() | 214 virtual TearOffType* baseVal() |
209 { | 215 { |
210 if (!m_baseValTearOff) | 216 if (!m_baseValTearOff) |
211 m_baseValTearOff = TearOffType::create(m_baseValue, contextElement()
, PropertyIsNotAnimVal, attributeName()); | 217 m_baseValTearOff = TearOffType::create(this->baseValue(), this->cont
extElement(), PropertyIsNotAnimVal, this->attributeName()); |
212 | 218 |
213 return m_baseValTearOff.get(); | 219 return m_baseValTearOff.get(); |
214 } | 220 } |
215 | 221 |
216 TearOffType* animVal() | 222 TearOffType* animVal() |
217 { | 223 { |
218 if (!m_animValTearOff) | 224 if (!m_animValTearOff) |
219 m_animValTearOff = TearOffType::create(currentValue(), contextElemen
t(), PropertyIsAnimVal, attributeName()); | 225 m_animValTearOff = TearOffType::create(this->currentValue(), this->c
ontextElement(), PropertyIsAnimVal, this->attributeName()); |
220 | 226 |
221 return m_animValTearOff.get(); | 227 return m_animValTearOff.get(); |
222 } | 228 } |
223 | 229 |
224 protected: | 230 protected: |
225 NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attr
ibuteName, PassRefPtr<Property> initialValue) | 231 NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attr
ibuteName, PassRefPtr<Property> initialValue) |
226 : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attr
ibuteName) | 232 : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName,
initialValue) |
227 , m_isReadOnly(false) | |
228 , m_isAnimating(false) | |
229 , m_baseValue(initialValue) | |
230 { | 233 { |
231 } | 234 } |
232 | 235 |
233 private: | 236 private: |
234 bool m_isReadOnly; | 237 void updateAnimValTearOffIfNeeded() |
235 bool m_isAnimating; | 238 { |
| 239 if (m_animValTearOff) |
| 240 m_animValTearOff->setTarget(this->currentValue()); |
| 241 } |
236 | 242 |
237 // When still (not animated): | 243 // When still (not animated): |
238 // Both m_animValTearOff and m_baseValTearOff target m_baseValue. | 244 // Both m_animValTearOff and m_baseValTearOff target m_baseValue. |
239 // When animated: | 245 // When animated: |
240 // m_animValTearOff targets m_currentValue. | 246 // m_animValTearOff targets m_currentValue. |
241 // m_baseValTearOff targets m_baseValue. | 247 // m_baseValTearOff targets m_baseValue. |
242 RefPtr<Property> m_baseValue; | |
243 RefPtr<Property> m_currentValue; | |
244 RefPtr<TearOffType> m_baseValTearOff; | 248 RefPtr<TearOffType> m_baseValTearOff; |
245 RefPtr<TearOffType> m_animValTearOff; | 249 RefPtr<TearOffType> m_animValTearOff; |
246 }; | 250 }; |
247 | 251 |
| 252 // Implementation of SVGAnimatedProperty which uses primitive types. |
| 253 // This is for classes which return primitive type for its "animVal". |
| 254 // Examples are SVGAnimatedBoolean, SVGAnimatedNumber, etc. |
| 255 // This is implemented as template specialization used when TearOffType is set t
o void. |
| 256 template <typename Property> |
| 257 class NewSVGAnimatedProperty<Property, void> : public NewSVGAnimatedPropertyComm
on<Property> { |
| 258 public: |
| 259 typedef typename Property::PrimitiveType PrimitiveType; |
| 260 |
| 261 static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* cont
extElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValu
e) |
| 262 { |
| 263 return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, att
ributeName, initialValue)); |
| 264 } |
| 265 |
| 266 virtual bool needsSynchronizeAttribute() OVERRIDE |
| 267 { |
| 268 // DOM attribute synchronization is only needed if tear-off is being tou
ched from javascript or the property is being animated. |
| 269 // This prevents unnecessary attribute creation on target element. |
| 270 return m_baseValueUpdated || this->isAnimating(); |
| 271 } |
| 272 |
| 273 virtual void synchronizeAttribute() OVERRIDE |
| 274 { |
| 275 NewSVGAnimatedPropertyBase::synchronizeAttribute(); |
| 276 m_baseValueUpdated = false; |
| 277 } |
| 278 |
| 279 // SVGAnimated* DOM Spec implementations: |
| 280 |
| 281 // baseVal()/setBaseVal()/animVal() are only to be used from SVG DOM impleme
ntation. |
| 282 // Use currentValue() from C++ code. |
| 283 PrimitiveType baseVal() |
| 284 { |
| 285 return this->baseValue()->value(); |
| 286 } |
| 287 |
| 288 void setBaseVal(PrimitiveType value, WebCore::ExceptionState& exceptionState
) |
| 289 { |
| 290 if (this->isReadOnly()) { |
| 291 exceptionState.throwDOMException(NoModificationAllowedError, "The at
tribute is read-only."); |
| 292 return; |
| 293 } |
| 294 |
| 295 this->baseValue()->setValue(value); |
| 296 |
| 297 ASSERT(this->attributeName() != nullQName()); |
| 298 this->contextElement()->invalidateSVGAttributes(); |
| 299 this->contextElement()->svgAttributeChanged(this->attributeName()); |
| 300 |
| 301 m_baseValueUpdated = true; |
| 302 } |
| 303 |
| 304 PrimitiveType animVal() |
| 305 { |
| 306 return this->currentValue()->value(); |
| 307 } |
| 308 |
| 309 protected: |
| 310 NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attr
ibuteName, PassRefPtr<Property> initialValue) |
| 311 : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName,
initialValue) |
| 312 , m_baseValueUpdated(false) |
| 313 { |
| 314 } |
| 315 |
| 316 bool m_baseValueUpdated; |
| 317 }; |
| 318 |
248 } | 319 } |
249 | 320 |
250 #endif // NewSVGAnimatedProperty_h | 321 #endif // NewSVGAnimatedProperty_h |
OLD | NEW |