| 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 30 matching lines...) Expand all Loading... |
| 41 #include "core/svg/SVGLengthContext.h" | 41 #include "core/svg/SVGLengthContext.h" |
| 42 #include "core/svg/SVGSVGElement.h" | 42 #include "core/svg/SVGSVGElement.h" |
| 43 #include "core/svg/SVGSymbolElement.h" | 43 #include "core/svg/SVGSymbolElement.h" |
| 44 #include "core/xml/parser/XMLDocumentParser.h" | 44 #include "core/xml/parser/XMLDocumentParser.h" |
| 45 #include "wtf/Vector.h" | 45 #include "wtf/Vector.h" |
| 46 | 46 |
| 47 namespace blink { | 47 namespace blink { |
| 48 | 48 |
| 49 static SVGUseEventSender& svgUseLoadEventSender() | 49 static SVGUseEventSender& svgUseLoadEventSender() |
| 50 { | 50 { |
| 51 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGUseEventSender>, sharedLoadEve
ntSender, (SVGUseEventSender::create(EventTypeNames::load))); | 51 DEFINE_STATIC_LOCAL(Persistent<SVGUseEventSender>, sharedLoadEventSender, (S
VGUseEventSender::create(EventTypeNames::load))); |
| 52 return *sharedLoadEventSender; | 52 return *sharedLoadEventSender; |
| 53 } | 53 } |
| 54 | 54 |
| 55 inline SVGUseElement::SVGUseElement(Document& document) | 55 inline SVGUseElement::SVGUseElement(Document& document) |
| 56 : SVGGraphicsElement(SVGNames::useTag, document) | 56 : SVGGraphicsElement(SVGNames::useTag, document) |
| 57 , SVGURIReference(this) | 57 , SVGURIReference(this) |
| 58 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(SVG
LengthMode::Width))) | 58 , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(SVG
LengthMode::Width))) |
| 59 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(SVG
LengthMode::Height))) | 59 , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(SVG
LengthMode::Height))) |
| 60 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::cr
eate(SVGLengthMode::Width))) | 60 , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::cr
eate(SVGLengthMode::Width))) |
| 61 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::
create(SVGLengthMode::Height))) | 61 , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::
create(SVGLengthMode::Height))) |
| 62 , m_haveFiredLoadEvent(false) | 62 , m_haveFiredLoadEvent(false) |
| 63 , m_needsShadowTreeRecreation(false) | 63 , m_needsShadowTreeRecreation(false) |
| 64 { | 64 { |
| 65 ASSERT(hasCustomStyleCallbacks()); | 65 ASSERT(hasCustomStyleCallbacks()); |
| 66 | 66 |
| 67 addToPropertyMap(m_x); | 67 addToPropertyMap(m_x); |
| 68 addToPropertyMap(m_y); | 68 addToPropertyMap(m_y); |
| 69 addToPropertyMap(m_width); | 69 addToPropertyMap(m_width); |
| 70 addToPropertyMap(m_height); | 70 addToPropertyMap(m_height); |
| 71 | 71 |
| 72 #if ENABLE(OILPAN) | 72 #if ENABLE(OILPAN) |
| 73 ThreadState::current()->registerPreFinalizer(this); | 73 ThreadState::current()->registerPreFinalizer(this); |
| 74 #endif | 74 #endif |
| 75 } | 75 } |
| 76 | 76 |
| 77 PassRefPtrWillBeRawPtr<SVGUseElement> SVGUseElement::create(Document& document) | 77 RawPtr<SVGUseElement> SVGUseElement::create(Document& document) |
| 78 { | 78 { |
| 79 // Always build a user agent #shadow-root for SVGUseElement. | 79 // Always build a user agent #shadow-root for SVGUseElement. |
| 80 RefPtrWillBeRawPtr<SVGUseElement> use = adoptRefWillBeNoop(new SVGUseElement
(document)); | 80 RawPtr<SVGUseElement> use = new SVGUseElement(document); |
| 81 use->ensureUserAgentShadowRoot(); | 81 use->ensureUserAgentShadowRoot(); |
| 82 return use.release(); | 82 return use.release(); |
| 83 } | 83 } |
| 84 | 84 |
| 85 SVGUseElement::~SVGUseElement() | 85 SVGUseElement::~SVGUseElement() |
| 86 { | 86 { |
| 87 #if !ENABLE(OILPAN) | 87 #if !ENABLE(OILPAN) |
| 88 clearShadowTree(); | 88 clearShadowTree(); |
| 89 cancelShadowTreeRecreation(); | 89 cancelShadowTreeRecreation(); |
| 90 svgUseLoadEventSender().cancelEvent(this); | 90 svgUseLoadEventSender().cancelEvent(this); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 element->parentNode()->removeChild(element); | 378 element->parentNode()->removeChild(element); |
| 379 element = next; | 379 element = next; |
| 380 } else { | 380 } else { |
| 381 element = ElementTraversal::next(*element, &subtree); | 381 element = ElementTraversal::next(*element, &subtree); |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 } | 384 } |
| 385 | 385 |
| 386 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe
rNode& destinationRoot) | 386 static void moveChildrenToReplacementElement(ContainerNode& sourceRoot, Containe
rNode& destinationRoot) |
| 387 { | 387 { |
| 388 for (RefPtrWillBeRawPtr<Node> child = sourceRoot.firstChild(); child; ) { | 388 for (RawPtr<Node> child = sourceRoot.firstChild(); child; ) { |
| 389 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); | 389 RawPtr<Node> nextChild = child->nextSibling(); |
| 390 destinationRoot.appendChild(child); | 390 destinationRoot.appendChild(child); |
| 391 child = nextChild.release(); | 391 child = nextChild.release(); |
| 392 } | 392 } |
| 393 } | 393 } |
| 394 | 394 |
| 395 PassRefPtrWillBeRawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& ta
rgetRoot) const | 395 RawPtr<Element> SVGUseElement::createInstanceTree(SVGElement& targetRoot) const |
| 396 { | 396 { |
| 397 RefPtrWillBeRawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildr
en(); | 397 RawPtr<Element> instanceRoot = targetRoot.cloneElementWithChildren(); |
| 398 ASSERT(instanceRoot->isSVGElement()); | 398 ASSERT(instanceRoot->isSVGElement()); |
| 399 if (isSVGSymbolElement(targetRoot)) { | 399 if (isSVGSymbolElement(targetRoot)) { |
| 400 // Spec: The referenced 'symbol' and its contents are deep-cloned into | 400 // Spec: The referenced 'symbol' and its contents are deep-cloned into |
| 401 // the generated tree, with the exception that the 'symbol' is replaced | 401 // the generated tree, with the exception that the 'symbol' is replaced |
| 402 // by an 'svg'. This generated 'svg' will always have explicit values | 402 // by an 'svg'. This generated 'svg' will always have explicit values |
| 403 // for attributes width and height. If attributes width and/or height | 403 // for attributes width and height. If attributes width and/or height |
| 404 // are provided on the 'use' element, then these attributes will be | 404 // are provided on the 'use' element, then these attributes will be |
| 405 // transferred to the generated 'svg'. If attributes width and/or | 405 // transferred to the generated 'svg'. If attributes width and/or |
| 406 // height are not specified, the generated 'svg' element will use | 406 // height are not specified, the generated 'svg' element will use |
| 407 // values of 100% for these attributes. | 407 // values of 100% for these attributes. |
| 408 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(tar
getRoot.document()); | 408 RawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(targetRoot.docu
ment()); |
| 409 // Transfer all data (attributes, etc.) from the <symbol> to the new | 409 // Transfer all data (attributes, etc.) from the <symbol> to the new |
| 410 // <svg> element. | 410 // <svg> element. |
| 411 svgElement->cloneDataFromElement(*instanceRoot); | 411 svgElement->cloneDataFromElement(*instanceRoot); |
| 412 // Move already cloned elements to the new <svg> element. | 412 // Move already cloned elements to the new <svg> element. |
| 413 moveChildrenToReplacementElement(*instanceRoot, *svgElement); | 413 moveChildrenToReplacementElement(*instanceRoot, *svgElement); |
| 414 instanceRoot = svgElement.release(); | 414 instanceRoot = svgElement.release(); |
| 415 } | 415 } |
| 416 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), target
Root); | 416 transferUseWidthAndHeightIfNeeded(*this, toSVGElement(*instanceRoot), target
Root); |
| 417 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); | 417 associateCorrespondingElements(targetRoot, toSVGElement(*instanceRoot)); |
| 418 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); | 418 removeDisallowedElementsFromSubtree(toSVGElement(*instanceRoot)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 429 // pass -- see expandUseElementsInShadowTree(). | 429 // pass -- see expandUseElementsInShadowTree(). |
| 430 if (inUseShadowTree()) | 430 if (inUseShadowTree()) |
| 431 return; | 431 return; |
| 432 | 432 |
| 433 // Do not allow self-referencing. | 433 // Do not allow self-referencing. |
| 434 if (&target == this || isDisallowedElement(target)) | 434 if (&target == this || isDisallowedElement(target)) |
| 435 return; | 435 return; |
| 436 | 436 |
| 437 // Set up root SVG element in shadow tree. | 437 // Set up root SVG element in shadow tree. |
| 438 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. | 438 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. |
| 439 RefPtrWillBeRawPtr<Element> instanceRoot = createInstanceTree(target); | 439 RawPtr<Element> instanceRoot = createInstanceTree(target); |
| 440 m_targetElementInstance = toSVGElement(instanceRoot.get()); | 440 m_targetElementInstance = toSVGElement(instanceRoot.get()); |
| 441 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 441 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
| 442 shadowTreeRootElement->appendChild(instanceRoot.release()); | 442 shadowTreeRootElement->appendChild(instanceRoot.release()); |
| 443 | 443 |
| 444 addReferencesToFirstDegreeNestedUseElements(target); | 444 addReferencesToFirstDegreeNestedUseElements(target); |
| 445 | 445 |
| 446 if (instanceTreeIsLoading()) { | 446 if (instanceTreeIsLoading()) { |
| 447 cloneNonMarkupEventListeners(); | 447 cloneNonMarkupEventListeners(); |
| 448 return; | 448 return; |
| 449 } | 449 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 bool SVGUseElement::expandUseElementsInShadowTree() | 593 bool SVGUseElement::expandUseElementsInShadowTree() |
| 594 { | 594 { |
| 595 // Why expand the <use> elements in the shadow tree here, and not just | 595 // Why expand the <use> elements in the shadow tree here, and not just |
| 596 // do this directly in buildShadowTree, if we encounter a <use> element? | 596 // do this directly in buildShadowTree, if we encounter a <use> element? |
| 597 // | 597 // |
| 598 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> | 598 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> |
| 599 // contains <use> tags, we'd miss them. So once we're done with setting up t
he | 599 // contains <use> tags, we'd miss them. So once we're done with setting up t
he |
| 600 // actual shadow tree (after the special case modification for svg/symbol) w
e have | 600 // actual shadow tree (after the special case modification for svg/symbol) w
e have |
| 601 // to walk it completely and expand all <use> elements. | 601 // to walk it completely and expand all <use> elements. |
| 602 ShadowRoot* shadowRoot = userAgentShadowRoot(); | 602 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
| 603 for (RefPtrWillBeRawPtr<SVGUseElement> use = Traversal<SVGUseElement>::first
Within(*shadowRoot); use; ) { | 603 for (RawPtr<SVGUseElement> use = Traversal<SVGUseElement>::firstWithin(*shad
owRoot); use; ) { |
| 604 ASSERT(!use->resourceIsStillLoading()); | 604 ASSERT(!use->resourceIsStillLoading()); |
| 605 | 605 |
| 606 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement(
)); | 606 SVGUseElement& originalUse = toSVGUseElement(*use->correspondingElement(
)); |
| 607 SVGElement* target = nullptr; | 607 SVGElement* target = nullptr; |
| 608 if (hasCycleUseReferencing(originalUse, *use, target)) | 608 if (hasCycleUseReferencing(originalUse, *use, target)) |
| 609 return false; | 609 return false; |
| 610 | 610 |
| 611 if (target && isDisallowedElement(*target)) | 611 if (target && isDisallowedElement(*target)) |
| 612 return false; | 612 return false; |
| 613 // Don't ASSERT(target) here, it may be "pending", too. | 613 // Don't ASSERT(target) here, it may be "pending", too. |
| 614 // Setup sub-shadow tree root node | 614 // Setup sub-shadow tree root node |
| 615 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(origin
alUse.document()); | 615 RawPtr<SVGGElement> cloneParent = SVGGElement::create(originalUse.docume
nt()); |
| 616 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. | 616 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. |
| 617 cloneParent->cloneDataFromElement(*use); | 617 cloneParent->cloneDataFromElement(*use); |
| 618 cloneParent->setCorrespondingElement(&originalUse); | 618 cloneParent->setCorrespondingElement(&originalUse); |
| 619 | 619 |
| 620 removeAttributesFromReplacementElement(*cloneParent); | 620 removeAttributesFromReplacementElement(*cloneParent); |
| 621 | 621 |
| 622 // Move already cloned elements to the new <g> element. | 622 // Move already cloned elements to the new <g> element. |
| 623 moveChildrenToReplacementElement(*use, *cloneParent); | 623 moveChildrenToReplacementElement(*use, *cloneParent); |
| 624 | 624 |
| 625 if (target) | 625 if (target) |
| 626 cloneParent->appendChild(use->createInstanceTree(*target)); | 626 cloneParent->appendChild(use->createInstanceTree(*target)); |
| 627 | 627 |
| 628 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); | 628 RawPtr<SVGElement> replacingElement(cloneParent.get()); |
| 629 | 629 |
| 630 // Replace <use> with referenced content. | 630 // Replace <use> with referenced content. |
| 631 use->parentNode()->replaceChild(cloneParent.release(), use); | 631 use->parentNode()->replaceChild(cloneParent.release(), use); |
| 632 | 632 |
| 633 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); | 633 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); |
| 634 } | 634 } |
| 635 return true; | 635 return true; |
| 636 } | 636 } |
| 637 | 637 |
| 638 void SVGUseElement::invalidateShadowTree() | 638 void SVGUseElement::invalidateShadowTree() |
| 639 { | 639 { |
| 640 if (!inActiveDocument() || m_needsShadowTreeRecreation) | 640 if (!inActiveDocument() || m_needsShadowTreeRecreation) |
| 641 return; | 641 return; |
| 642 clearInstanceRoot(); | 642 clearInstanceRoot(); |
| 643 scheduleShadowTreeRecreation(); | 643 scheduleShadowTreeRecreation(); |
| 644 invalidateDependentShadowTrees(); | 644 invalidateDependentShadowTrees(); |
| 645 } | 645 } |
| 646 | 646 |
| 647 void SVGUseElement::invalidateDependentShadowTrees() | 647 void SVGUseElement::invalidateDependentShadowTrees() |
| 648 { | 648 { |
| 649 // Recursively invalidate dependent <use> shadow trees | 649 // Recursively invalidate dependent <use> shadow trees |
| 650 const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement>>& rawInstances =
instancesForElement(); | 650 const HeapHashSet<WeakMember<SVGElement>>& rawInstances = instancesForElemen
t(); |
| 651 WillBeHeapVector<RefPtrWillBeMember<SVGElement>> instances; | 651 HeapVector<Member<SVGElement>> instances; |
| 652 instances.appendRange(rawInstances.begin(), rawInstances.end()); | 652 instances.appendRange(rawInstances.begin(), rawInstances.end()); |
| 653 for (auto& instance : instances) { | 653 for (auto& instance : instances) { |
| 654 if (RefPtrWillBeRawPtr<SVGUseElement> element = instance->correspondingU
seElement()) { | 654 if (RawPtr<SVGUseElement> element = instance->correspondingUseElement())
{ |
| 655 ASSERT(element->inDocument()); | 655 ASSERT(element->inDocument()); |
| 656 element->invalidateShadowTree(); | 656 element->invalidateShadowTree(); |
| 657 } | 657 } |
| 658 } | 658 } |
| 659 } | 659 } |
| 660 | 660 |
| 661 bool SVGUseElement::selfHasRelativeLengths() const | 661 bool SVGUseElement::selfHasRelativeLengths() const |
| 662 { | 662 { |
| 663 if (m_x->currentValue()->isRelative() | 663 if (m_x->currentValue()->isRelative() |
| 664 || m_y->currentValue()->isRelative() | 664 || m_y->currentValue()->isRelative() |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 | 737 |
| 738 bool SVGUseElement::instanceTreeIsLoading() const | 738 bool SVGUseElement::instanceTreeIsLoading() const |
| 739 { | 739 { |
| 740 for (const SVGUseElement& useElement : Traversal<SVGUseElement>::descendants
Of(*userAgentShadowRoot())) { | 740 for (const SVGUseElement& useElement : Traversal<SVGUseElement>::descendants
Of(*userAgentShadowRoot())) { |
| 741 if (useElement.resourceIsStillLoading()) | 741 if (useElement.resourceIsStillLoading()) |
| 742 return true; | 742 return true; |
| 743 } | 743 } |
| 744 return false; | 744 return false; |
| 745 } | 745 } |
| 746 | 746 |
| 747 void SVGUseElement::setDocumentResource(PassRefPtrWillBeRawPtr<DocumentResource>
resource) | 747 void SVGUseElement::setDocumentResource(RawPtr<DocumentResource> resource) |
| 748 { | 748 { |
| 749 if (m_resource == resource) | 749 if (m_resource == resource) |
| 750 return; | 750 return; |
| 751 | 751 |
| 752 if (m_resource) | 752 if (m_resource) |
| 753 m_resource->removeClient(this); | 753 m_resource->removeClient(this); |
| 754 | 754 |
| 755 m_resource = resource; | 755 m_resource = resource; |
| 756 if (m_resource) | 756 if (m_resource) |
| 757 m_resource->addClient(this); | 757 m_resource->addClient(this); |
| 758 } | 758 } |
| 759 | 759 |
| 760 } // namespace blink | 760 } // namespace blink |
| OLD | NEW |