| 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 |