OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple 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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "core/svg/animation/SVGSMILElement.h" | 26 #include "core/svg/animation/SVGSMILElement.h" |
27 | 27 |
| 28 #include <algorithm> |
28 #include "bindings/core/v8/ScriptEventListener.h" | 29 #include "bindings/core/v8/ScriptEventListener.h" |
29 #include "core/XLinkNames.h" | 30 #include "core/XLinkNames.h" |
30 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
| 32 #include "core/dom/IdTargetObserver.h" |
31 #include "core/dom/TaskRunnerHelper.h" | 33 #include "core/dom/TaskRunnerHelper.h" |
32 #include "core/events/Event.h" | 34 #include "core/events/Event.h" |
33 #include "core/events/EventListener.h" | 35 #include "core/events/EventListener.h" |
34 #include "core/svg/SVGSVGElement.h" | 36 #include "core/svg/SVGSVGElement.h" |
35 #include "core/svg/SVGTreeScopeResources.h" | |
36 #include "core/svg/SVGURIReference.h" | 37 #include "core/svg/SVGURIReference.h" |
37 #include "core/svg/animation/SMILTimeContainer.h" | 38 #include "core/svg/animation/SMILTimeContainer.h" |
38 #include "platform/heap/Handle.h" | 39 #include "platform/heap/Handle.h" |
39 #include "wtf/MathExtras.h" | 40 #include "wtf/MathExtras.h" |
40 #include "wtf/StdLibExtras.h" | 41 #include "wtf/StdLibExtras.h" |
41 #include "wtf/Vector.h" | 42 #include "wtf/Vector.h" |
42 #include <algorithm> | |
43 | 43 |
44 namespace blink { | 44 namespace blink { |
45 | 45 |
46 class RepeatEvent final : public Event { | 46 class RepeatEvent final : public Event { |
47 public: | 47 public: |
48 static RepeatEvent* create(const AtomicString& type, int repeat) { | 48 static RepeatEvent* create(const AtomicString& type, int repeat) { |
49 return new RepeatEvent(type, false, false, repeat); | 49 return new RepeatEvent(type, false, false, repeat); |
50 } | 50 } |
51 | 51 |
52 ~RepeatEvent() override {} | 52 ~RepeatEvent() override {} |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 m_beginOrEnd(beginOrEnd), | 138 m_beginOrEnd(beginOrEnd), |
139 m_baseID(baseID), | 139 m_baseID(baseID), |
140 m_name(name), | 140 m_name(name), |
141 m_offset(offset), | 141 m_offset(offset), |
142 m_repeat(repeat) {} | 142 m_repeat(repeat) {} |
143 | 143 |
144 SVGSMILElement::Condition::~Condition() = default; | 144 SVGSMILElement::Condition::~Condition() = default; |
145 | 145 |
146 DEFINE_TRACE(SVGSMILElement::Condition) { | 146 DEFINE_TRACE(SVGSMILElement::Condition) { |
147 visitor->trace(m_baseElement); | 147 visitor->trace(m_baseElement); |
| 148 visitor->trace(m_baseIdObserver); |
148 visitor->trace(m_eventListener); | 149 visitor->trace(m_eventListener); |
149 } | 150 } |
150 | 151 |
151 void SVGSMILElement::Condition::connectSyncBase(SVGSMILElement& timedElement) { | 152 void SVGSMILElement::Condition::connectSyncBase(SVGSMILElement& timedElement) { |
152 DCHECK(!m_baseID.isEmpty()); | 153 DCHECK(!m_baseID.isEmpty()); |
153 DCHECK_EQ(m_type, Syncbase); | 154 DCHECK_EQ(m_type, Syncbase); |
154 Element* element = timedElement.treeScope().getElementById(m_baseID); | 155 Element* element = timedElement.treeScope().getElementById(m_baseID); |
155 if (!element || !isSVGSMILElement(*element)) { | 156 if (!element || !isSVGSMILElement(*element)) { |
156 m_baseElement = nullptr; | 157 m_baseElement = nullptr; |
157 return; | 158 return; |
158 } | 159 } |
159 m_baseElement = toSVGSMILElement(element); | 160 m_baseElement = toSVGSMILElement(element); |
160 toSVGSMILElement(*element).addSyncBaseDependent(timedElement); | 161 toSVGSMILElement(*element).addSyncBaseDependent(timedElement); |
161 } | 162 } |
162 | 163 |
163 void SVGSMILElement::Condition::disconnectSyncBase( | 164 void SVGSMILElement::Condition::disconnectSyncBase( |
164 SVGSMILElement& timedElement) { | 165 SVGSMILElement& timedElement) { |
165 DCHECK_EQ(m_type, Syncbase); | 166 DCHECK_EQ(m_type, Syncbase); |
166 if (!m_baseElement) | 167 if (!m_baseElement) |
167 return; | 168 return; |
168 toSVGSMILElement(*m_baseElement).removeSyncBaseDependent(timedElement); | 169 toSVGSMILElement(*m_baseElement).removeSyncBaseDependent(timedElement); |
169 m_baseElement = nullptr; | 170 m_baseElement = nullptr; |
170 } | 171 } |
171 | 172 |
172 SVGElement* SVGSMILElement::Condition::lookupEventBase( | |
173 SVGSMILElement& timedElement) const { | |
174 Element* eventBase = m_baseID.isEmpty() | |
175 ? timedElement.targetElement() | |
176 : timedElement.treeScope().getElementById(m_baseID); | |
177 if (!eventBase || !eventBase->isSVGElement()) | |
178 return nullptr; | |
179 return toSVGElement(eventBase); | |
180 } | |
181 | |
182 void SVGSMILElement::Condition::connectEventBase(SVGSMILElement& timedElement) { | 173 void SVGSMILElement::Condition::connectEventBase(SVGSMILElement& timedElement) { |
183 DCHECK_EQ(m_type, EventBase); | 174 DCHECK_EQ(m_type, EventBase); |
184 DCHECK(!m_baseElement); | 175 DCHECK(!m_baseElement); |
185 SVGElement* eventBase = lookupEventBase(timedElement); | 176 Element* target; |
186 if (!eventBase) { | 177 if (m_baseID.isEmpty()) { |
187 if (m_baseID.isEmpty()) | 178 target = timedElement.targetElement(); |
188 return; | 179 } else { |
189 SVGTreeScopeResources& treeScopeResources = | 180 target = SVGURIReference::observeTarget( |
190 timedElement.treeScope().ensureSVGTreeScopedResources(); | 181 m_baseIdObserver, timedElement.treeScope(), m_baseID, |
191 if (!treeScopeResources.isElementPendingResource(timedElement, m_baseID)) | 182 WTF::bind(&SVGSMILElement::buildPendingResource, |
192 treeScopeResources.addPendingResource(m_baseID, timedElement); | 183 wrapWeakPersistent(&timedElement))); |
| 184 } |
| 185 if (!target || !target->isSVGElement()) |
193 return; | 186 return; |
194 } | |
195 DCHECK(!m_eventListener); | 187 DCHECK(!m_eventListener); |
196 m_eventListener = ConditionEventListener::create(&timedElement, this); | 188 m_eventListener = ConditionEventListener::create(&timedElement, this); |
197 m_baseElement = eventBase; | 189 m_baseElement = toSVGElement(target); |
198 m_baseElement->addEventListener(m_name, m_eventListener, false); | 190 m_baseElement->addEventListener(m_name, m_eventListener, false); |
199 timedElement.addReferenceTo(m_baseElement); | 191 timedElement.addReferenceTo(m_baseElement); |
200 } | 192 } |
201 | 193 |
202 void SVGSMILElement::Condition::disconnectEventBase( | 194 void SVGSMILElement::Condition::disconnectEventBase( |
203 SVGSMILElement& timedElement) { | 195 SVGSMILElement& timedElement) { |
204 DCHECK_EQ(m_type, EventBase); | 196 DCHECK_EQ(m_type, EventBase); |
| 197 SVGURIReference::unobserveTarget(m_baseIdObserver); |
205 if (!m_eventListener) | 198 if (!m_eventListener) |
206 return; | 199 return; |
207 m_baseElement->removeEventListener(m_name, m_eventListener, false); | 200 m_baseElement->removeEventListener(m_name, m_eventListener, false); |
208 m_baseElement = nullptr; | 201 m_baseElement = nullptr; |
209 m_eventListener->disconnectAnimation(); | 202 m_eventListener->disconnectAnimation(); |
210 m_eventListener = nullptr; | 203 m_eventListener = nullptr; |
211 } | 204 } |
212 | 205 |
213 SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc) | 206 SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc) |
214 : SVGElement(tagName, doc), | 207 : SVGElement(tagName, doc), |
(...skipping 15 matching lines...) Expand all Loading... |
230 m_cachedRepeatDur(invalidCachedTime), | 223 m_cachedRepeatDur(invalidCachedTime), |
231 m_cachedRepeatCount(invalidCachedTime), | 224 m_cachedRepeatCount(invalidCachedTime), |
232 m_cachedMin(invalidCachedTime), | 225 m_cachedMin(invalidCachedTime), |
233 m_cachedMax(invalidCachedTime) { | 226 m_cachedMax(invalidCachedTime) { |
234 resolveFirstInterval(); | 227 resolveFirstInterval(); |
235 } | 228 } |
236 | 229 |
237 SVGSMILElement::~SVGSMILElement() {} | 230 SVGSMILElement::~SVGSMILElement() {} |
238 | 231 |
239 void SVGSMILElement::clearResourceAndEventBaseReferences() { | 232 void SVGSMILElement::clearResourceAndEventBaseReferences() { |
| 233 SVGURIReference::unobserveTarget(m_targetIdObserver); |
240 removeAllOutgoingReferences(); | 234 removeAllOutgoingReferences(); |
241 } | 235 } |
242 | 236 |
243 void SVGSMILElement::clearConditions() { | 237 void SVGSMILElement::clearConditions() { |
244 disconnectSyncBaseConditions(); | 238 disconnectSyncBaseConditions(); |
245 disconnectEventBaseConditions(); | 239 disconnectEventBaseConditions(); |
246 m_conditions.clear(); | 240 m_conditions.clear(); |
247 } | 241 } |
248 | 242 |
249 void SVGSMILElement::buildPendingResource() { | 243 void SVGSMILElement::buildPendingResource() { |
250 clearResourceAndEventBaseReferences(); | 244 clearResourceAndEventBaseReferences(); |
| 245 disconnectEventBaseConditions(); |
251 | 246 |
252 if (!isConnected()) { | 247 if (!isConnected()) { |
253 // Reset the target element if we are no longer in the document. | 248 // Reset the target element if we are no longer in the document. |
254 setTargetElement(nullptr); | 249 setTargetElement(nullptr); |
255 return; | 250 return; |
256 } | 251 } |
257 | 252 |
258 AtomicString id; | |
259 const AtomicString& href = SVGURIReference::legacyHrefString(*this); | 253 const AtomicString& href = SVGURIReference::legacyHrefString(*this); |
260 Element* target; | 254 Element* target; |
261 if (href.isEmpty()) | 255 if (href.isEmpty()) { |
262 target = parentNode() && parentNode()->isElementNode() | 256 target = parentElement(); |
263 ? toElement(parentNode()) | 257 } else { |
264 : nullptr; | 258 target = SVGURIReference::observeTarget(m_targetIdObserver, *this, href); |
265 else | 259 } |
266 target = | |
267 SVGURIReference::targetElementFromIRIString(href, treeScope(), &id); | |
268 SVGElement* svgTarget = | 260 SVGElement* svgTarget = |
269 target && target->isSVGElement() ? toSVGElement(target) : nullptr; | 261 target && target->isSVGElement() ? toSVGElement(target) : nullptr; |
270 | 262 |
271 if (svgTarget && !svgTarget->isConnected()) | 263 if (svgTarget && !svgTarget->isConnected()) |
272 svgTarget = nullptr; | 264 svgTarget = nullptr; |
273 | 265 |
274 if (svgTarget != targetElement()) | 266 if (svgTarget != targetElement()) |
275 setTargetElement(svgTarget); | 267 setTargetElement(svgTarget); |
276 | 268 |
277 if (!svgTarget) { | 269 if (svgTarget) { |
278 // Do not register as pending if we are already pending this resource. | |
279 if (treeScope().ensureSVGTreeScopedResources().isElementPendingResource( | |
280 *this, id)) | |
281 return; | |
282 if (!id.isEmpty()) { | |
283 treeScope().ensureSVGTreeScopedResources().addPendingResource(id, *this); | |
284 DCHECK(hasPendingResources()); | |
285 } | |
286 } else { | |
287 // Register us with the target in the dependencies map. Any change of | 270 // Register us with the target in the dependencies map. Any change of |
288 // hrefElement that leads to relayout/repainting now informs us, so we can | 271 // hrefElement that leads to relayout/repainting now informs us, so we can |
289 // react to it. | 272 // react to it. |
290 addReferenceTo(svgTarget); | 273 addReferenceTo(svgTarget); |
291 } | 274 } |
292 connectEventBaseConditions(); | 275 connectEventBaseConditions(); |
293 } | 276 } |
294 | 277 |
295 static inline void clearTimesWithDynamicOrigins( | 278 static inline void clearTimesWithDynamicOrigins( |
296 Vector<SMILTimeWithOrigin>& timeList) { | 279 Vector<SMILTimeWithOrigin>& timeList) { |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1282 return; | 1265 return; |
1283 | 1266 |
1284 DCHECK(m_timeContainer); | 1267 DCHECK(m_timeContainer); |
1285 DCHECK(m_targetElement); | 1268 DCHECK(m_targetElement); |
1286 m_timeContainer->unschedule(this, m_targetElement, m_attributeName); | 1269 m_timeContainer->unschedule(this, m_targetElement, m_attributeName); |
1287 m_isScheduled = false; | 1270 m_isScheduled = false; |
1288 } | 1271 } |
1289 | 1272 |
1290 DEFINE_TRACE(SVGSMILElement) { | 1273 DEFINE_TRACE(SVGSMILElement) { |
1291 visitor->trace(m_targetElement); | 1274 visitor->trace(m_targetElement); |
| 1275 visitor->trace(m_targetIdObserver); |
1292 visitor->trace(m_timeContainer); | 1276 visitor->trace(m_timeContainer); |
1293 visitor->trace(m_conditions); | 1277 visitor->trace(m_conditions); |
1294 visitor->trace(m_syncBaseDependents); | 1278 visitor->trace(m_syncBaseDependents); |
1295 SVGElement::trace(visitor); | 1279 SVGElement::trace(visitor); |
1296 SVGTests::trace(visitor); | 1280 SVGTests::trace(visitor); |
1297 } | 1281 } |
1298 | 1282 |
1299 } // namespace blink | 1283 } // namespace blink |
OLD | NEW |