void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) { if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) { SVGElement::InvalidationGuard invalidationGuard(this); if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr) { invalidateSVGPresentationAttributeStyle(); setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::fromAttribute(attrName)); } updateRelativeLengthsInformation(); if (m_targetElementInstance) { ASSERT(m_targetElementInstance->correspondingElement()); transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_targetElementInstance->correspondingElement()); } LayoutObject* object = this->layoutObject(); if (object) markForLayoutAndParentResourceInvalidation(object); return; } if (SVGURIReference::isKnownAttribute(attrName)) { SVGElement::InvalidationGuard invalidationGuard(this); if (isStructurallyExternal()) { KURL url = document().completeURL(hrefString()); const KURL& existingURL = m_resource ? m_resource->url() : KURL(); if (url.hasFragmentIdentifier() && !equalIgnoringFragmentIdentifier(url, existingURL)) { FetchRequest request(ResourceRequest(url), localName()); setDocumentResource(DocumentResource::fetchSVGDocument(request, document().fetcher())); } } else { setDocumentResource(nullptr); } invalidateShadowTree(); return; } SVGGraphicsElement::svgAttributeChanged(attrName); }
void SVGUseElement::notifyFinished(Resource* resource) { if (!inDocument()) return; invalidateShadowTree(); if (resource->errorOccurred()) { dispatchEvent(Event::create(EventTypeNames::error)); } else if (!resource->wasCanceled()) { if (m_haveFiredLoadEvent) return; if (!isStructurallyExternal()) return; ASSERT(!m_haveFiredLoadEvent); m_haveFiredLoadEvent = true; svgUseLoadEventSender().dispatchEventSoon(this); } }
bool SVGUseElement::buildShadowTree(SVGElement* target, SVGElement* targetInstance, bool foundUse) { ASSERT(target); ASSERT(targetInstance); // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree. if (isSVGUseElement(*target)) { // We only need to track first degree <use> dependencies. Indirect references are handled // as the invalidation bubbles up the dependency chain. if (!foundUse && !isStructurallyExternal()) { addReferenceTo(target); foundUse = true; } } else if (isDisallowedElement(target)) { return false; } targetInstance->setCorrespondingElement(target); if (EventTargetData* data = target->eventTargetData()) data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(targetInstance); for (RefPtrWillBeRawPtr<Node> child = target->firstChild(); child; child = child->nextSibling()) { // Skip any disallowed element. if (isDisallowedElement(child.get())) continue; RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false); targetInstance->appendChild(newChild.get()); if (newChild->isSVGElement()) { // Enter recursion, appending new instance tree nodes to the "instance" object. if (!buildShadowTree(toSVGElement(child), toSVGElement(newChild), foundUse)) return false; } } return true; }
void SVGUseElement::dispatchPendingEvent(SVGUseEventSender* eventSender) { ASSERT_UNUSED(eventSender, eventSender == &svgUseLoadEventSender()); ASSERT(isStructurallyExternal() && m_haveFiredLoadEvent); dispatchEvent(Event::create(EventTypeNames::load)); }
TreeScope* SVGUseElement::referencedScope() const { if (isStructurallyExternal()) return externalDocument(); return &treeScope(); }