| 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 |