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 |