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

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

Issue 1769493002: Remove SVGUseElement::buildShadowTree (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@svg-useelm-shadowbuilder-cleanup-9
Patch Set: Created 4 years, 9 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
« no previous file with comments | « third_party/WebKit/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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot) ; 357 auto targetRange = Traversal<SVGElement>::inclusiveDescendantsOf(targetRoot) ;
358 auto targetIterator = targetRange.begin(); 358 auto targetIterator = targetRange.begin();
359 for (SVGElement& instance : Traversal<SVGElement>::inclusiveDescendantsOf(in stanceRoot)) { 359 for (SVGElement& instance : Traversal<SVGElement>::inclusiveDescendantsOf(in stanceRoot)) {
360 ASSERT(!instance.correspondingElement()); 360 ASSERT(!instance.correspondingElement());
361 instance.setCorrespondingElement(&*targetIterator); 361 instance.setCorrespondingElement(&*targetIterator);
362 ++targetIterator; 362 ++targetIterator;
363 } 363 }
364 ASSERT(!(targetIterator != targetRange.end())); 364 ASSERT(!(targetIterator != targetRange.end()));
365 } 365 }
366 366
367 // We don't walk the target tree element-by-element, and clone each element,
368 // but instead use cloneNode(deep=true). This is an optimization for the common
369 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
370 // Though if there are disallowed elements in the subtree, we have to remove
371 // them. For instance: <use> on <g> containing <foreignObject> (indirect
372 // case).
373 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree)
374 {
375 ASSERT(!subtree.inDocument());
376 Element* element = ElementTraversal::firstWithin(subtree);
377 while (element) {
378 if (isDisallowedElement(*element)) {
379 Element* next = ElementTraversal::nextSkippingChildren(*element, &su btree);
380 // The subtree is not in document so this won't generate events that could mutate the tree.
381 element->parentNode()->removeChild(element);
382 element = next;
383 } else {
384 element = ElementTraversal::next(*element, &subtree);
385 }
386 }
387 }
388
367 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) 389 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target)
368 { 390 {
369 ASSERT(!m_targetElementInstance); 391 ASSERT(!m_targetElementInstance);
370 ASSERT(!m_needsShadowTreeRecreation); 392 ASSERT(!m_needsShadowTreeRecreation);
371 393
372 // <use> creates a "user agent" shadow root. Do not build the shadow/instanc e tree for <use> 394 // <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 395 // elements living in a user agent shadow tree because they will get expande d in a second
374 // pass -- see expandUseElementsInShadowTree(). 396 // pass -- see expandUseElementsInShadowTree().
375 if (inUseShadowTree()) 397 if (inUseShadowTree())
376 return; 398 return;
377 399
378 // Do not allow self-referencing. 400 // Do not allow self-referencing.
379 if (&target == this || isDisallowedElement(target)) 401 if (&target == this || isDisallowedElement(target))
380 return; 402 return;
381 403
382 // Set up root SVG element in shadow tree. 404 // Set up root SVG element in shadow tree.
383 RefPtrWillBeRawPtr<Element> newChild = target.cloneElementWithoutChildren(); 405 // Clone the target subtree into the shadow tree, not handling <use> and <sy mbol> yet.
384 m_targetElementInstance = toSVGElement(newChild.get()); 406 RefPtrWillBeRawPtr<Element> instanceRoot = target.cloneElementWithChildren() ;
407 ASSERT(instanceRoot->isSVGElement());
408 associateCorrespondingElements(target, toSVGElement(*instanceRoot));
409 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot));
410
411 m_targetElementInstance = toSVGElement(instanceRoot.get());
385 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); 412 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot();
386 shadowTreeRootElement->appendChild(newChild.release()); 413 shadowTreeRootElement->appendChild(instanceRoot.release());
387
388 // Clone the target subtree into the shadow tree, not handling <use> and <sy mbol> yet.
389
390 // SVG specification does not say a word about <use> & cycles. My view on th is is: just ignore it!
391 // Non-appearing <use> content is easier to debug, then half-appearing conte nt.
392 buildShadowTree(target, *m_targetElementInstance);
393 414
394 addReferencesToFirstDegreeNestedUseElements(target); 415 addReferencesToFirstDegreeNestedUseElements(target);
395 416
396 if (instanceTreeIsLoading()) { 417 if (instanceTreeIsLoading()) {
397 cloneNonMarkupEventListeners(); 418 cloneNonMarkupEventListeners();
398 return; 419 return;
399 } 420 }
400 421
401 // Assure shadow tree building was successful. 422 // Assure shadow tree building was successful.
402 ASSERT(m_targetElementInstance); 423 ASSERT(m_targetElementInstance);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 return; 510 return;
490 // We only need to track first degree <use> dependencies. Indirect 511 // We only need to track first degree <use> dependencies. Indirect
491 // references are handled as the invalidation bubbles up the dependency 512 // references are handled as the invalidation bubbles up the dependency
492 // chain. 513 // chain.
493 SVGUseElement* useElement = 514 SVGUseElement* useElement =
494 isSVGUseElement(target) ? toSVGUseElement(&target) : Traversal<SVGUseEle ment>::firstWithin(target); 515 isSVGUseElement(target) ? toSVGUseElement(&target) : Traversal<SVGUseEle ment>::firstWithin(target);
495 for (; useElement; useElement = Traversal<SVGUseElement>::nextSkippingChildr en(*useElement, &target)) 516 for (; useElement; useElement = Traversal<SVGUseElement>::nextSkippingChildr en(*useElement, &target))
496 addReferenceTo(useElement); 517 addReferenceTo(useElement);
497 } 518 }
498 519
499 void SVGUseElement::buildShadowTree(SVGElement& target, SVGElement& targetInstan ce)
500 {
501 ASSERT(!isDisallowedElement(target));
502
503 targetInstance.setCorrespondingElement(&target);
504
505 for (RefPtrWillBeRawPtr<Node> child = target.firstChild(); child; child = ch ild->nextSibling()) {
506 // Skip any disallowed element.
507 if (isDisallowedElement(*child))
508 continue;
509
510 RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false);
511 targetInstance.appendChild(newChild.get());
512 if (newChild->isSVGElement()) {
513 // Enter recursion, appending new instance tree nodes to the "instan ce" object.
514 buildShadowTree(toSVGElement(*child), toSVGElement(*newChild));
515 }
516 }
517 }
518
519 void SVGUseElement::cloneNonMarkupEventListeners() 520 void SVGUseElement::cloneNonMarkupEventListeners()
520 { 521 {
521 for (SVGElement& element : Traversal<SVGElement>::descendantsOf(*userAgentSh adowRoot())) { 522 for (SVGElement& element : Traversal<SVGElement>::descendantsOf(*userAgentSh adowRoot())) {
522 if (EventTargetData* data = element.correspondingElement()->eventTargetD ata()) 523 if (EventTargetData* data = element.correspondingElement()->eventTargetD ata())
523 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarge t(&element); 524 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarge t(&element);
524 } 525 }
525 } 526 }
526 527
527 bool SVGUseElement::hasCycleUseReferencing(const SVGUseElement& use, const Conta inerNode& targetInstance, SVGElement*& newTarget) const 528 bool SVGUseElement::hasCycleUseReferencing(const SVGUseElement& use, const Conta inerNode& targetInstance, SVGElement*& newTarget) const
528 { 529 {
(...skipping 14 matching lines...) Expand all
543 while (instance && instance->isSVGElement()) { 544 while (instance && instance->isSVGElement()) {
544 SVGElement* element = toSVGElement(instance); 545 SVGElement* element = toSVGElement(instance);
545 if (element->hasID() && element->getIdAttribute() == targetId && element ->document() == newTarget->document()) 546 if (element->hasID() && element->getIdAttribute() == targetId && element ->document() == newTarget->document())
546 return true; 547 return true;
547 548
548 instance = instance->parentNode(); 549 instance = instance->parentNode();
549 } 550 }
550 return false; 551 return false;
551 } 552 }
552 553
553 // We don't walk the target tree element-by-element, and clone each element,
554 // but instead use cloneNode(deep=true). This is an optimization for the common
555 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
556 // Though if there are disallowed elements in the subtree, we have to remove
557 // them. For instance: <use> on <g> containing <foreignObject> (indirect
558 // case).
559 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree)
560 {
561 ASSERT(!subtree.inDocument());
562 Element* element = ElementTraversal::firstWithin(subtree);
563 while (element) {
564 if (isDisallowedElement(*element)) {
565 Element* next = ElementTraversal::nextSkippingChildren(*element, &su btree);
566 // The subtree is not in document so this won't generate events that could mutate the tree.
567 element->parentNode()->removeChild(element);
568 element = next;
569 } else {
570 element = ElementTraversal::next(*element, &subtree);
571 }
572 }
573 }
574
575 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe rNode& destinationRoot) 554 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe rNode& destinationRoot)
576 { 555 {
577 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) { 556 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) {
578 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); 557 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling();
579 destinationRoot.appendChild(child); 558 destinationRoot.appendChild(child);
580 child = nextChild.release(); 559 child = nextChild.release();
581 } 560 }
582 } 561 }
583 562
584 // Spec: In the generated content, the 'use' will be replaced by 'g', where all 563 // Spec: In the generated content, the 'use' will be replaced by 'g', where all
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 770
792 if (m_resource) 771 if (m_resource)
793 m_resource->removeClient(this); 772 m_resource->removeClient(this);
794 773
795 m_resource = resource; 774 m_resource = resource;
796 if (m_resource) 775 if (m_resource)
797 m_resource->addClient(this); 776 m_resource->addClient(this);
798 } 777 }
799 778
800 } // namespace blink 779 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGUseElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698