OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> |
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
6 * Copyright (C) 2012 University of Szeged | 6 * Copyright (C) 2012 University of Szeged |
7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 // Always build a user agent #shadow-root for SVGUseElement. | 73 // Always build a user agent #shadow-root for SVGUseElement. |
74 RefPtrWillBeRawPtr<SVGUseElement> use = adoptRefWillBeNoop(new SVGUseElement
(document)); | 74 RefPtrWillBeRawPtr<SVGUseElement> use = adoptRefWillBeNoop(new SVGUseElement
(document)); |
75 use->ensureUserAgentShadowRoot(); | 75 use->ensureUserAgentShadowRoot(); |
76 return use.release(); | 76 return use.release(); |
77 } | 77 } |
78 | 78 |
79 SVGUseElement::~SVGUseElement() | 79 SVGUseElement::~SVGUseElement() |
80 { | 80 { |
81 setDocumentResource(0); | 81 setDocumentResource(0); |
82 #if !ENABLE(OILPAN) | 82 #if !ENABLE(OILPAN) |
83 clearResourceReferences(); | 83 clearShadowTree(); |
| 84 cancelShadowTreeRecreation(); |
84 #endif | 85 #endif |
85 svgUseLoadEventSender().cancelEvent(this); | 86 svgUseLoadEventSender().cancelEvent(this); |
86 } | 87 } |
87 | 88 |
88 DEFINE_TRACE(SVGUseElement) | 89 DEFINE_TRACE(SVGUseElement) |
89 { | 90 { |
90 visitor->trace(m_x); | 91 visitor->trace(m_x); |
91 visitor->trace(m_y); | 92 visitor->trace(m_y); |
92 visitor->trace(m_width); | 93 visitor->trace(m_width); |
93 visitor->trace(m_height); | 94 visitor->trace(m_height); |
(...skipping 19 matching lines...) Expand all Loading... |
113 return InsertionDone; | 114 return InsertionDone; |
114 ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document())); | 115 ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document())); |
115 ASSERT(!hasPendingResources() || !isWellFormedDocument(&document())); | 116 ASSERT(!hasPendingResources() || !isWellFormedDocument(&document())); |
116 invalidateShadowTree(); | 117 invalidateShadowTree(); |
117 return InsertionDone; | 118 return InsertionDone; |
118 } | 119 } |
119 | 120 |
120 void SVGUseElement::removedFrom(ContainerNode* rootParent) | 121 void SVGUseElement::removedFrom(ContainerNode* rootParent) |
121 { | 122 { |
122 SVGGraphicsElement::removedFrom(rootParent); | 123 SVGGraphicsElement::removedFrom(rootParent); |
123 if (rootParent->inDocument()) | 124 if (rootParent->inDocument()) { |
124 clearResourceReferences(); | 125 clearShadowTree(); |
| 126 cancelShadowTreeRecreation(); |
| 127 } |
125 } | 128 } |
126 | 129 |
127 TreeScope* SVGUseElement::referencedScope() const | 130 TreeScope* SVGUseElement::referencedScope() const |
128 { | 131 { |
129 if (isStructurallyExternal()) | 132 if (isStructurallyExternal()) |
130 return externalDocument(); | 133 return externalDocument(); |
131 return &treeScope(); | 134 return &treeScope(); |
132 } | 135 } |
133 | 136 |
134 Document* SVGUseElement::externalDocument() const | 137 Document* SVGUseElement::externalDocument() const |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 } | 298 } |
296 | 299 |
297 void SVGUseElement::scheduleShadowTreeRecreation() | 300 void SVGUseElement::scheduleShadowTreeRecreation() |
298 { | 301 { |
299 if (inUseShadowTree()) | 302 if (inUseShadowTree()) |
300 return; | 303 return; |
301 m_needsShadowTreeRecreation = true; | 304 m_needsShadowTreeRecreation = true; |
302 document().scheduleUseShadowTreeUpdate(*this); | 305 document().scheduleUseShadowTreeUpdate(*this); |
303 } | 306 } |
304 | 307 |
305 void SVGUseElement::clearResourceReferences() | 308 void SVGUseElement::cancelShadowTreeRecreation() |
| 309 { |
| 310 m_needsShadowTreeRecreation = false; |
| 311 document().unscheduleUseShadowTreeUpdate(*this); |
| 312 } |
| 313 |
| 314 void SVGUseElement::clearInstanceRoot() |
306 { | 315 { |
307 if (m_targetElementInstance) | 316 if (m_targetElementInstance) |
308 m_targetElementInstance = nullptr; | 317 m_targetElementInstance = nullptr; |
| 318 } |
| 319 |
| 320 void SVGUseElement::clearShadowTree() |
| 321 { |
| 322 clearInstanceRoot(); |
309 | 323 |
310 // FIXME: We should try to optimize this, to at least allow partial reclones
. | 324 // FIXME: We should try to optimize this, to at least allow partial reclones
. |
311 if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot()) | 325 if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot()) |
312 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); | 326 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); |
313 | 327 |
314 m_needsShadowTreeRecreation = false; | |
315 document().unscheduleUseShadowTreeUpdate(*this); | |
316 | |
317 removeAllOutgoingReferences(); | 328 removeAllOutgoingReferences(); |
318 } | 329 } |
319 | 330 |
320 void SVGUseElement::buildPendingResource() | 331 void SVGUseElement::buildPendingResource() |
321 { | 332 { |
322 if (inUseShadowTree()) | 333 if (inUseShadowTree()) |
323 return; | 334 return; |
324 clearResourceReferences(); | 335 clearShadowTree(); |
| 336 cancelShadowTreeRecreation(); |
325 if (!referencedScope() || !inDocument()) | 337 if (!referencedScope() || !inDocument()) |
326 return; | 338 return; |
327 | 339 |
328 AtomicString id; | 340 AtomicString id; |
329 Element* target = SVGURIReference::targetElementFromIRIString(hrefString(),
treeScope(), &id, externalDocument()); | 341 Element* target = SVGURIReference::targetElementFromIRIString(hrefString(),
treeScope(), &id, externalDocument()); |
330 if (!target || !target->inDocument()) { | 342 if (!target || !target->inDocument()) { |
331 // If we can't find the target of an external element, just give up. | 343 // If we can't find the target of an external element, just give up. |
332 // We can't observe if the target somewhen enters the external document,
nor should we do it. | 344 // We can't observe if the target somewhen enters the external document,
nor should we do it. |
333 if (externalDocument()) | 345 if (externalDocument()) |
334 return; | 346 return; |
(...skipping 26 matching lines...) Expand all Loading... |
361 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(cl
one.get()); | 373 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(cl
one.get()); |
362 TrackExceptionState exceptionState; | 374 TrackExceptionState exceptionState; |
363 for (Node* node = toClone.firstChild(); node && !exceptionState.hadException
(); node = node->nextSibling()) | 375 for (Node* node = toClone.firstChild(); node && !exceptionState.hadException
(); node = node->nextSibling()) |
364 clone->appendChild(cloneNodeAndAssociate(*node), exceptionState); | 376 clone->appendChild(cloneNodeAndAssociate(*node), exceptionState); |
365 return clone.release(); | 377 return clone.release(); |
366 } | 378 } |
367 | 379 |
368 void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target) | 380 void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target) |
369 { | 381 { |
370 ASSERT(!m_targetElementInstance); | 382 ASSERT(!m_targetElementInstance); |
| 383 ASSERT(!m_needsShadowTreeRecreation); |
371 | 384 |
372 // <use> creates a "user agent" shadow root. Do not build the shadow/instanc
e tree for <use> | 385 // <use> creates a "user agent" shadow root. Do not build the shadow/instanc
e tree for <use> |
373 // elements living in a user agent shadow tree because they will get expande
d in a second | 386 // elements living in a user agent shadow tree because they will get expande
d in a second |
374 // pass -- see expandUseElementsInShadowTree(). | 387 // pass -- see expandUseElementsInShadowTree(). |
375 if (inUseShadowTree()) | 388 if (inUseShadowTree()) |
376 return; | 389 return; |
377 | 390 |
378 // Do not allow self-referencing. | 391 // Do not allow self-referencing. |
379 // 'target' may be null, if it's a non SVG namespaced element. | 392 // 'target' may be null, if it's a non SVG namespaced element. |
380 if (!target || target == this || isDisallowedElement(target)) | 393 if (!target || target == this || isDisallowedElement(target)) |
381 return; | 394 return; |
382 | 395 |
383 // Set up root SVG element in shadow tree. | 396 // Set up root SVG element in shadow tree. |
384 RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren()
; | 397 RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren()
; |
385 m_targetElementInstance = toSVGElement(newChild.get()); | 398 m_targetElementInstance = toSVGElement(newChild.get()); |
386 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 399 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
387 shadowTreeRootElement->appendChild(newChild.release()); | 400 shadowTreeRootElement->appendChild(newChild.release()); |
388 | 401 |
389 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. | 402 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. |
390 | 403 |
391 // SVG specification does not say a word about <use> & cycles. My view on th
is is: just ignore it! | 404 // SVG specification does not say a word about <use> & cycles. My view on th
is is: just ignore it! |
392 // Non-appearing <use> content is easier to debug, then half-appearing conte
nt. | 405 // Non-appearing <use> content is easier to debug, then half-appearing conte
nt. |
393 if (!buildShadowTree(target, m_targetElementInstance.get(), false)) { | 406 if (!buildShadowTree(target, m_targetElementInstance.get(), false)) { |
394 clearResourceReferences(); | 407 clearShadowTree(); |
395 return; | 408 return; |
396 } | 409 } |
397 | 410 |
398 if (instanceTreeIsLoading(m_targetElementInstance.get())) | 411 if (instanceTreeIsLoading(m_targetElementInstance.get())) |
399 return; | 412 return; |
400 | 413 |
401 // Assure shadow tree building was successfull | 414 // Assure shadow tree building was successfull |
402 ASSERT(m_targetElementInstance); | 415 ASSERT(m_targetElementInstance); |
403 ASSERT(m_targetElementInstance->correspondingUseElement() == this); | 416 ASSERT(m_targetElementInstance->correspondingUseElement() == this); |
404 ASSERT(m_targetElementInstance->correspondingElement() == target); | 417 ASSERT(m_targetElementInstance->correspondingElement() == target); |
405 | 418 |
406 // Expand all <use> elements in the shadow tree. | 419 // Expand all <use> elements in the shadow tree. |
407 // Expand means: replace the actual <use> element by what it references. | 420 // Expand means: replace the actual <use> element by what it references. |
408 if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) { | 421 if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) { |
409 clearResourceReferences(); | 422 clearShadowTree(); |
410 return; | 423 return; |
411 } | 424 } |
412 | 425 |
413 // Expand all <symbol> elements in the shadow tree. | 426 // Expand all <symbol> elements in the shadow tree. |
414 // Expand means: replace the actual <symbol> element by the <svg> element. | 427 // Expand means: replace the actual <symbol> element by the <svg> element. |
415 expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstCh
ild())); | 428 expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstCh
ild())); |
416 | 429 |
417 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); | 430 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); |
418 transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_t
argetElementInstance->correspondingElement()); | 431 transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_t
argetElementInstance->correspondingElement()); |
419 | 432 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 } | 691 } |
679 | 692 |
680 for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChil
d(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) | 693 for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChil
d(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) |
681 expandSymbolElementsInShadowTree(child.get()); | 694 expandSymbolElementsInShadowTree(child.get()); |
682 } | 695 } |
683 | 696 |
684 void SVGUseElement::invalidateShadowTree() | 697 void SVGUseElement::invalidateShadowTree() |
685 { | 698 { |
686 if (!inActiveDocument() || m_needsShadowTreeRecreation) | 699 if (!inActiveDocument() || m_needsShadowTreeRecreation) |
687 return; | 700 return; |
| 701 clearInstanceRoot(); |
688 scheduleShadowTreeRecreation(); | 702 scheduleShadowTreeRecreation(); |
689 invalidateDependentShadowTrees(); | 703 invalidateDependentShadowTrees(); |
690 } | 704 } |
691 | 705 |
692 void SVGUseElement::invalidateDependentShadowTrees() | 706 void SVGUseElement::invalidateDependentShadowTrees() |
693 { | 707 { |
694 // Recursively invalidate dependent <use> shadow trees | 708 // Recursively invalidate dependent <use> shadow trees |
695 const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement>>& instances = ins
tancesForElement(); | 709 const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement>>& instances = ins
tancesForElement(); |
696 for (SVGElement* instance : instances) { | 710 for (SVGElement* instance : instances) { |
697 if (SVGUseElement* element = instance->correspondingUseElement()) { | 711 if (SVGUseElement* element = instance->correspondingUseElement()) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 | 796 |
783 if (m_resource) | 797 if (m_resource) |
784 m_resource->removeClient(this); | 798 m_resource->removeClient(this); |
785 | 799 |
786 m_resource = resource; | 800 m_resource = resource; |
787 if (m_resource) | 801 if (m_resource) |
788 m_resource->addClient(this); | 802 m_resource->addClient(this); |
789 } | 803 } |
790 | 804 |
791 } | 805 } |
OLD | NEW |