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 |