void SVGUseElement::expandSymbolElementsInShadowTree(SVGElement* element) { ASSERT(element); if (isSVGSymbolElement(*element)) { // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree, // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will // always have explicit values for attributes width and height. If attributes width and/or // height are provided on the 'use' element, then these attributes will be transferred to // the generated 'svg'. If attributes width and/or height are not specified, the generated // 'svg' element will use values of 100% for these attributes. ASSERT(referencedScope()); RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(referencedScope()->document()); // Transfer all data (attributes, etc.) from <symbol> to the new <svg> element. svgElement->cloneDataFromElement(*element); svgElement->setCorrespondingElement(element->correspondingElement()); // Move already cloned elements to the new <svg> element for (RefPtrWillBeRawPtr<Node> child = element->firstChild(); child; ) { RefPtrWillBeRawPtr<Node> nextChild = child->nextSibling(); svgElement->appendChild(child); child = nextChild.release(); } // We don't walk the target tree element-by-element, and clone each element, // but instead use cloneNode(deep=true). This is an optimization for the common // case where <use> doesn't contain disallowed elements (ie. <foreignObject>). // Though if there are disallowed elements in the subtree, we have to remove them. // For instance: <use> on <g> containing <foreignObject> (indirect case). if (subtreeContainsDisallowedElement(svgElement.get())) removeDisallowedElementsFromSubtree(*svgElement); RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); // Replace <symbol> with <svg>. ASSERT(element->parentNode()); element->parentNode()->replaceChild(svgElement.release(), element); // Expand the siblings because the *element* is replaced and we will // lose the sibling chain when we are back from recursion. element = replacingElement.get(); for (RefPtrWillBeRawPtr<SVGElement> sibling = Traversal<SVGElement>::nextSibling(*element); sibling; sibling = Traversal<SVGElement>::nextSibling(*sibling)) expandSymbolElementsInShadowTree(sibling.get()); } for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChild(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) expandSymbolElementsInShadowTree(child.get()); }