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

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

Issue 2752763002: Change the type of a SVG <use> element's shadow tree from "user agent" to "closed" (Closed)
Patch Set: Rebased and resolve a conflict in HitTestResult Created 3 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann
3 * <zimmermann@kde.org> 3 * <zimmermann@kde.org>
4 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 4 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
5 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 5 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
6 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 6 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
7 * Copyright (C) 2012 University of Szeged 7 * Copyright (C) 2012 University of Szeged
8 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> 8 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 14 matching lines...) Expand all
25 25
26 #include "core/svg/SVGUseElement.h" 26 #include "core/svg/SVGUseElement.h"
27 27
28 #include "core/SVGNames.h" 28 #include "core/SVGNames.h"
29 #include "core/XLinkNames.h" 29 #include "core/XLinkNames.h"
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/dom/ElementTraversal.h" 31 #include "core/dom/ElementTraversal.h"
32 #include "core/dom/IdTargetObserver.h" 32 #include "core/dom/IdTargetObserver.h"
33 #include "core/dom/StyleChangeReason.h" 33 #include "core/dom/StyleChangeReason.h"
34 #include "core/dom/TaskRunnerHelper.h" 34 #include "core/dom/TaskRunnerHelper.h"
35 #include "core/dom/shadow/ElementShadow.h"
35 #include "core/dom/shadow/ShadowRoot.h" 36 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/events/Event.h" 37 #include "core/events/Event.h"
37 #include "core/layout/svg/LayoutSVGTransformableContainer.h" 38 #include "core/layout/svg/LayoutSVGTransformableContainer.h"
38 #include "core/svg/SVGGElement.h" 39 #include "core/svg/SVGGElement.h"
39 #include "core/svg/SVGLengthContext.h" 40 #include "core/svg/SVGLengthContext.h"
40 #include "core/svg/SVGSVGElement.h" 41 #include "core/svg/SVGSVGElement.h"
41 #include "core/svg/SVGSymbolElement.h" 42 #include "core/svg/SVGSymbolElement.h"
42 #include "core/svg/SVGTitleElement.h" 43 #include "core/svg/SVGTitleElement.h"
43 #include "core/xml/parser/XMLDocumentParser.h" 44 #include "core/xml/parser/XMLDocumentParser.h"
44 #include "platform/loader/fetch/FetchRequest.h" 45 #include "platform/loader/fetch/FetchRequest.h"
(...skipping 28 matching lines...) Expand all
73 74
74 addToPropertyMap(m_x); 75 addToPropertyMap(m_x);
75 addToPropertyMap(m_y); 76 addToPropertyMap(m_y);
76 addToPropertyMap(m_width); 77 addToPropertyMap(m_width);
77 addToPropertyMap(m_height); 78 addToPropertyMap(m_height);
78 } 79 }
79 80
80 SVGUseElement* SVGUseElement::create(Document& document) { 81 SVGUseElement* SVGUseElement::create(Document& document) {
81 // Always build a user agent #shadow-root for SVGUseElement. 82 // Always build a user agent #shadow-root for SVGUseElement.
82 SVGUseElement* use = new SVGUseElement(document); 83 SVGUseElement* use = new SVGUseElement(document);
83 use->ensureUserAgentShadowRoot(); 84 use->ensureShadow().addShadowRoot(*use, ShadowRootType::Closed);
84 return use; 85 return use;
85 } 86 }
86 87
87 SVGUseElement::~SVGUseElement() {} 88 SVGUseElement::~SVGUseElement() {}
88 89
89 void SVGUseElement::dispose() { 90 void SVGUseElement::dispose() {
90 setDocumentResource(nullptr); 91 setDocumentResource(nullptr);
91 } 92 }
92 93
93 DEFINE_TRACE(SVGUseElement) { 94 DEFINE_TRACE(SVGUseElement) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 } 307 }
307 if (!resourceIsValid()) 308 if (!resourceIsValid())
308 return nullptr; 309 return nullptr;
309 return m_resource->document()->getElementById(m_elementIdentifier); 310 return m_resource->document()->getElementById(m_elementIdentifier);
310 } 311 }
311 312
312 void SVGUseElement::buildPendingResource() { 313 void SVGUseElement::buildPendingResource() {
313 if (inUseShadowTree()) 314 if (inUseShadowTree())
314 return; 315 return;
315 // FIXME: We should try to optimize this, to at least allow partial reclones. 316 // FIXME: We should try to optimize this, to at least allow partial reclones.
316 userAgentShadowRoot()->removeChildren(OmitSubtreeModifiedEvent); 317 useShadowRoot().removeChildren(OmitSubtreeModifiedEvent);
317 clearResourceReference(); 318 clearResourceReference();
318 cancelShadowTreeRecreation(); 319 cancelShadowTreeRecreation();
319 if (!isConnected()) 320 if (!isConnected())
320 return; 321 return;
321 Element* target = resolveTargetElement(); 322 Element* target = resolveTargetElement();
322 // TODO(fs): Why would the Element not be "connected" at this point? 323 // TODO(fs): Why would the Element not be "connected" at this point?
323 if (target && target->isConnected() && target->isSVGElement()) { 324 if (target && target->isConnected() && target->isSVGElement()) {
324 buildShadowAndInstanceTree(toSVGElement(*target)); 325 buildShadowAndInstanceTree(toSVGElement(*target));
325 invalidateDependentShadowTrees(); 326 invalidateDependentShadowTrees();
326 } 327 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 targetRoot); 414 targetRoot);
414 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); 415 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot));
415 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); 416 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot));
416 return instanceRoot; 417 return instanceRoot;
417 } 418 }
418 419
419 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) { 420 void SVGUseElement::buildShadowAndInstanceTree(SVGElement& target) {
420 DCHECK(!m_targetElementInstance); 421 DCHECK(!m_targetElementInstance);
421 DCHECK(!m_needsShadowTreeRecreation); 422 DCHECK(!m_needsShadowTreeRecreation);
422 423
423 // <use> creates a "user agent" shadow root. Do not build the shadow/instance 424 // <use> creates a closed shadow root. Do not build the shadow/instance
424 // tree for <use> elements living in a user agent shadow tree because they 425 // tree for <use> elements living in a closed tree because they
425 // will get expanded in a second pass -- see expandUseElementsInShadowTree(). 426 // will get expanded in a second pass -- see expandUseElementsInShadowTree().
426 if (inUseShadowTree()) 427 if (inUseShadowTree())
427 return; 428 return;
428 429
429 // Do not allow self-referencing. 430 // Do not allow self-referencing.
430 if (&target == this || isDisallowedElement(target)) 431 if (&target == this || isDisallowedElement(target))
431 return; 432 return;
432 433
433 // Set up root SVG element in shadow tree. 434 // Set up root SVG element in shadow tree.
434 // Clone the target subtree into the shadow tree, not handling <use> and 435 // Clone the target subtree into the shadow tree, not handling <use> and
435 // <symbol> yet. 436 // <symbol> yet.
436 Element* instanceRoot = createInstanceTree(target); 437 Element* instanceRoot = createInstanceTree(target);
437 m_targetElementInstance = toSVGElement(instanceRoot); 438 m_targetElementInstance = toSVGElement(instanceRoot);
438 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); 439 ShadowRoot& shadowRoot = useShadowRoot();
439 shadowTreeRootElement->appendChild(instanceRoot); 440 shadowRoot.appendChild(instanceRoot);
440 441
441 addReferencesToFirstDegreeNestedUseElements(target); 442 addReferencesToFirstDegreeNestedUseElements(target);
442 443
443 if (instanceTreeIsLoading()) 444 if (instanceTreeIsLoading())
444 return; 445 return;
445 446
446 // Assure shadow tree building was successful. 447 // Assure shadow tree building was successful.
447 DCHECK(m_targetElementInstance); 448 DCHECK(m_targetElementInstance);
448 DCHECK_EQ(m_targetElementInstance->correspondingUseElement(), this); 449 DCHECK_EQ(m_targetElementInstance->correspondingUseElement(), this);
449 DCHECK_EQ(m_targetElementInstance->correspondingElement(), &target); 450 DCHECK_EQ(m_targetElementInstance->correspondingElement(), &target);
450 451
451 // Expand all <use> elements in the shadow tree. 452 // Expand all <use> elements in the shadow tree.
452 // Expand means: replace the actual <use> element by what it references. 453 // Expand means: replace the actual <use> element by what it references.
453 if (!expandUseElementsInShadowTree()) { 454 if (!expandUseElementsInShadowTree()) {
454 shadowTreeRootElement->removeChildren(OmitSubtreeModifiedEvent); 455 shadowRoot.removeChildren(OmitSubtreeModifiedEvent);
455 clearResourceReference(); 456 clearResourceReference();
456 return; 457 return;
457 } 458 }
458 459
459 // If the instance root was a <use>, it could have been replaced now, so 460 // If the instance root was a <use>, it could have been replaced now, so
460 // reset |m_targetElementInstance|. 461 // reset |m_targetElementInstance|.
461 m_targetElementInstance = 462 m_targetElementInstance = toSVGElementOrDie(shadowRoot.firstChild());
462 toSVGElementOrDie(shadowTreeRootElement->firstChild()); 463 DCHECK_EQ(m_targetElementInstance->parentNode(), shadowRoot);
463 DCHECK_EQ(m_targetElementInstance->parentNode(), shadowTreeRootElement);
464 464
465 // Update relative length information. 465 // Update relative length information.
466 updateRelativeLengthsInformation(); 466 updateRelativeLengthsInformation();
467 } 467 }
468 468
469 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) { 469 LayoutObject* SVGUseElement::createLayoutObject(const ComputedStyle&) {
470 return new LayoutSVGTransformableContainer(this); 470 return new LayoutSVGTransformableContainer(this);
471 } 471 }
472 472
473 static bool isDirectReference(const SVGElement& element) { 473 static bool isDirectReference(const SVGElement& element) {
(...skipping 16 matching lines...) Expand all
490 // FIXME: Avoid manual resolution of x/y here. Its potentially harmful. 490 // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
491 SVGLengthContext lengthContext(this); 491 SVGLengthContext lengthContext(this);
492 path.translate(FloatSize(m_x->currentValue()->value(lengthContext), 492 path.translate(FloatSize(m_x->currentValue()->value(lengthContext),
493 m_y->currentValue()->value(lengthContext))); 493 m_y->currentValue()->value(lengthContext)));
494 path.transform(calculateTransform(SVGElement::IncludeMotionTransform)); 494 path.transform(calculateTransform(SVGElement::IncludeMotionTransform));
495 } 495 }
496 } 496 }
497 497
498 SVGGraphicsElement* SVGUseElement::visibleTargetGraphicsElementForClipping() 498 SVGGraphicsElement* SVGUseElement::visibleTargetGraphicsElementForClipping()
499 const { 499 const {
500 Node* n = userAgentShadowRoot()->firstChild(); 500 Node* n = useShadowRoot().firstChild();
501 if (!n || !n->isSVGElement()) 501 if (!n || !n->isSVGElement())
502 return nullptr; 502 return nullptr;
503 503
504 SVGElement& element = toSVGElement(*n); 504 SVGElement& element = toSVGElement(*n);
505 505
506 if (!element.isSVGGraphicsElement()) 506 if (!element.isSVGGraphicsElement())
507 return nullptr; 507 return nullptr;
508 508
509 // Spec: "If a <use> element is a child of a clipPath element, it must 509 // Spec: "If a <use> element is a child of a clipPath element, it must
510 // directly reference <path>, <text> or basic shapes elements. Indirect 510 // directly reference <path>, <text> or basic shapes elements. Indirect
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 } 578 }
579 579
580 bool SVGUseElement::expandUseElementsInShadowTree() { 580 bool SVGUseElement::expandUseElementsInShadowTree() {
581 // Why expand the <use> elements in the shadow tree here, and not just 581 // Why expand the <use> elements in the shadow tree here, and not just
582 // do this directly in buildShadowTree, if we encounter a <use> element? 582 // do this directly in buildShadowTree, if we encounter a <use> element?
583 // 583 //
584 // Short answer: Because we may miss to expand some elements. For example, if 584 // Short answer: Because we may miss to expand some elements. For example, if
585 // a <symbol> contains <use> tags, we'd miss them. So once we're done with 585 // a <symbol> contains <use> tags, we'd miss them. So once we're done with
586 // setting up the actual shadow tree (after the special case modification for 586 // setting up the actual shadow tree (after the special case modification for
587 // svg/symbol) we have to walk it completely and expand all <use> elements. 587 // svg/symbol) we have to walk it completely and expand all <use> elements.
588 ShadowRoot* shadowRoot = userAgentShadowRoot(); 588 ShadowRoot& shadowRoot = useShadowRoot();
589 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(*shadowRoot); 589 for (SVGUseElement* use = Traversal<SVGUseElement>::firstWithin(shadowRoot);
590 use;) { 590 use;) {
591 DCHECK(!use->resourceIsStillLoading()); 591 DCHECK(!use->resourceIsStillLoading());
592 592
593 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement()); 593 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement());
594 SVGElement* target = nullptr; 594 SVGElement* target = nullptr;
595 if (hasCycleUseReferencing(originalUse, *use, target)) 595 if (hasCycleUseReferencing(originalUse, *use, target))
596 return false; 596 return false;
597 597
598 if (target && isDisallowedElement(*target)) 598 if (target && isDisallowedElement(*target))
599 return false; 599 return false;
(...skipping 10 matching lines...) Expand all
610 moveChildrenToReplacementElement(*use, *cloneParent); 610 moveChildrenToReplacementElement(*use, *cloneParent);
611 611
612 if (target) 612 if (target)
613 cloneParent->appendChild(use->createInstanceTree(*target)); 613 cloneParent->appendChild(use->createInstanceTree(*target));
614 614
615 SVGElement* replacingElement(cloneParent); 615 SVGElement* replacingElement(cloneParent);
616 616
617 // Replace <use> with referenced content. 617 // Replace <use> with referenced content.
618 use->parentNode()->replaceChild(cloneParent, use); 618 use->parentNode()->replaceChild(cloneParent, use);
619 619
620 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); 620 use = Traversal<SVGUseElement>::next(*replacingElement, &shadowRoot);
621 } 621 }
622 return true; 622 return true;
623 } 623 }
624 624
625 void SVGUseElement::invalidateShadowTree() { 625 void SVGUseElement::invalidateShadowTree() {
626 if (!inActiveDocument() || m_needsShadowTreeRecreation) 626 if (!inActiveDocument() || m_needsShadowTreeRecreation)
627 return; 627 return;
628 clearInstanceRoot(); 628 clearInstanceRoot();
629 scheduleShadowTreeRecreation(); 629 scheduleShadowTreeRecreation();
630 invalidateDependentShadowTrees(); 630 invalidateDependentShadowTrees();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 return m_resource && m_resource->isLoading(); 711 return m_resource && m_resource->isLoading();
712 } 712 }
713 713
714 bool SVGUseElement::resourceIsValid() const { 714 bool SVGUseElement::resourceIsValid() const {
715 return m_resource && m_resource->isLoaded() && !m_resource->errorOccurred() && 715 return m_resource && m_resource->isLoaded() && !m_resource->errorOccurred() &&
716 m_resource->document(); 716 m_resource->document();
717 } 717 }
718 718
719 bool SVGUseElement::instanceTreeIsLoading() const { 719 bool SVGUseElement::instanceTreeIsLoading() const {
720 for (const SVGUseElement& useElement : 720 for (const SVGUseElement& useElement :
721 Traversal<SVGUseElement>::descendantsOf(*userAgentShadowRoot())) { 721 Traversal<SVGUseElement>::descendantsOf(useShadowRoot())) {
722 if (useElement.resourceIsStillLoading()) 722 if (useElement.resourceIsStillLoading())
723 return true; 723 return true;
724 } 724 }
725 return false; 725 return false;
726 } 726 }
727 727
728 void SVGUseElement::setDocumentResource(DocumentResource* resource) { 728 void SVGUseElement::setDocumentResource(DocumentResource* resource) {
729 if (m_resource == resource) 729 if (m_resource == resource)
730 return; 730 return;
731 731
732 if (m_resource) 732 if (m_resource)
733 m_resource->removeClient(this); 733 m_resource->removeClient(this);
734 734
735 m_resource = resource; 735 m_resource = resource;
736 if (m_resource) 736 if (m_resource)
737 m_resource->addClient(this); 737 m_resource->addClient(this);
738 } 738 }
739 739
740 } // namespace blink 740 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGUseElement.h ('k') | third_party/WebKit/Source/web/ContextMenuClientImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698