void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target) { ASSERT(!m_targetElementInstance); ASSERT(!m_needsShadowTreeRecreation); // <use> creates a "user agent" shadow root. Do not build the shadow/instance tree for <use> // elements living in a user agent shadow tree because they will get expanded in a second // pass -- see expandUseElementsInShadowTree(). if (inUseShadowTree()) return; // Do not allow self-referencing. // 'target' may be null, if it's a non SVG namespaced element. if (!target || target == this || isDisallowedElement(target)) return; // Set up root SVG element in shadow tree. RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren(); m_targetElementInstance = toSVGElement(newChild.get()); ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); shadowTreeRootElement->appendChild(newChild.release()); // Clone the target subtree into the shadow tree, not handling <use> and <symbol> yet. // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it! // Non-appearing <use> content is easier to debug, then half-appearing content. if (!buildShadowTree(target, m_targetElementInstance.get(), false)) { clearShadowTree(); return; } if (instanceTreeIsLoading(m_targetElementInstance.get())) return; // Assure shadow tree building was successfull ASSERT(m_targetElementInstance); ASSERT(m_targetElementInstance->correspondingUseElement() == this); ASSERT(m_targetElementInstance->correspondingElement() == target); // Expand all <use> elements in the shadow tree. // Expand means: replace the actual <use> element by what it references. if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) { clearShadowTree(); return; } // Expand all <symbol> elements in the shadow tree. // Expand means: replace the actual <symbol> element by the <svg> element. expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstChild())); m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild()); transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_targetElementInstance->correspondingElement()); ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement); // Update relative length information. updateRelativeLengthsInformation(); }
void SVGUseElement::removedFrom(ContainerNode* rootParent) { SVGGraphicsElement::removedFrom(rootParent); if (rootParent->isConnected()) { clearShadowTree(); cancelShadowTreeRecreation(); } }
void SVGUseElement::buildPendingResource() { if (inUseShadowTree()) return; clearShadowTree(); cancelShadowTreeRecreation(); if (!referencedScope() || !inDocument()) return; AtomicString id; Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id, externalDocument()); if (!target || !target->inDocument()) { // If we can't find the target of an external element, just give up. // We can't observe if the target somewhen enters the external document, nor should we do it. if (externalDocument()) return; if (id.isEmpty()) return; referencedScope()->document().accessSVGExtensions().addPendingResource(id, this); ASSERT(hasPendingResources()); return; } if (target->isSVGElement()) { buildShadowAndInstanceTree(toSVGElement(target)); invalidateDependentShadowTrees(); } ASSERT(!m_needsShadowTreeRecreation); }
SVGUseElement::~SVGUseElement() { #if !ENABLE(OILPAN) clearShadowTree(); cancelShadowTreeRecreation(); svgUseLoadEventSender().cancelEvent(this); dispose(); #endif }
SVGUseElement::~SVGUseElement() { setDocumentResource(0); #if !ENABLE(OILPAN) clearShadowTree(); cancelShadowTreeRecreation(); svgUseLoadEventSender().cancelEvent(this); #endif }