| OLD | NEW |
| 1 /* | 1 /* |
| 2 Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kd
e.org> | 2 Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kd
e.org> |
| 3 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 3 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 | 5 |
| 6 This library is free software; you can redistribute it and/or | 6 This library is free software; you can redistribute it and/or |
| 7 modify it under the terms of the GNU Library General Public | 7 modify it under the terms of the GNU Library General Public |
| 8 License as published by the Free Software Foundation; either | 8 License as published by the Free Software Foundation; either |
| 9 version 2 of the License, or (at your option) any later version. | 9 version 2 of the License, or (at your option) any later version. |
| 10 | 10 |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 void SVGUseElement::buildPendingResource() | 381 void SVGUseElement::buildPendingResource() |
| 382 { | 382 { |
| 383 // If we're called the first time (during shadow tree root creation from Ren
derSVGShadowTreeRootContainer) | 383 // If we're called the first time (during shadow tree root creation from Ren
derSVGShadowTreeRootContainer) |
| 384 // we either determine that our target is available or not - then we add our
selves to the pending resource list | 384 // we either determine that our target is available or not - then we add our
selves to the pending resource list |
| 385 // Once the pending resource appears, it will call buildPendingResource(), s
o we're called a second time. | 385 // Once the pending resource appears, it will call buildPendingResource(), s
o we're called a second time. |
| 386 String id = SVGURIReference::getTarget(href()); | 386 String id = SVGURIReference::getTarget(href()); |
| 387 Element* targetElement = document()->getElementById(id); | 387 Element* targetElement = document()->getElementById(id); |
| 388 ASSERT(!m_targetElementInstance); | 388 ASSERT(!m_targetElementInstance); |
| 389 | 389 |
| 390 if (!targetElement) { | 390 if (!targetElement) { |
| 391 if (m_isPendingResource) | 391 if (m_isPendingResource || id.isEmpty()) |
| 392 return; | 392 return; |
| 393 | 393 |
| 394 m_isPendingResource = true; | 394 m_isPendingResource = true; |
| 395 m_resourceId = id; | 395 m_resourceId = id; |
| 396 document()->accessSVGExtensions()->addPendingResource(id, this); | 396 document()->accessSVGExtensions()->addPendingResource(id, this); |
| 397 return; | 397 return; |
| 398 } | 398 } |
| 399 | 399 |
| 400 if (m_isPendingResource) { | 400 if (m_isPendingResource) { |
| 401 ASSERT(!m_targetElementInstance); | 401 ASSERT(!m_targetElementInstance); |
| 402 m_isPendingResource = false; | 402 m_isPendingResource = false; |
| 403 invalidateShadowTree(); | 403 invalidateShadowTree(); |
| 404 } | 404 } |
| 405 } | 405 } |
| 406 | 406 |
| 407 void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR
oot) | 407 void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR
oot) |
| 408 { | 408 { |
| 409 String id = SVGURIReference::getTarget(href()); | 409 String id = SVGURIReference::getTarget(href()); |
| 410 Element* targetElement = document()->getElementById(id); | 410 Element* targetElement = document()->getElementById(id); |
| 411 ASSERT(targetElement); | 411 if (!targetElement) { |
| 412 // The only time we should get here is when the use element has not been |
| 413 // given a resource to target. |
| 414 ASSERT(m_resourceId.isEmpty()); |
| 415 return; |
| 416 } |
| 412 | 417 |
| 413 // Do not build the shadow/instance tree for <use> elements living in a shad
ow tree. | 418 // Do not build the shadow/instance tree for <use> elements living in a shad
ow tree. |
| 414 // The will be expanded soon anyway - see expandUseElementsInShadowTree(). | 419 // The will be expanded soon anyway - see expandUseElementsInShadowTree(). |
| 415 Node* parent = parentNode(); | 420 Node* parent = parentNode(); |
| 416 while (parent) { | 421 while (parent) { |
| 417 if (parent->isShadowNode()) | 422 if (parent->isShadowNode()) |
| 418 return; | 423 return; |
| 419 | 424 |
| 420 parent = parent->parentNode(); | 425 parent = parent->parentNode(); |
| 421 } | 426 } |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 if (element->hasTagName(SVGNames::useTag)) { | 708 if (element->hasTagName(SVGNames::useTag)) { |
| 704 SVGUseElement* use = static_cast<SVGUseElement*>(element); | 709 SVGUseElement* use = static_cast<SVGUseElement*>(element); |
| 705 | 710 |
| 706 String id = SVGURIReference::getTarget(use->href()); | 711 String id = SVGURIReference::getTarget(use->href()); |
| 707 Element* targetElement = document()->getElementById(id); | 712 Element* targetElement = document()->getElementById(id); |
| 708 SVGElement* target = 0; | 713 SVGElement* target = 0; |
| 709 if (targetElement && targetElement->isSVGElement()) | 714 if (targetElement && targetElement->isSVGElement()) |
| 710 target = static_cast<SVGElement*>(targetElement); | 715 target = static_cast<SVGElement*>(targetElement); |
| 711 | 716 |
| 712 // Don't ASSERT(target) here, it may be "pending", too. | 717 // Don't ASSERT(target) here, it may be "pending", too. |
| 713 if (target) { | 718 // Setup sub-shadow tree root node |
| 714 // Setup sub-shadow tree root node | 719 RefPtr<SVGShadowTreeContainerElement> cloneParent = new SVGShadowTreeCon
tainerElement(document()); |
| 715 RefPtr<SVGShadowTreeContainerElement> cloneParent = new SVGShadowTre
eContainerElement(document()); | |
| 716 | 720 |
| 717 // Spec: In the generated content, the 'use' will be replaced by 'g'
, where all attributes from the | 721 // Spec: In the generated content, the 'use' will be replaced by 'g', wh
ere all attributes from the |
| 718 // 'use' element except for x, y, width, height and xlink:href are t
ransferred to the generated 'g' element. | 722 // 'use' element except for x, y, width, height and xlink:href are trans
ferred to the generated 'g' element. |
| 719 transferUseAttributesToReplacedElement(use, cloneParent.get()); | 723 transferUseAttributesToReplacedElement(use, cloneParent.get()); |
| 720 | 724 |
| 721 ExceptionCode ec = 0; | 725 ExceptionCode ec = 0; |
| 722 | 726 if (target && !isDisallowedElement(target)) { |
| 723 // For instance <use> on <foreignObject> (direct case). | |
| 724 if (isDisallowedElement(target)) { | |
| 725 // We still have to setup the <use> replacment (<g>). Otherwhise | |
| 726 // associateInstancesWithShadowTreeElements() makes wrong assump
tions. | |
| 727 // Replace <use> with referenced content. | |
| 728 ASSERT(use->parentNode()); | |
| 729 use->parentNode()->replaceChild(cloneParent.release(), use, ec); | |
| 730 ASSERT(!ec); | |
| 731 return; | |
| 732 } | |
| 733 | |
| 734 RefPtr<Element> newChild = target->cloneElementWithChildren(); | 727 RefPtr<Element> newChild = target->cloneElementWithChildren(); |
| 735 | 728 |
| 736 // We don't walk the target tree element-by-element, and clone each
element, | 729 // We don't walk the target tree element-by-element, and clone each
element, |
| 737 // but instead use cloneElementWithChildren(). This is an optimizati
on for the common | 730 // but instead use cloneElementWithChildren(). This is an optimizati
on for the common |
| 738 // case where <use> doesn't contain disallowed elements (ie. <foreig
nObject>). | 731 // case where <use> doesn't contain disallowed elements (ie. <foreig
nObject>). |
| 739 // Though if there are disallowed elements in the subtree, we have t
o remove them. | 732 // Though if there are disallowed elements in the subtree, we have t
o remove them. |
| 740 // For instance: <use> on <g> containing <foreignObject> (indirect c
ase). | 733 // For instance: <use> on <g> containing <foreignObject> (indirect c
ase). |
| 741 if (subtreeContainsDisallowedElement(newChild.get())) | 734 if (subtreeContainsDisallowedElement(newChild.get())) |
| 742 removeDisallowedElementsFromSubtree(newChild.get()); | 735 removeDisallowedElementsFromSubtree(newChild.get()); |
| 743 | 736 |
| 744 SVGElement* newChildPtr = 0; | 737 SVGElement* newChildPtr = 0; |
| 745 if (newChild->isSVGElement()) | 738 if (newChild->isSVGElement()) |
| 746 newChildPtr = static_cast<SVGElement*>(newChild.get()); | 739 newChildPtr = static_cast<SVGElement*>(newChild.get()); |
| 747 ASSERT(newChildPtr); | 740 ASSERT(newChildPtr); |
| 748 | 741 |
| 749 cloneParent->appendChild(newChild.release(), ec); | 742 cloneParent->appendChild(newChild.release(), ec); |
| 750 ASSERT(!ec); | 743 ASSERT(!ec); |
| 744 } |
| 751 | 745 |
| 752 // Replace <use> with referenced content. | 746 // Replace <use> with referenced content. |
| 753 ASSERT(use->parentNode()); | 747 ASSERT(use->parentNode()); |
| 754 use->parentNode()->replaceChild(cloneParent.release(), use, ec); | 748 use->parentNode()->replaceChild(cloneParent.release(), use, ec); |
| 755 ASSERT(!ec); | 749 ASSERT(!ec); |
| 756 | 750 |
| 757 // Immediately stop here, and restart expanding. | 751 // Immediately stop here, and restart expanding. |
| 758 expandUseElementsInShadowTree(shadowRoot, shadowRoot); | 752 expandUseElementsInShadowTree(shadowRoot, shadowRoot); |
| 759 return; | 753 return; |
| 760 } | |
| 761 } | 754 } |
| 762 | 755 |
| 763 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextS
ibling()) | 756 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextS
ibling()) |
| 764 expandUseElementsInShadowTree(shadowRoot, child.get()); | 757 expandUseElementsInShadowTree(shadowRoot, child.get()); |
| 765 } | 758 } |
| 766 | 759 |
| 767 void SVGUseElement::expandSymbolElementsInShadowTree(SVGShadowTreeRootElement* s
hadowRoot, Node* element) | 760 void SVGUseElement::expandSymbolElementsInShadowTree(SVGShadowTreeRootElement* s
hadowRoot, Node* element) |
| 768 { | 761 { |
| 769 if (element->hasTagName(SVGNames::symbolTag)) { | 762 if (element->hasTagName(SVGNames::symbolTag)) { |
| 770 // Spec: The referenced 'symbol' and its contents are deep-cloned into t
he generated tree, | 763 // Spec: The referenced 'symbol' and its contents are deep-cloned into t
he generated tree, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 } | 934 } |
| 942 | 935 |
| 943 bool SVGUseElement::hasRelativeValues() const | 936 bool SVGUseElement::hasRelativeValues() const |
| 944 { | 937 { |
| 945 return x().isRelative() || y().isRelative() || width().isRelative() || heigh
t().isRelative(); | 938 return x().isRelative() || y().isRelative() || width().isRelative() || heigh
t().isRelative(); |
| 946 } | 939 } |
| 947 | 940 |
| 948 } | 941 } |
| 949 | 942 |
| 950 #endif // ENABLE(SVG) | 943 #endif // ENABLE(SVG) |
| OLD | NEW |