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 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 ASSERT(!m_targetElementInstance->shadowTreeElement()); | 474 ASSERT(!m_targetElementInstance->shadowTreeElement()); |
475 ASSERT(m_targetElementInstance->correspondingUseElement() == this); | 475 ASSERT(m_targetElementInstance->correspondingUseElement() == this); |
476 ASSERT(m_targetElementInstance->directUseElement() == this); | 476 ASSERT(m_targetElementInstance->directUseElement() == this); |
477 ASSERT(m_targetElementInstance->correspondingElement() == target); | 477 ASSERT(m_targetElementInstance->correspondingElement() == target); |
478 | 478 |
479 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 479 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
480 ASSERT(shadowTreeRootElement); | 480 ASSERT(shadowTreeRootElement); |
481 | 481 |
482 // Build shadow tree from instance tree | 482 // Build shadow tree from instance tree |
483 // This also handles the special cases: <use> on <symbol>, <use> on <svg>. | 483 // This also handles the special cases: <use> on <symbol>, <use> on <svg>. |
484 buildShadowTree(target, m_targetElementInstance.get()); | 484 buildShadowTree(target, m_targetElementInstance.get(), shadowTreeRootElement
); |
485 | 485 |
486 // Expand all <use> elements in the shadow tree. | 486 // Expand all <use> elements in the shadow tree. |
487 // Expand means: replace the actual <use> element by what it references. | 487 // Expand means: replace the actual <use> element by what it references. |
488 expandUseElementsInShadowTree(shadowTreeRootElement); | 488 expandUseElementsInShadowTree(shadowTreeRootElement); |
489 | 489 |
490 // Expand all <symbol> elements in the shadow tree. | 490 // Expand all <symbol> elements in the shadow tree. |
491 // Expand means: replace the actual <symbol> element by the <svg> element. | 491 // Expand means: replace the actual <symbol> element by the <svg> element. |
492 expandSymbolElementsInShadowTree(shadowTreeRootElement); | 492 expandSymbolElementsInShadowTree(shadowTreeRootElement); |
493 | 493 |
494 // Now that the shadow tree is completly expanded, we can associate | |
495 // shadow tree elements <-> instances in the instance tree. | |
496 associateInstancesWithShadowTreeElements(shadowTreeRootElement->firstChild()
, m_targetElementInstance.get()); | |
497 | |
498 ASSERT(m_targetElementInstance->correspondingElement()); | |
499 transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance->shadowTree
Element(), *m_targetElementInstance->correspondingElement()); | |
500 | |
501 // If no shadow tree element is present, this means that the reference root | 494 // If no shadow tree element is present, this means that the reference root |
502 // element was removed, as it is disallowed (ie. <use> on <foreignObject>) | 495 // element was removed, as it is disallowed (ie. <use> on <foreignObject>) |
503 // Do NOT leave an inconsistent instance tree around, instead destruct it. | 496 // Do NOT leave an inconsistent instance tree around, instead destruct it. |
504 if (!m_targetElementInstance->shadowTreeElement()) { | 497 Node* shadowTreeTargetNode = shadowTreeRootElement->firstChild(); |
| 498 if (!shadowTreeTargetNode) { |
505 clearResourceReferences(); | 499 clearResourceReferences(); |
506 return; | 500 return; |
507 } | 501 } |
508 | 502 |
509 ASSERT(m_targetElementInstance->shadowTreeElement()->parentNode() == shadowT
reeRootElement); | 503 // Now that the shadow tree is completly expanded, we can associate |
| 504 // shadow tree elements <-> instances in the instance tree. |
| 505 associateInstancesWithShadowTreeElements(shadowTreeTargetNode, m_targetEleme
ntInstance.get()); |
| 506 |
| 507 SVGElement* shadowTreeTargetElement = toSVGElement(shadowTreeTargetNode); |
| 508 ASSERT(shadowTreeTargetElement->correspondingElement()); |
| 509 transferUseWidthAndHeightIfNeeded(*this, shadowTreeTargetElement, *shadowTre
eTargetElement->correspondingElement()); |
| 510 |
| 511 ASSERT(shadowTreeTargetElement->parentNode() == shadowTreeRootElement); |
510 | 512 |
511 // Transfer event listeners assigned to the referenced element to our shadow
tree elements. | 513 // Transfer event listeners assigned to the referenced element to our shadow
tree elements. |
512 transferEventListenersToShadowTree(m_targetElementInstance.get()); | 514 transferEventListenersToShadowTree(shadowTreeTargetElement); |
513 | 515 |
514 // Update relative length information. | 516 // Update relative length information. |
515 updateRelativeLengthsInformation(); | 517 updateRelativeLengthsInformation(); |
516 | 518 |
517 // Eventually dump instance tree | 519 // Eventually dump instance tree |
518 #ifdef DUMP_INSTANCE_TREE | 520 #ifdef DUMP_INSTANCE_TREE |
519 String text; | 521 String text; |
520 unsigned depth = 0; | 522 unsigned depth = 0; |
521 | 523 |
522 dumpInstanceTree(depth, text, m_targetElementInstance.get()); | 524 dumpInstanceTree(depth, text, m_targetElementInstance.get()); |
(...skipping 21 matching lines...) Expand all Loading... |
544 || isSVGEllipseElement(node) | 546 || isSVGEllipseElement(node) |
545 || isSVGPolygonElement(node) | 547 || isSVGPolygonElement(node) |
546 || isSVGPolylineElement(node) | 548 || isSVGPolylineElement(node) |
547 || isSVGTextElement(node); | 549 || isSVGTextElement(node); |
548 } | 550 } |
549 | 551 |
550 void SVGUseElement::toClipPath(Path& path) | 552 void SVGUseElement::toClipPath(Path& path) |
551 { | 553 { |
552 ASSERT(path.isEmpty()); | 554 ASSERT(path.isEmpty()); |
553 | 555 |
554 Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeEleme
nt() : 0; | 556 Node* n = userAgentShadowRoot()->firstChild(); |
555 if (!n) | 557 if (!n) |
556 return; | 558 return; |
557 | 559 |
558 if (n->isSVGElement() && toSVGElement(n)->isSVGGraphicsElement()) { | 560 if (n->isSVGElement() && toSVGElement(n)->isSVGGraphicsElement()) { |
559 if (!isDirectReference(*n)) { | 561 if (!isDirectReference(*n)) { |
560 // Spec: Indirect references are an error (14.3.5) | 562 // Spec: Indirect references are an error (14.3.5) |
561 document().accessSVGExtensions().reportError("Not allowed to use ind
irect reference in <clip-path>"); | 563 document().accessSVGExtensions().reportError("Not allowed to use ind
irect reference in <clip-path>"); |
562 } else { | 564 } else { |
563 toSVGGraphicsElement(n)->toClipPath(path); | 565 toSVGGraphicsElement(n)->toClipPath(path); |
564 // FIXME: Avoid manual resolution of x/y here. Its potentially harmf
ul. | 566 // FIXME: Avoid manual resolution of x/y here. Its potentially harmf
ul. |
565 SVGLengthContext lengthContext(this); | 567 SVGLengthContext lengthContext(this); |
566 path.translate(FloatSize(m_x->currentValue()->value(lengthContext),
m_y->currentValue()->value(lengthContext))); | 568 path.translate(FloatSize(m_x->currentValue()->value(lengthContext),
m_y->currentValue()->value(lengthContext))); |
567 path.transform(animatedLocalTransform()); | 569 path.transform(animatedLocalTransform()); |
568 } | 570 } |
569 } | 571 } |
570 } | 572 } |
571 | 573 |
572 RenderObject* SVGUseElement::rendererClipChild() const | 574 RenderObject* SVGUseElement::rendererClipChild() const |
573 { | 575 { |
574 Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeEleme
nt() : 0; | 576 if (Node* n = userAgentShadowRoot()->firstChild()) { |
575 if (!n) | 577 if (n->isSVGElement() && isDirectReference(*n)) |
576 return 0; | 578 return toSVGElement(n)->renderer(); |
577 | 579 } |
578 if (n->isSVGElement() && isDirectReference(*n)) | |
579 return toSVGElement(n)->renderer(); | |
580 | 580 |
581 return 0; | 581 return 0; |
582 } | 582 } |
583 | 583 |
584 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
rgetInstance, bool& foundProblem, bool foundUse) | 584 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
rgetInstance, bool& foundProblem, bool foundUse) |
585 { | 585 { |
586 ASSERT(target); | 586 ASSERT(target); |
587 ASSERT(targetInstance); | 587 ASSERT(targetInstance); |
588 | 588 |
589 // Spec: If the referenced object is itself a 'use', or if there are 'use' s
ubelements within the referenced | 589 // Spec: If the referenced object is itself a 'use', or if there are 'use' s
ubelements within the referenced |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); | 675 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); |
676 // The subtree is not in document so this won't generate events that
could mutate the tree. | 676 // The subtree is not in document so this won't generate events that
could mutate the tree. |
677 element->parentNode()->removeChild(element); | 677 element->parentNode()->removeChild(element); |
678 element = next; | 678 element = next; |
679 } else { | 679 } else { |
680 element = ElementTraversal::next(*element, &subtree); | 680 element = ElementTraversal::next(*element, &subtree); |
681 } | 681 } |
682 } | 682 } |
683 } | 683 } |
684 | 684 |
685 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targ
etInstance) | 685 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targ
etInstance, ShadowRoot* shadowTreeRootElement) |
686 { | 686 { |
687 // For instance <use> on <foreignObject> (direct case). | 687 // For instance <use> on <foreignObject> (direct case). |
688 if (isDisallowedElement(target)) | 688 if (isDisallowedElement(target)) |
689 return; | 689 return; |
690 | 690 |
691 RefPtr<Element> newChild = targetInstance->correspondingElement()->cloneElem
entWithChildren(); | 691 RefPtr<Element> newChild = targetInstance->correspondingElement()->cloneElem
entWithChildren(); |
692 | 692 |
693 // We don't walk the target tree element-by-element, and clone each element, | 693 // We don't walk the target tree element-by-element, and clone each element, |
694 // but instead use cloneElementWithChildren(). This is an optimization for t
he common | 694 // but instead use cloneElementWithChildren(). This is an optimization for t
he common |
695 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>
). | 695 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>
). |
696 // Though if there are disallowed elements in the subtree, we have to remove
them. | 696 // Though if there are disallowed elements in the subtree, we have to remove
them. |
697 // For instance: <use> on <g> containing <foreignObject> (indirect case). | 697 // For instance: <use> on <g> containing <foreignObject> (indirect case). |
698 if (subtreeContainsDisallowedElement(newChild.get())) | 698 if (subtreeContainsDisallowedElement(newChild.get())) |
699 removeDisallowedElementsFromSubtree(*newChild); | 699 removeDisallowedElementsFromSubtree(*newChild); |
700 | 700 |
701 userAgentShadowRoot()->appendChild(newChild.release()); | 701 shadowTreeRootElement->appendChild(newChild.release()); |
702 } | 702 } |
703 | 703 |
704 void SVGUseElement::expandUseElementsInShadowTree(Node* element) | 704 void SVGUseElement::expandUseElementsInShadowTree(Node* element) |
705 { | 705 { |
706 ASSERT(element); | 706 ASSERT(element); |
707 // Why expand the <use> elements in the shadow tree here, and not just | 707 // Why expand the <use> elements in the shadow tree here, and not just |
708 // do this directly in buildShadowTree, if we encounter a <use> element? | 708 // do this directly in buildShadowTree, if we encounter a <use> element? |
709 // | 709 // |
710 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> | 710 // Short answer: Because we may miss to expand some elements. For example, i
f a <symbol> |
711 // contains <use> tags, we'd miss them. So once we're done with setting up t
he | 711 // contains <use> tags, we'd miss them. So once we're done with setting up t
he |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 // lose the sibling chain when we are back from recursion. | 801 // lose the sibling chain when we are back from recursion. |
802 element = replacingElement.get(); | 802 element = replacingElement.get(); |
803 for (RefPtr<Node> sibling = element->nextSibling(); sibling; sibling = s
ibling->nextSibling()) | 803 for (RefPtr<Node> sibling = element->nextSibling(); sibling; sibling = s
ibling->nextSibling()) |
804 expandSymbolElementsInShadowTree(sibling.get()); | 804 expandSymbolElementsInShadowTree(sibling.get()); |
805 } | 805 } |
806 | 806 |
807 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextS
ibling()) | 807 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextS
ibling()) |
808 expandSymbolElementsInShadowTree(child.get()); | 808 expandSymbolElementsInShadowTree(child.get()); |
809 } | 809 } |
810 | 810 |
811 void SVGUseElement::transferEventListenersToShadowTree(SVGElementInstance* targe
t) | 811 void SVGUseElement::transferEventListenersToShadowTree(SVGElement* shadowTreeTar
getElement) |
812 { | 812 { |
813 if (!target) | 813 if (!shadowTreeTargetElement) |
814 return; | 814 return; |
815 | 815 |
816 SVGElement* originalElement = target->correspondingElement(); | 816 SVGElement* originalElement = shadowTreeTargetElement->correspondingElement(
); |
817 ASSERT(originalElement); | 817 ASSERT(originalElement); |
| 818 if (EventTargetData* data = originalElement->eventTargetData()) |
| 819 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(sh
adowTreeTargetElement); |
818 | 820 |
819 if (SVGElement* shadowTreeElement = target->shadowTreeElement()) { | 821 for (SVGElement* child = Traversal<SVGElement>::firstChild(*shadowTreeTarget
Element); child; child = Traversal<SVGElement>::nextSibling(*child)) |
820 if (EventTargetData* data = originalElement->eventTargetData()) | 822 transferEventListenersToShadowTree(child); |
821 data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarge
t(shadowTreeElement); | |
822 } | |
823 | |
824 for (SVGElementInstance* instance = target->firstChild(); instance; instance
= instance->nextSibling()) | |
825 transferEventListenersToShadowTree(instance); | |
826 } | 823 } |
827 | 824 |
828 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGEl
ementInstance* targetInstance) | 825 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGEl
ementInstance* targetInstance) |
829 { | 826 { |
830 if (!target || !targetInstance) | 827 if (!target || !targetInstance) |
831 return; | 828 return; |
832 | 829 |
833 SVGElement* originalElement = targetInstance->correspondingElement(); | 830 SVGElement* originalElement = targetInstance->correspondingElement(); |
834 ASSERT(originalElement); | 831 ASSERT(originalElement); |
835 if (isSVGUseElement(*originalElement)) { | 832 if (isSVGUseElement(*originalElement)) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 | 994 |
998 if (m_resource) | 995 if (m_resource) |
999 m_resource->removeClient(this); | 996 m_resource->removeClient(this); |
1000 | 997 |
1001 m_resource = resource; | 998 m_resource = resource; |
1002 if (m_resource) | 999 if (m_resource) |
1003 m_resource->addClient(this); | 1000 m_resource->addClient(this); |
1004 } | 1001 } |
1005 | 1002 |
1006 } | 1003 } |
OLD | NEW |