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

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

Issue 1736283003: Don't expand <symbol> elements in <use> that are not targets (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@svg-use-symbol-siblings-in-shadow
Patch Set: Drop additional fix. 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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 Element* next = ElementTraversal::nextSkippingChildren(*element, &su btree); 373 Element* next = ElementTraversal::nextSkippingChildren(*element, &su btree);
374 // The subtree is not in document so this won't generate events that could mutate the tree. 374 // The subtree is not in document so this won't generate events that could mutate the tree.
375 element->parentNode()->removeChild(element); 375 element->parentNode()->removeChild(element);
376 element = next; 376 element = next;
377 } else { 377 } else {
378 element = ElementTraversal::next(*element, &subtree); 378 element = ElementTraversal::next(*element, &subtree);
379 } 379 }
380 } 380 }
381 } 381 }
382 382
383 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe rNode& destinationRoot)
384 {
385 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) {
386 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling();
387 destinationRoot.appendChild(child);
388 child = nextChild.release();
389 }
390 }
391
383 PassRefPtrWillBeRawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& ta rgetRoot) const 392 PassRefPtrWillBeRawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& ta rgetRoot) const
384 { 393 {
385 RefPtrWillBeRawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildr en(); 394 RefPtrWillBeRawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildr en();
386 ASSERT(instanceRoot->isSVGElement()); 395 ASSERT(instanceRoot->isSVGElement());
396 if (isSVGSymbolElement(targetRoot)) {
397 // Spec: The referenced 'symbol' and its contents are deep-cloned into
398 // the generated tree, with the exception that the 'symbol' is replaced
399 // by an 'svg'. This generated 'svg' will always have explicit values
400 // for attributes width and height. If attributes width and/or height
401 // are provided on the 'use' element, then these attributes will be
402 // transferred to the generated 'svg'. If attributes width and/or
403 // height are not specified, the generated 'svg' element will use
404 // values of 100% for these attributes.
405 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(tar getRoot.document());
406 // Transfer all data (attributes, etc.) from the <symbol> to the new
407 // <svg> element.
408 svgElement->cloneDataFromElement(*instanceRoot);
409 // Move already cloned elements to the new <svg> element.
410 moveChildrenToReplacementElement(*instanceRoot, *svgElement);
411 instanceRoot = svgElement.release();
412 }
413 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), target Root);
387 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); 414 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot));
388 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); 415 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot));
389 return instanceRoot.release(); 416 return instanceRoot.release();
390 } 417 }
391 418
392 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) 419 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target)
393 { 420 {
394 ASSERT(!m_targetElementInstance); 421 ASSERT(!m_targetElementInstance);
395 ASSERT(!m_needsShadowTreeRecreation); 422 ASSERT(!m_needsShadowTreeRecreation);
396 423
(...skipping 26 matching lines...) Expand all
423 ASSERT(m_targetElementInstance->correspondingUseElement() == this); 450 ASSERT(m_targetElementInstance->correspondingUseElement() == this);
424 ASSERT(m_targetElementInstance->correspondingElement() == &target); 451 ASSERT(m_targetElementInstance->correspondingElement() == &target);
425 452
426 // Expand all <use> elements in the shadow tree. 453 // Expand all <use> elements in the shadow tree.
427 // Expand means: replace the actual <use> element by what it references. 454 // Expand means: replace the actual <use> element by what it references.
428 if (!expandUseElementsInShadowTree()) { 455 if (!expandUseElementsInShadowTree()) {
429 clearShadowTree(); 456 clearShadowTree();
430 return; 457 return;
431 } 458 }
432 459
433 // Expand all <symbol> elements in the shadow tree. 460 // If the instance root was a <use>, it could have been replaced now, so
434 // Expand means: replace the actual <symbol> element by the <svg> element. 461 // reset |m_targetElementInstance|.
435 expandSymbolElementsInShadowTree(); 462 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild());
463 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement);
436 464
437 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild());
438 transferUseWidthAndHeightIfNeeded(*this, *m_targetElementInstance, *m_target ElementInstance->correspondingElement());
439 cloneNonMarkupEventListeners(); 465 cloneNonMarkupEventListeners();
440 466
441 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement);
442
443 // Update relative length information. 467 // Update relative length information.
444 updateRelativeLengthsInformation(); 468 updateRelativeLengthsInformation();
445 } 469 }
446 470
447 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) 471 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&)
448 { 472 {
449 return new LayoutSVGTransformableContainer(this); 473 return new LayoutSVGTransformableContainer(this);
450 } 474 }
451 475
452 static bool isDirectReference(const SVGElement& element) 476 static bool isDirectReference(const SVGElement& element)
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 while (instance && instance->isSVGElement()) { 567 while (instance && instance->isSVGElement()) {
544 SVGElement* element = toSVGElement(instance); 568 SVGElement* element = toSVGElement(instance);
545 if (element->hasID() && element->getIdAttribute() == targetId && element ->document() == newTarget->document()) 569 if (element->hasID() && element->getIdAttribute() == targetId && element ->document() == newTarget->document())
546 return true; 570 return true;
547 571
548 instance = instance->parentNode(); 572 instance = instance->parentNode();
549 } 573 }
550 return false; 574 return false;
551 } 575 }
552 576
553 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe rNode& destinationRoot)
554 {
555 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) {
556 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling();
557 destinationRoot.appendChild(child);
558 child = nextChild.release();
559 }
560 }
561
562 // Spec: In the generated content, the 'use' will be replaced by 'g', where all 577 // Spec: In the generated content, the 'use' will be replaced by 'g', where all
563 // attributes from the 'use' element except for x, y, width, height and 578 // attributes from the 'use' element except for x, y, width, height and
564 // xlink:href are transferred to the generated 'g' element. 579 // xlink:href are transferred to the generated 'g' element.
565 static void removeAttributesFromReplacementElement(SVGElement& replacementElemen t) 580 static void removeAttributesFromReplacementElement(SVGElement& replacementElemen t)
566 { 581 {
567 replacementElement.removeAttribute(SVGNames::xAttr); 582 replacementElement.removeAttribute(SVGNames::xAttr);
568 replacementElement.removeAttribute(SVGNames::yAttr); 583 replacementElement.removeAttribute(SVGNames::yAttr);
569 replacementElement.removeAttribute(SVGNames::widthAttr); 584 replacementElement.removeAttribute(SVGNames::widthAttr);
570 replacementElement.removeAttribute(SVGNames::heightAttr); 585 replacementElement.removeAttribute(SVGNames::heightAttr);
571 replacementElement.removeAttribute(SVGNames::hrefAttr); 586 replacementElement.removeAttribute(SVGNames::hrefAttr);
(...skipping 25 matching lines...) Expand all
597 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(origin alUse.document()); 612 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(origin alUse.document());
598 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen t. 613 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen t.
599 cloneParent->cloneDataFromElement(*use); 614 cloneParent->cloneDataFromElement(*use);
600 cloneParent->setCorrespondingElement(&originalUse); 615 cloneParent->setCorrespondingElement(&originalUse);
601 616
602 removeAttributesFromReplacementElement(*cloneParent); 617 removeAttributesFromReplacementElement(*cloneParent);
603 618
604 // Move already cloned elements to the new <g> element. 619 // Move already cloned elements to the new <g> element.
605 moveChildrenToReplacementElement(*use, *cloneParent); 620 moveChildrenToReplacementElement(*use, *cloneParent);
606 621
607 if (target) { 622 if (target)
608 RefPtrWillBeRawPtr<Element> instanceRoot = use->createInstanceTree(* target); 623 cloneParent->appendChild(use->createInstanceTree(*target));
609 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(*instanceRoot), *target);
610 cloneParent->appendChild(instanceRoot.release());
611 }
612 624
613 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); 625 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get());
614 626
615 // Replace <use> with referenced content. 627 // Replace <use> with referenced content.
616 use->parentNode()->replaceChild(cloneParent.release(), use); 628 use->parentNode()->replaceChild(cloneParent.release(), use);
617 629
618 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); 630 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot);
619 } 631 }
620 return true; 632 return true;
621 } 633 }
622 634
623 void SVGUseElement::expandSymbolElementsInShadowTree()
624 {
625 ShadowRoot* shadowRoot = userAgentShadowRoot();
626 for (RefPtrWillBeRawPtr<SVGSymbolElement> symbol = Traversal<SVGSymbolElemen t>::firstWithin(*shadowRoot); symbol; ) {
627 // Spec: The referenced 'symbol' and its contents are deep-cloned into t he generated tree,
628 // with the exception that the 'symbol' is replaced by an 'svg'. This ge nerated 'svg' will
629 // always have explicit values for attributes width and height. If attri butes width and/or
630 // height are provided on the 'use' element, then these attributes will be transferred to
631 // the generated 'svg'. If attributes width and/or height are not specif ied, the generated
632 // 'svg' element will use values of 100% for these attributes.
633 SVGElement& originalSymbol = *symbol->correspondingElement();
634 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ori ginalSymbol.document());
635 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e lement.
636 svgElement->cloneDataFromElement(*symbol);
637 svgElement->setCorrespondingElement(&originalSymbol);
638
639 // Move already cloned elements to the new <svg> element.
640 moveChildrenToReplacementElement(*symbol, *svgElement);
641
642 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get());
643
644 // Replace <symbol> with <svg>.
645 symbol->parentNode()->replaceChild(svgElement.release(), symbol);
646
647 symbol = Traversal<SVGSymbolElement>::next(*replacingElement, shadowRoot );
648 }
649 }
650
651 void SVGUseElement::invalidateShadowTree() 635 void SVGUseElement::invalidateShadowTree()
652 { 636 {
653 if (!inActiveDocument() || m_needsShadowTreeRecreation) 637 if (!inActiveDocument() || m_needsShadowTreeRecreation)
654 return; 638 return;
655 clearInstanceRoot(); 639 clearInstanceRoot();
656 scheduleShadowTreeRecreation(); 640 scheduleShadowTreeRecreation();
657 invalidateDependentShadowTrees(); 641 invalidateDependentShadowTrees();
658 } 642 }
659 643
660 void SVGUseElement::invalidateDependentShadowTrees() 644 void SVGUseElement::invalidateDependentShadowTrees()
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 748
765 if (m_resource) 749 if (m_resource)
766 m_resource->removeClient(this); 750 m_resource->removeClient(this);
767 751
768 m_resource = resource; 752 m_resource = resource;
769 if (m_resource) 753 if (m_resource)
770 m_resource->addClient(this); 754 m_resource->addClient(this);
771 } 755 }
772 756
773 } // namespace blink 757 } // 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