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 "bindings/core/v8/ExceptionStatePlaceholder.h" | |
29 #include "bindings/core/v8/ScriptEventListener.h" | 28 #include "bindings/core/v8/ScriptEventListener.h" |
30 #include "core/XLinkNames.h" | 29 #include "core/XLinkNames.h" |
31 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
32 #include "core/dom/TaskRunnerHelper.h" | 31 #include "core/dom/TaskRunnerHelper.h" |
33 #include "core/events/Event.h" | 32 #include "core/events/Event.h" |
34 #include "core/events/EventListener.h" | 33 #include "core/events/EventListener.h" |
35 #include "core/svg/SVGDocumentExtensions.h" | 34 #include "core/svg/SVGDocumentExtensions.h" |
36 #include "core/svg/SVGSVGElement.h" | 35 #include "core/svg/SVGSVGElement.h" |
37 #include "core/svg/SVGURIReference.h" | 36 #include "core/svg/SVGURIReference.h" |
38 #include "core/svg/animation/SMILTimeContainer.h" | 37 #include "core/svg/animation/SMILTimeContainer.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 217 } |
219 } else { | 218 } else { |
220 // Register us with the target in the dependencies map. Any change of | 219 // Register us with the target in the dependencies map. Any change of |
221 // hrefElement that leads to relayout/repainting now informs us, so we can | 220 // hrefElement that leads to relayout/repainting now informs us, so we can |
222 // react to it. | 221 // react to it. |
223 addReferenceTo(svgTarget); | 222 addReferenceTo(svgTarget); |
224 } | 223 } |
225 connectEventBaseConditions(); | 224 connectEventBaseConditions(); |
226 } | 225 } |
227 | 226 |
228 static inline QualifiedName constructQualifiedName( | |
229 const SVGElement* svgElement, | |
230 const AtomicString& attributeName) { | |
231 ASSERT(svgElement); | |
232 if (attributeName.isEmpty()) | |
233 return anyQName(); | |
234 if (!attributeName.contains(':')) | |
235 return QualifiedName(nullAtom, attributeName, nullAtom); | |
236 | |
237 AtomicString prefix; | |
238 AtomicString localName; | |
239 if (!Document::parseQualifiedName(attributeName, prefix, localName, | |
240 IGNORE_EXCEPTION)) | |
241 return anyQName(); | |
242 | |
243 const AtomicString& namespaceURI = svgElement->lookupNamespaceURI(prefix); | |
244 if (namespaceURI.isEmpty()) | |
245 return anyQName(); | |
246 | |
247 QualifiedName resolvedAttrName(nullAtom, localName, namespaceURI); | |
248 // "Animation elements treat attributeName='xlink:href' as being an alias | |
249 // for targetting the 'href' attribute." | |
250 // https://svgwg.org/svg2-draft/types.html#__svg__SVGURIReference__href | |
251 if (resolvedAttrName == XLinkNames::hrefAttr) | |
252 return SVGNames::hrefAttr; | |
253 return resolvedAttrName; | |
254 } | |
255 | |
256 static inline void clearTimesWithDynamicOrigins( | 227 static inline void clearTimesWithDynamicOrigins( |
257 Vector<SMILTimeWithOrigin>& timeList) { | 228 Vector<SMILTimeWithOrigin>& timeList) { |
258 for (int i = timeList.size() - 1; i >= 0; --i) { | 229 for (int i = timeList.size() - 1; i >= 0; --i) { |
259 if (timeList[i].originIsScript()) | 230 if (timeList[i].originIsScript()) |
260 timeList.remove(i); | 231 timeList.remove(i); |
261 } | 232 } |
262 } | 233 } |
263 | 234 |
264 void SVGSMILElement::reset() { | 235 void SVGSMILElement::reset() { |
265 clearAnimatedType(); | 236 clearAnimatedType(); |
(...skipping 13 matching lines...) Expand all Loading... |
279 ContainerNode* rootParent) { | 250 ContainerNode* rootParent) { |
280 SVGElement::insertedInto(rootParent); | 251 SVGElement::insertedInto(rootParent); |
281 | 252 |
282 if (!rootParent->isConnected()) | 253 if (!rootParent->isConnected()) |
283 return InsertionDone; | 254 return InsertionDone; |
284 | 255 |
285 UseCounter::count(document(), UseCounter::SVGSMILElementInDocument); | 256 UseCounter::count(document(), UseCounter::SVGSMILElementInDocument); |
286 if (document().isLoadCompleted()) | 257 if (document().isLoadCompleted()) |
287 UseCounter::count(&document(), UseCounter::SVGSMILElementInsertedAfterLoad); | 258 UseCounter::count(&document(), UseCounter::SVGSMILElementInsertedAfterLoad); |
288 | 259 |
289 setAttributeName(constructQualifiedName( | |
290 this, fastGetAttribute(SVGNames::attributeNameAttr))); | |
291 SVGSVGElement* owner = ownerSVGElement(); | 260 SVGSVGElement* owner = ownerSVGElement(); |
292 if (!owner) | 261 if (!owner) |
293 return InsertionDone; | 262 return InsertionDone; |
294 | 263 |
295 m_timeContainer = owner->timeContainer(); | 264 m_timeContainer = owner->timeContainer(); |
296 ASSERT(m_timeContainer); | 265 ASSERT(m_timeContainer); |
297 m_timeContainer->setDocumentOrderIndexesDirty(); | 266 m_timeContainer->setDocumentOrderIndexesDirty(); |
298 | 267 |
299 // "If no attribute is present, the default begin value (an offset-value of 0) | 268 // "If no attribute is present, the default begin value (an offset-value of 0) |
300 // must be evaluated." | 269 // must be evaluated." |
301 if (!fastHasAttribute(SVGNames::beginAttr)) | 270 if (!fastHasAttribute(SVGNames::beginAttr)) |
302 m_beginTimes.append(SMILTimeWithOrigin()); | 271 m_beginTimes.append(SMILTimeWithOrigin()); |
303 | 272 |
304 if (m_isWaitingForFirstInterval) | 273 if (m_isWaitingForFirstInterval) |
305 resolveFirstInterval(); | 274 resolveFirstInterval(); |
306 | 275 |
307 if (m_timeContainer) | 276 if (m_timeContainer) |
308 m_timeContainer->notifyIntervalsChanged(); | 277 m_timeContainer->notifyIntervalsChanged(); |
309 | 278 |
310 buildPendingResource(); | 279 buildPendingResource(); |
311 | 280 |
312 return InsertionDone; | 281 return InsertionDone; |
313 } | 282 } |
314 | 283 |
315 void SVGSMILElement::removedFrom(ContainerNode* rootParent) { | 284 void SVGSMILElement::removedFrom(ContainerNode* rootParent) { |
316 if (rootParent->isConnected()) { | 285 if (rootParent->isConnected()) { |
317 clearResourceAndEventBaseReferences(); | 286 clearResourceAndEventBaseReferences(); |
318 clearConditions(); | 287 clearConditions(); |
319 setTargetElement(nullptr); | 288 setTargetElement(nullptr); |
320 setAttributeName(anyQName()); | |
321 animationAttributeChanged(); | 289 animationAttributeChanged(); |
322 m_timeContainer = nullptr; | 290 m_timeContainer = nullptr; |
323 } | 291 } |
324 | 292 |
325 SVGElement::removedFrom(rootParent); | 293 SVGElement::removedFrom(rootParent); |
326 } | 294 } |
327 | 295 |
328 SMILTime SVGSMILElement::parseOffsetValue(const String& data) { | 296 SMILTime SVGSMILElement::parseOffsetValue(const String& data) { |
329 bool ok; | 297 bool ok; |
330 double result = 0; | 298 double result = 0; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 if (attrName == SVGNames::durAttr) { | 485 if (attrName == SVGNames::durAttr) { |
518 m_cachedDur = invalidCachedTime; | 486 m_cachedDur = invalidCachedTime; |
519 } else if (attrName == SVGNames::repeatDurAttr) { | 487 } else if (attrName == SVGNames::repeatDurAttr) { |
520 m_cachedRepeatDur = invalidCachedTime; | 488 m_cachedRepeatDur = invalidCachedTime; |
521 } else if (attrName == SVGNames::repeatCountAttr) { | 489 } else if (attrName == SVGNames::repeatCountAttr) { |
522 m_cachedRepeatCount = invalidCachedTime; | 490 m_cachedRepeatCount = invalidCachedTime; |
523 } else if (attrName == SVGNames::minAttr) { | 491 } else if (attrName == SVGNames::minAttr) { |
524 m_cachedMin = invalidCachedTime; | 492 m_cachedMin = invalidCachedTime; |
525 } else if (attrName == SVGNames::maxAttr) { | 493 } else if (attrName == SVGNames::maxAttr) { |
526 m_cachedMax = invalidCachedTime; | 494 m_cachedMax = invalidCachedTime; |
527 } else if (attrName == SVGNames::attributeNameAttr) { | |
528 setAttributeName(constructQualifiedName( | |
529 this, fastGetAttribute(SVGNames::attributeNameAttr))); | |
530 } else if (attrName.matches(SVGNames::hrefAttr) || | 495 } else if (attrName.matches(SVGNames::hrefAttr) || |
531 attrName.matches(XLinkNames::hrefAttr)) { | 496 attrName.matches(XLinkNames::hrefAttr)) { |
532 // TODO(fs): Could be smarter here when 'href' is specified and 'xlink:href' | 497 // TODO(fs): Could be smarter here when 'href' is specified and 'xlink:href' |
533 // is changed. | 498 // is changed. |
534 SVGElement::InvalidationGuard invalidationGuard(this); | 499 SVGElement::InvalidationGuard invalidationGuard(this); |
535 buildPendingResource(); | 500 buildPendingResource(); |
536 if (m_targetElement) | 501 if (m_targetElement) |
537 clearAnimatedType(); | 502 clearAnimatedType(); |
538 } else if (attrName == SVGNames::beginAttr || attrName == SVGNames::endAttr) { | 503 } else if (attrName == SVGNames::beginAttr || attrName == SVGNames::endAttr) { |
539 if (isConnected()) { | 504 if (isConnected()) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 SVGElement* eventBase = eventBaseFor(*condition); | 601 SVGElement* eventBase = eventBaseFor(*condition); |
637 if (eventBase) | 602 if (eventBase) |
638 eventBase->removeEventListener(AtomicString(condition->name()), | 603 eventBase->removeEventListener(AtomicString(condition->name()), |
639 condition->eventListener(), false); | 604 condition->eventListener(), false); |
640 condition->eventListener()->disconnectAnimation(); | 605 condition->eventListener()->disconnectAnimation(); |
641 condition->setEventListener(nullptr); | 606 condition->setEventListener(nullptr); |
642 } | 607 } |
643 } | 608 } |
644 } | 609 } |
645 | 610 |
646 void SVGSMILElement::setAttributeName(const QualifiedName& attributeName) { | |
647 unscheduleIfScheduled(); | |
648 if (m_targetElement) | |
649 clearAnimatedType(); | |
650 m_attributeName = attributeName; | |
651 schedule(); | |
652 } | |
653 | |
654 void SVGSMILElement::setTargetElement(SVGElement* target) { | 611 void SVGSMILElement::setTargetElement(SVGElement* target) { |
655 unscheduleIfScheduled(); | 612 unscheduleIfScheduled(); |
656 | 613 |
657 if (m_targetElement) { | 614 if (m_targetElement) { |
658 // Clear values that may depend on the previous target. | 615 // Clear values that may depend on the previous target. |
659 clearAnimatedType(); | 616 clearAnimatedType(); |
660 disconnectSyncBaseConditions(); | 617 disconnectSyncBaseConditions(); |
661 } | 618 } |
662 | 619 |
663 // If the animation state is not Inactive, always reset to a clear state | 620 // If the animation state is not Inactive, always reset to a clear state |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 DEFINE_TRACE(SVGSMILElement) { | 1309 DEFINE_TRACE(SVGSMILElement) { |
1353 visitor->trace(m_targetElement); | 1310 visitor->trace(m_targetElement); |
1354 visitor->trace(m_timeContainer); | 1311 visitor->trace(m_timeContainer); |
1355 visitor->trace(m_conditions); | 1312 visitor->trace(m_conditions); |
1356 visitor->trace(m_syncBaseDependents); | 1313 visitor->trace(m_syncBaseDependents); |
1357 SVGElement::trace(visitor); | 1314 SVGElement::trace(visitor); |
1358 SVGTests::trace(visitor); | 1315 SVGTests::trace(visitor); |
1359 } | 1316 } |
1360 | 1317 |
1361 } // namespace blink | 1318 } // namespace blink |
OLD | NEW |