Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(520)

Side by Side Diff: Source/core/svg/SVGUseElement.cpp

Issue 1323443003: Don't transfer viewport to an invalid/dirty <use> instance (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Only clear the instance root. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/SVGUseElement.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Source/core/svg/SVGUseElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698