| 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 21 matching lines...) Expand all Loading... |
| 32 #include "core/dom/shadow/ElementShadow.h" | 32 #include "core/dom/shadow/ElementShadow.h" |
| 33 #include "core/dom/shadow/ShadowRoot.h" | 33 #include "core/dom/shadow/ShadowRoot.h" |
| 34 #include "core/events/Event.h" | 34 #include "core/events/Event.h" |
| 35 #include "core/fetch/FetchRequest.h" | 35 #include "core/fetch/FetchRequest.h" |
| 36 #include "core/fetch/ResourceFetcher.h" | 36 #include "core/fetch/ResourceFetcher.h" |
| 37 #include "core/layout/svg/LayoutSVGTransformableContainer.h" | 37 #include "core/layout/svg/LayoutSVGTransformableContainer.h" |
| 38 #include "core/svg/SVGDocumentExtensions.h" | 38 #include "core/svg/SVGDocumentExtensions.h" |
| 39 #include "core/svg/SVGGElement.h" | 39 #include "core/svg/SVGGElement.h" |
| 40 #include "core/svg/SVGLengthContext.h" | 40 #include "core/svg/SVGLengthContext.h" |
| 41 #include "core/svg/SVGSVGElement.h" | 41 #include "core/svg/SVGSVGElement.h" |
| 42 #include "core/svg/SVGSymbolElement.h" |
| 42 #include "core/xml/parser/XMLDocumentParser.h" | 43 #include "core/xml/parser/XMLDocumentParser.h" |
| 43 #include "wtf/Vector.h" | 44 #include "wtf/Vector.h" |
| 44 | 45 |
| 45 namespace blink { | 46 namespace blink { |
| 46 | 47 |
| 47 static SVGUseEventSender& svgUseLoadEventSender() | 48 static SVGUseEventSender& svgUseLoadEventSender() |
| 48 { | 49 { |
| 49 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGUseEventSender>, sharedLoadEve
ntSender, (SVGUseEventSender::create(EventTypeNames::load))); | 50 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGUseEventSender>, sharedLoadEve
ntSender, (SVGUseEventSender::create(EventTypeNames::load))); |
| 50 return *sharedLoadEventSender; | 51 return *sharedLoadEventSender; |
| 51 } | 52 } |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 return; | 417 return; |
| 417 } | 418 } |
| 418 | 419 |
| 419 // Assure shadow tree building was successful. | 420 // Assure shadow tree building was successful. |
| 420 ASSERT(m_targetElementInstance); | 421 ASSERT(m_targetElementInstance); |
| 421 ASSERT(m_targetElementInstance->correspondingUseElement() == this); | 422 ASSERT(m_targetElementInstance->correspondingUseElement() == this); |
| 422 ASSERT(m_targetElementInstance->correspondingElement() == target); | 423 ASSERT(m_targetElementInstance->correspondingElement() == target); |
| 423 | 424 |
| 424 // Expand all <use> elements in the shadow tree. | 425 // Expand all <use> elements in the shadow tree. |
| 425 // Expand means: replace the actual <use> element by what it references. | 426 // Expand means: replace the actual <use> element by what it references. |
| 426 if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) { | 427 if (!expandUseElementsInShadowTree()) { |
| 427 clearShadowTree(); | 428 clearShadowTree(); |
| 428 return; | 429 return; |
| 429 } | 430 } |
| 430 | 431 |
| 431 // Expand all <symbol> elements in the shadow tree. | 432 // Expand all <symbol> elements in the shadow tree. |
| 432 // Expand means: replace the actual <symbol> element by the <svg> element. | 433 // Expand means: replace the actual <symbol> element by the <svg> element. |
| 433 expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstCh
ild())); | 434 expandSymbolElementsInShadowTree(); |
| 434 | 435 |
| 435 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); | 436 m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); |
| 436 transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_t
argetElementInstance->correspondingElement()); | 437 transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_t
argetElementInstance->correspondingElement()); |
| 437 cloneNonMarkupEventListeners(); | 438 cloneNonMarkupEventListeners(); |
| 438 | 439 |
| 439 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); | 440 ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); |
| 440 | 441 |
| 441 // Update relative length information. | 442 // Update relative length information. |
| 442 updateRelativeLengthsInformation(); | 443 updateRelativeLengthsInformation(); |
| 443 } | 444 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); | 578 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); |
| 578 // The subtree is not in document so this won't generate events that
could mutate the tree. | 579 // The subtree is not in document so this won't generate events that
could mutate the tree. |
| 579 element->parentNode()->removeChild(element); | 580 element->parentNode()->removeChild(element); |
| 580 element = next; | 581 element = next; |
| 581 } else { | 582 } else { |
| 582 element = ElementTraversal::next(*element, &subtree); | 583 element = ElementTraversal::next(*element, &subtree); |
| 583 } | 584 } |
| 584 } | 585 } |
| 585 } | 586 } |
| 586 | 587 |
| 587 bool SVGUseElement::expandUseElementsInShadowTree(SVGElement* element) | 588 bool SVGUseElement::expandUseElementsInShadowTree() |
| 588 { | 589 { |
| 589 ASSERT(element); | |
| 590 // Why expand the <use> elements in the shadow tree here, and not just | 590 // Why expand the <use> elements in the shadow tree here, and not just |
| 591 // do this directly in buildShadowTree, if we encounter a <use> element? | 591 // do this directly in buildShadowTree, if we encounter a <use> element? |
| 592 // | 592 // |
| 593 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> | 593 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> |
| 594 // contains <use> tags, we'd miss them. So once we're done with setting up t
he | 594 // contains <use> tags, we'd miss them. So once we're done with setting up t
he |
| 595 // actual shadow tree (after the special case modification for svg/symbol) w
e have | 595 // actual shadow tree (after the special case modification for svg/symbol) w
e have |
| 596 // to walk it completely and expand all <use> elements. | 596 // to walk it completely and expand all <use> elements. |
| 597 if (isSVGUseElement(*element)) { | 597 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
| 598 SVGUseElement* use = toSVGUseElement(element); | 598 for (RefPtrWillBeRawPtr<SVGUseElement> use = Traversal<SVGUseElement>::first
Within(*shadowRoot); use; ) { |
| 599 ASSERT(!use->resourceIsStillLoading()); | 599 ASSERT(!use->resourceIsStillLoading()); |
| 600 | 600 |
| 601 SVGElement* target = 0; | 601 SVGElement* target = 0; |
| 602 if (hasCycleUseReferencing(toSVGUseElement(use->correspondingElement()),
use, target)) | 602 if (hasCycleUseReferencing(toSVGUseElement(use->correspondingElement()),
use.get(), target)) |
| 603 return false; | 603 return false; |
| 604 | 604 |
| 605 if (target && isDisallowedElement(target)) | 605 if (target && isDisallowedElement(target)) |
| 606 return false; | 606 return false; |
| 607 // Don't ASSERT(target) here, it may be "pending", too. | 607 // Don't ASSERT(target) here, it may be "pending", too. |
| 608 // Setup sub-shadow tree root node | 608 // Setup sub-shadow tree root node |
| 609 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(refere
ncedScope()->document()); | 609 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(refere
ncedScope()->document()); |
| 610 cloneParent->setCorrespondingElement(use->correspondingElement()); | 610 cloneParent->setCorrespondingElement(use->correspondingElement()); |
| 611 | 611 |
| 612 // Move already cloned elements to the new <g> element | 612 // Move already cloned elements to the new <g> element |
| 613 for (RefPtrWillBeRawPtr<Node> child = use->firstChild(); child; ) { | 613 for (RefPtrWillBeRawPtr<Node> child = use->firstChild(); child; ) { |
| 614 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); | 614 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); |
| 615 cloneParent->appendChild(child); | 615 cloneParent->appendChild(child); |
| 616 child = nextChild.release(); | 616 child = nextChild.release(); |
| 617 } | 617 } |
| 618 | 618 |
| 619 // Spec: In the generated content, the 'use' will be replaced by 'g', wh
ere all attributes from the | 619 // Spec: In the generated content, the 'use' will be replaced by 'g', wh
ere all attributes from the |
| 620 // 'use' element except for x, y, width, height and xlink:href are trans
ferred to the generated 'g' element. | 620 // 'use' element except for x, y, width, height and xlink:href are trans
ferred to the generated 'g' element. |
| 621 transferUseAttributesToReplacedElement(use, cloneParent.get()); | 621 transferUseAttributesToReplacedElement(use.get(), cloneParent.get()); |
| 622 | 622 |
| 623 if (target) { | 623 if (target) { |
| 624 RefPtrWillBeRawPtr<Node> newChild = cloneNodeAndAssociate(*target); | 624 RefPtrWillBeRawPtr<Node> newChild = cloneNodeAndAssociate(*target); |
| 625 ASSERT(newChild->isSVGElement()); | 625 ASSERT(newChild->isSVGElement()); |
| 626 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(newChild.get())
, *target); | 626 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(newChild.get())
, *target); |
| 627 cloneParent->appendChild(newChild.release()); | 627 cloneParent->appendChild(newChild.release()); |
| 628 } | 628 } |
| 629 | 629 |
| 630 // We don't walk the target tree element-by-element, and clone each elem
ent, | 630 // We don't walk the target tree element-by-element, and clone each elem
ent, |
| 631 // but instead use cloneElementWithChildren(). This is an optimization f
or the common | 631 // but instead use cloneElementWithChildren(). This is an optimization f
or the common |
| 632 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). | 632 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). |
| 633 // Though if there are disallowed elements in the subtree, we have to re
move them. | 633 // Though if there are disallowed elements in the subtree, we have to re
move them. |
| 634 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. | 634 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. |
| 635 if (subtreeContainsDisallowedElement(cloneParent.get())) | 635 if (subtreeContainsDisallowedElement(cloneParent.get())) |
| 636 removeDisallowedElementsFromSubtree(*cloneParent); | 636 removeDisallowedElementsFromSubtree(*cloneParent); |
| 637 | 637 |
| 638 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); | 638 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); |
| 639 | 639 |
| 640 // Replace <use> with referenced content. | 640 // Replace <use> with referenced content. |
| 641 ASSERT(use->parentNode()); | |
| 642 use->parentNode()->replaceChild(cloneParent.release(), use); | 641 use->parentNode()->replaceChild(cloneParent.release(), use); |
| 643 | 642 |
| 644 // Expand the siblings because the *element* is replaced and we will | 643 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); |
| 645 // lose the sibling chain when we are back from recursion. | |
| 646 element = replacingElement.get(); | |
| 647 for (RefPtrWillBeRawPtr<SVGElement> sibling = Traversal<SVGElement>::nex
tSibling(*element); sibling; sibling = Traversal<SVGElement>::nextSibling(*sibli
ng)) { | |
| 648 if (!expandUseElementsInShadowTree(sibling.get())) | |
| 649 return false; | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChil
d(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) { | |
| 654 if (!expandUseElementsInShadowTree(child.get())) | |
| 655 return false; | |
| 656 } | 644 } |
| 657 return true; | 645 return true; |
| 658 } | 646 } |
| 659 | 647 |
| 660 void SVGUseElement::expandSymbolElementsInShadowTree(SVGElement* element) | 648 void SVGUseElement::expandSymbolElementsInShadowTree() |
| 661 { | 649 { |
| 662 ASSERT(element); | 650 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
| 663 if (isSVGSymbolElement(*element)) { | 651 for (RefPtrWillBeRawPtr<SVGSymbolElement> symbol = Traversal<SVGSymbolElemen
t>::firstWithin(*shadowRoot); symbol; ) { |
| 664 // Spec: The referenced 'symbol' and its contents are deep-cloned into t
he generated tree, | 652 // Spec: The referenced 'symbol' and its contents are deep-cloned into t
he generated tree, |
| 665 // with the exception that the 'symbol' is replaced by an 'svg'. This ge
nerated 'svg' will | 653 // with the exception that the 'symbol' is replaced by an 'svg'. This ge
nerated 'svg' will |
| 666 // always have explicit values for attributes width and height. If attri
butes width and/or | 654 // always have explicit values for attributes width and height. If attri
butes width and/or |
| 667 // height are provided on the 'use' element, then these attributes will
be transferred to | 655 // height are provided on the 'use' element, then these attributes will
be transferred to |
| 668 // the generated 'svg'. If attributes width and/or height are not specif
ied, the generated | 656 // the generated 'svg'. If attributes width and/or height are not specif
ied, the generated |
| 669 // 'svg' element will use values of 100% for these attributes. | 657 // 'svg' element will use values of 100% for these attributes. |
| 670 ASSERT(referencedScope()); | 658 ASSERT(referencedScope()); |
| 671 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ref
erencedScope()->document()); | 659 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ref
erencedScope()->document()); |
| 672 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e
lement. | 660 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e
lement. |
| 673 svgElement->cloneDataFromElement(*element); | 661 svgElement->cloneDataFromElement(*symbol); |
| 674 svgElement->setCorrespondingElement(element->correspondingElement()); | 662 svgElement->setCorrespondingElement(symbol->correspondingElement()); |
| 675 | 663 |
| 676 // Move already cloned elements to the new <svg> element | 664 // Move already cloned elements to the new <svg> element |
| 677 for (RefPtrWillBeRawPtr<Node> child = element->firstChild(); child; ) { | 665 for (RefPtrWillBeRawPtr<Node> child = symbol->firstChild(); child; ) { |
| 678 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); | 666 RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); |
| 679 svgElement->appendChild(child); | 667 svgElement->appendChild(child); |
| 680 child = nextChild.release(); | 668 child = nextChild.release(); |
| 681 } | 669 } |
| 682 | 670 |
| 683 // We don't walk the target tree element-by-element, and clone each elem
ent, | 671 // We don't walk the target tree element-by-element, and clone each elem
ent, |
| 684 // but instead use cloneNode(deep=true). This is an optimization for the
common | 672 // but instead use cloneNode(deep=true). This is an optimization for the
common |
| 685 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). | 673 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). |
| 686 // Though if there are disallowed elements in the subtree, we have to re
move them. | 674 // Though if there are disallowed elements in the subtree, we have to re
move them. |
| 687 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. | 675 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. |
| 688 if (subtreeContainsDisallowedElement(svgElement.get())) | 676 if (subtreeContainsDisallowedElement(svgElement.get())) |
| 689 removeDisallowedElementsFromSubtree(*svgElement); | 677 removeDisallowedElementsFromSubtree(*svgElement); |
| 690 | 678 |
| 691 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); | 679 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); |
| 692 | 680 |
| 693 // Replace <symbol> with <svg>. | 681 // Replace <symbol> with <svg>. |
| 694 ASSERT(element->parentNode()); | 682 symbol->parentNode()->replaceChild(svgElement.release(), symbol); |
| 695 element->parentNode()->replaceChild(svgElement.release(), element); | |
| 696 | 683 |
| 697 // Expand the siblings because the *element* is replaced and we will | 684 symbol = Traversal<SVGSymbolElement>::next(*replacingElement, shadowRoot
); |
| 698 // lose the sibling chain when we are back from recursion. | |
| 699 element = replacingElement.get(); | |
| 700 for (RefPtrWillBeRawPtr<SVGElement> sibling = Traversal<SVGElement>::nex
tSibling(*element); sibling; sibling = Traversal<SVGElement>::nextSibling(*sibli
ng)) | |
| 701 expandSymbolElementsInShadowTree(sibling.get()); | |
| 702 } | 685 } |
| 703 | |
| 704 for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChil
d(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) | |
| 705 expandSymbolElementsInShadowTree(child.get()); | |
| 706 } | 686 } |
| 707 | 687 |
| 708 void SVGUseElement::invalidateShadowTree() | 688 void SVGUseElement::invalidateShadowTree() |
| 709 { | 689 { |
| 710 if (!inActiveDocument() || m_needsShadowTreeRecreation) | 690 if (!inActiveDocument() || m_needsShadowTreeRecreation) |
| 711 return; | 691 return; |
| 712 clearInstanceRoot(); | 692 clearInstanceRoot(); |
| 713 scheduleShadowTreeRecreation(); | 693 scheduleShadowTreeRecreation(); |
| 714 invalidateDependentShadowTrees(); | 694 invalidateDependentShadowTrees(); |
| 715 } | 695 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 | 816 |
| 837 if (m_resource) | 817 if (m_resource) |
| 838 m_resource->removeClient(this); | 818 m_resource->removeClient(this); |
| 839 | 819 |
| 840 m_resource = resource; | 820 m_resource = resource; |
| 841 if (m_resource) | 821 if (m_resource) |
| 842 m_resource->addClient(this); | 822 m_resource->addClient(this); |
| 843 } | 823 } |
| 844 | 824 |
| 845 } // namespace blink | 825 } // namespace blink |
| OLD | NEW |