bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, SVGElement*& newTarget) { ASSERT(referencedDocument()); Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), *referencedDocument()); newTarget = 0; if (targetElement && targetElement->isSVGElement()) newTarget = toSVGElement(targetElement); if (!newTarget) return false; // Shortcut for self-references if (newTarget == this) return true; AtomicString targetId = newTarget->getIdAttribute(); SVGElementInstance* instance = targetInstance->parentNode(); while (instance) { SVGElement* element = instance->correspondingElement(); if (element->hasID() && element->getIdAttribute() == targetId && &element->document() == &newTarget->document()) return true; instance = instance->parentNode(); } return false; }
bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, SVGElement*& newTarget) { String id = SVGURIReference::getTarget(use->href()); Element* targetElement = document()->getElementById(id); newTarget = 0; if (targetElement && targetElement->isSVGElement()) newTarget = static_cast<SVGElement*>(targetElement); if (!newTarget) return false; // Shortcut for self-references if (newTarget == this) return true; SVGElementInstance* instance = targetInstance->parentNode(); while (instance) { SVGElement* element = instance->correspondingElement(); // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution. if (element->hasID() && element->idForStyleResolution() == id) return true; instance = instance->parentNode(); } return false; }
JSValue* JSSVGElementInstance::getValueProperty(ExecState* exec, int token) const { switch (token) { case CorrespondingElementAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->correspondingElement())); } case CorrespondingUseElementAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->correspondingUseElement())); } case ParentNodeAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->parentNode())); } case ChildNodesAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->childNodes())); } case FirstChildAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->firstChild())); } case LastChildAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->lastChild())); } case PreviousSiblingAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->previousSibling())); } case NextSiblingAttrNum: { SVGElementInstance* imp = static_cast<SVGElementInstance*>(impl()); return toJS(exec, WTF::getPtr(imp->nextSibling())); } } return 0; }
void SVGUseElement::handleDeepUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, bool& foundProblem) { String id = SVGURIReference::getTarget(use->href()); Element* targetElement = document()->getElementById(id); SVGElement* target = 0; if (targetElement && targetElement->isSVGElement()) target = static_cast<SVGElement*>(targetElement); if (!target) return; // Cycle detection first! foundProblem = (target == this); // Shortcut for self-references if (foundProblem) return; SVGElementInstance* instance = targetInstance->parentNode(); while (instance) { SVGElement* element = instance->correspondingElement(); if (element->getIDAttribute() == id) { foundProblem = true; return; } instance = instance->parentNode(); } // Create an instance object, even if we're dealing with a cycle RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, target); SVGElementInstance* newInstancePtr = newInstance.get(); targetInstance->appendChild(newInstance.release()); // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children buildInstanceTree(target, newInstancePtr, foundProblem); }