00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "wtf/Platform.h"
00025
00026
00027
00028
00029
00030
00031
00032 #if ENABLE(SVG)
00033 #include "SVGUseElement.h"
00034
00035 #include "CSSStyleSelector.h"
00036
00037 #include "Document.h"
00038
00039
00040 #include "RenderSVGTransformableContainer.h"
00041 #include "SVGElementInstance.h"
00042 #include "SVGElementInstanceList.h"
00043 #include "SVGGElement.h"
00044 #include "SVGLength.h"
00045 #include "SVGNames.h"
00046 #include "SVGPreserveAspectRatio.h"
00047
00048 #include "SVGSVGElement.h"
00049 #include "SVGSymbolElement.h"
00050 #include "XLinkNames.h"
00051
00052 #include <wtf/OwnPtr.h>
00053
00054 namespace WebCore {
00055
00056 SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document* doc)
00057 : SVGStyledTransformableElement(tagName, doc)
00058 , SVGTests()
00059 , SVGLangSpace()
00060 , SVGExternalResourcesRequired()
00061 , SVGURIReference()
00062 , m_x(this, LengthModeWidth)
00063 , m_y(this, LengthModeHeight)
00064 , m_width(this, LengthModeWidth)
00065 , m_height(this, LengthModeHeight)
00066 {
00067 }
00068
00069 SVGUseElement::~SVGUseElement()
00070 {
00071 }
00072
00073 ANIMATED_PROPERTY_DEFINITIONS(SVGUseElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
00074 ANIMATED_PROPERTY_DEFINITIONS(SVGUseElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
00075 ANIMATED_PROPERTY_DEFINITIONS(SVGUseElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
00076 ANIMATED_PROPERTY_DEFINITIONS(SVGUseElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
00077
00078 SVGElementInstance* SVGUseElement::instanceRoot() const
00079 {
00080 return m_targetElementInstance.get();
00081 }
00082
00083 SVGElementInstance* SVGUseElement::animatedInstanceRoot() const
00084 {
00085
00086 return 0;
00087 }
00088
00089 void SVGUseElement::parseMappedAttribute(MappedAttribute* attr)
00090 {
00091 if (attr->name() == SVGNames::xAttr)
00092 setXBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00093 else if (attr->name() == SVGNames::yAttr)
00094 setYBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00095 else if (attr->name() == SVGNames::widthAttr) {
00096 setWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00097 if (width().value() < 0.0)
00098 document()->accessSVGExtensions()->reportError("A negative value for use attribute <width> is not allowed");
00099 } else if (attr->name() == SVGNames::heightAttr) {
00100 setHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00101 if (height().value() < 0.0)
00102 document()->accessSVGExtensions()->reportError("A negative value for use attribute <height> is not allowed");
00103 } else {
00104 if (SVGTests::parseMappedAttribute(attr))
00105 return;
00106 if (SVGLangSpace::parseMappedAttribute(attr))
00107 return;
00108 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
00109 return;
00110 if (SVGURIReference::parseMappedAttribute(attr))
00111 return;
00112 SVGStyledTransformableElement::parseMappedAttribute(attr);
00113 }
00114 }
00115
00116 void SVGUseElement::insertedIntoDocument()
00117 {
00118 SVGElement::insertedIntoDocument();
00119 buildPendingResource();
00120 }
00121
00122 void SVGUseElement::removedFromDocument()
00123 {
00124 m_targetElementInstance = 0;
00125 m_shadowTreeRootElement = 0;
00126 SVGElement::removedFromDocument();
00127 }
00128
00129 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
00130 {
00131 SVGStyledTransformableElement::svgAttributeChanged(attrName);
00132
00133 if (!attached())
00134 return;
00135
00136 if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
00137 attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||
00138 SVGTests::isKnownAttribute(attrName) ||
00139 SVGLangSpace::isKnownAttribute(attrName) ||
00140 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
00141 SVGURIReference::isKnownAttribute(attrName) ||
00142 SVGStyledTransformableElement::isKnownAttribute(attrName)) {
00143
00144
00145 buildPendingResource();
00146
00147 if (m_shadowTreeRootElement)
00148 m_shadowTreeRootElement->setChanged();
00149 }
00150 }
00151
00152 void SVGUseElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
00153 {
00154 SVGElement::childrenChanged();
00155
00156 if (!attached())
00157 return;
00158
00159 buildPendingResource();
00160
00161 if (m_shadowTreeRootElement)
00162 m_shadowTreeRootElement->setChanged();
00163 }
00164
00165 void SVGUseElement::recalcStyle(StyleChange change)
00166 {
00167 SVGStyledElement::recalcStyle(change);
00168
00169
00170
00171 if (!m_shadowTreeRootElement || !m_shadowTreeRootElement->attached())
00172 return;
00173
00174
00175
00176
00177 if (change >= Inherit || m_shadowTreeRootElement->changed()) {
00178 RenderStyle* newStyle = document()->styleSelector()->styleForElement(m_shadowTreeRootElement.get());
00179 StyleChange ch = m_shadowTreeRootElement->diff((m_shadowTreeRootElement->renderer() ? m_shadowTreeRootElement->renderer()->style() : 0), newStyle);
00180 if (ch == Detach) {
00181 ASSERT(m_shadowTreeRootElement->attached());
00182 m_shadowTreeRootElement->detach();
00183 attachShadowTree();
00184
00185
00186 m_shadowTreeRootElement->setChanged();
00187 m_shadowTreeRootElement->setHasChangedChild(false);
00188
00189 return;
00190 }
00191
00192
00193 }
00194
00195
00196 m_shadowTreeRootElement->recalcStyle(change);
00197 }
00198
00199 #ifdef DUMP_INSTANCE_TREE
00200 void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance)
00201 {
00202 SVGElement* element = targetInstance->correspondingElement();
00203 ASSERT(element);
00204
00205 String elementId = element->getIDAttribute();
00206 String elementNodeName = element->nodeName();
00207 String parentNodeName = element->parentNode() ? element->parentNode()->nodeName() : "null";
00208 String firstChildNodeName = element->firstChild() ? element->firstChild()->nodeName() : "null";
00209
00210 for (unsigned int i = 0; i < depth; ++i)
00211 text += " ";
00212
00213 text += String::format("SVGElementInstance (parentNode=%s, firstChild=%s, correspondingElement=%s, id=%s)\n",
00214 parentNodeName.latin1().data(), firstChildNodeName.latin1().data(), elementNodeName.latin1().data(), elementId.latin1().data());
00215
00216 depth++;
00217
00218 for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
00219 dumpInstanceTree(depth, text, instance);
00220
00221 depth--;
00222 }
00223 #endif
00224
00225 static bool isDisallowedElement(Node* element)
00226 {
00227 #if ENABLE(SVG_FOREIGN_OBJECT)
00228
00229 if (element->hasTagName(SVGNames::foreignObjectTag))
00230 return true;
00231 #endif
00232 #if ENABLE(SVG_ANIMATION)
00233 if (SVGSMILElement::isSMILElement(element))
00234 return true;
00235 #endif
00236
00237 return false;
00238 }
00239
00240 static bool subtreeContainsDisallowedElement(Node* start)
00241 {
00242 if (isDisallowedElement(start))
00243 return true;
00244
00245 for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {
00246 if (subtreeContainsDisallowedElement(cur))
00247 return true;
00248 }
00249
00250 return false;
00251 }
00252
00253 void SVGUseElement::buildPendingResource()
00254 {
00255 String id = SVGURIReference::getTarget(href());
00256 Element* targetElement = document()->getElementById(id);
00257
00258 if (!targetElement) {
00259
00260
00261 document()->accessSVGExtensions()->addPendingResource(id, this);
00262 return;
00263 }
00264
00265
00266
00267 Node* parent = parentNode();
00268 while (parent) {
00269 if (parent->isShadowNode())
00270 return;
00271
00272 parent = parent->parentNode();
00273 }
00274
00275 SVGElement* target = 0;
00276 if (targetElement && targetElement->isSVGElement())
00277 target = static_cast<SVGElement*>(targetElement);
00278
00279
00280
00281 if (!target || target == this) {
00282 m_targetElementInstance = 0;
00283 m_shadowTreeRootElement = 0;
00284 return;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 m_targetElementInstance = new SVGElementInstance(this, target);
00298
00299
00300 bool foundProblem = false;
00301 buildInstanceTree(target, m_targetElementInstance.get(), foundProblem);
00302
00303
00304
00305 if (foundProblem) {
00306 m_targetElementInstance = 0;
00307 m_shadowTreeRootElement = 0;
00308 return;
00309 }
00310
00311
00312 ASSERT(m_targetElementInstance);
00313 ASSERT(m_targetElementInstance->correspondingUseElement() == this);
00314
00315
00316 m_shadowTreeRootElement = new SVGGElement(SVGNames::gTag, document());
00317 m_shadowTreeRootElement->setInDocument();
00318 m_shadowTreeRootElement->setShadowParentNode(this);
00319
00320
00321
00322
00323 if (x().value() != 0.0 || y().value() != 0.0) {
00324 String transformString = String::format("translate(%f, %f)", x().value(), y().value());
00325 m_shadowTreeRootElement->setAttribute(SVGNames::transformAttr, transformString);
00326 }
00327
00328
00329
00330 buildShadowTree(target, m_targetElementInstance.get());
00331
00332 #if ENABLE(SVG) && ENABLE(SVG_USE)
00333
00334
00335 expandUseElementsInShadowTree(m_shadowTreeRootElement.get());
00336
00337
00338
00339 expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());
00340
00341 #endif
00342
00343
00344
00345 associateInstancesWithShadowTreeElements(m_shadowTreeRootElement->firstChild(), m_targetElementInstance.get());
00346
00347
00348 #ifdef DUMP_INSTANCE_TREE
00349 String text;
00350 unsigned int depth = 0;
00351
00352 dumpInstanceTree(depth, text, m_targetElementInstance.get());
00353 fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());
00354 #endif
00355
00356
00357 #ifdef DUMP_SHADOW_TREE
00358 ExceptionCode ec = 0;
00359
00360 PassRefPtr<XMLSerializer> serializer = XMLSerializer::create();
00361
00362 String markup = serializer->serializeToString(m_shadowTreeRootElement.get(), ec);
00363 ASSERT(ec == 0);
00364
00365 fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
00366 #endif
00367
00368
00369
00370 attachShadowTree();
00371 }
00372
00373 RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*)
00374 {
00375 return new (arena) RenderSVGTransformableContainer(this);
00376 }
00377
00378 void SVGUseElement::attach()
00379 {
00380 SVGStyledTransformableElement::attach();
00381
00382
00383 attachShadowTree();
00384 }
00385
00386 void SVGUseElement::detach()
00387 {
00388 SVGStyledTransformableElement::detach();
00389
00390 if (m_shadowTreeRootElement)
00391 m_shadowTreeRootElement->detach();
00392 }
00393
00394 static bool isDirectReference(Node* n)
00395 {
00396 return n->hasTagName(SVGNames::pathTag) ||
00397 n->hasTagName(SVGNames::rectTag) ||
00398 n->hasTagName(SVGNames::circleTag) ||
00399 n->hasTagName(SVGNames::ellipseTag) ||
00400 n->hasTagName(SVGNames::polygonTag) ||
00401 n->hasTagName(SVGNames::polylineTag) ||
00402 n->hasTagName(SVGNames::textTag);
00403 }
00404
00405 Path SVGUseElement::toClipPath() const
00406 {
00407 if (!m_shadowTreeRootElement)
00408 const_cast<SVGUseElement*>(this)->buildPendingResource();
00409
00410 Node* n = m_shadowTreeRootElement->firstChild();
00411 if (n->isSVGElement() && static_cast<SVGElement*>(n)->isStyledTransformable()) {
00412 if (!isDirectReference(n))
00413
00414 document()->accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
00415 else
00416 return static_cast<SVGStyledTransformableElement*>(n)->toClipPath();
00417 }
00418
00419 return Path();
00420 }
00421
00422 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem)
00423 {
00424 ASSERT(target);
00425 ASSERT(targetInstance);
00426
00427
00428
00429
00430
00431
00432
00433
00434 for (Node* node = target->firstChild(); node; node = node->nextSibling()) {
00435 SVGElement* element = 0;
00436 if (node->isSVGElement())
00437 element = static_cast<SVGElement*>(node);
00438
00439
00440 if (!element || isDisallowedElement(element))
00441 continue;
00442
00443
00444 SVGElementInstance* instancePtr = new SVGElementInstance(this, element);
00445
00446 RefPtr<SVGElementInstance> instance = instancePtr;
00447 targetInstance->appendChild(instance.release());
00448
00449
00450 if (element->hasChildNodes())
00451 buildInstanceTree(element, instancePtr, foundProblem);
00452
00453
00454
00455 if (element->hasTagName(SVGNames::useTag))
00456 handleDeepUseReferencing(element, instancePtr, foundProblem);
00457 }
00458
00459
00460
00461 if (target->hasTagName(SVGNames::useTag))
00462 handleDeepUseReferencing(target, targetInstance, foundProblem);
00463 }
00464
00465 void SVGUseElement::handleDeepUseReferencing(SVGElement* use, SVGElementInstance* targetInstance, bool& foundProblem)
00466 {
00467 String id = SVGURIReference::getTarget(use->href());
00468 Element* targetElement = document()->getElementById(id);
00469 SVGElement* target = 0;
00470 if (targetElement && targetElement->isSVGElement())
00471 target = static_cast<SVGElement*>(targetElement);
00472
00473 if (!target)
00474 return;
00475
00476
00477 foundProblem = (target == this);
00478
00479
00480 if (foundProblem)
00481 return;
00482
00483 SVGElementInstance* instance = targetInstance->parentNode();
00484 while (instance) {
00485 SVGElement* element = instance->correspondingElement();
00486
00487 if (element->getIDAttribute() == id) {
00488 foundProblem = true;
00489 return;
00490 }
00491
00492 instance = instance->parentNode();
00493 }
00494
00495
00496 SVGElementInstance* newInstance = new SVGElementInstance(this, target);
00497 targetInstance->appendChild(newInstance);
00498
00499
00500 buildInstanceTree(target, newInstance, foundProblem);
00501 }
00502
00503 void SVGUseElement::alterShadowTreeForSVGTag(SVGElement* target)
00504 {
00505 String widthString = String::number(width().value());
00506 String heightString = String::number(height().value());
00507
00508 if (hasAttribute(SVGNames::widthAttr))
00509 target->setAttribute(SVGNames::widthAttr, widthString);
00510
00511 if (hasAttribute(SVGNames::heightAttr))
00512 target->setAttribute(SVGNames::heightAttr, heightString);
00513 }
00514
00515 void SVGUseElement::removeDisallowedElementsFromSubtree(Node* subtree)
00516 {
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 }
00531
00532 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance)
00533 {
00534
00535 if (isDisallowedElement(target))
00536 return;
00537
00538 PassRefPtr<NodeImpl> newChild = targetInstance->correspondingElement()->cloneNode(true);
00539
00540
00541
00542
00543
00544
00545 if (subtreeContainsDisallowedElement(newChild.get()))
00546 removeDisallowedElementsFromSubtree(newChild.get());
00547
00548 SVGElement* newChildPtr = 0;
00549 if (newChild->isSVGElement())
00550 newChildPtr = static_cast<SVGElement*>(newChild.get());
00551 ASSERT(newChildPtr);
00552
00553 int ec = 0;
00554 m_shadowTreeRootElement->appendChild(newChild.releaseRef(), ec);
00555 ASSERT(ec == 0);
00556
00557
00558 if (target->hasTagName(SVGNames::svgTag))
00559 alterShadowTreeForSVGTag(newChildPtr);
00560 }
00561
00562 #if ENABLE(SVG) && ENABLE(SVG_USE)
00563 void SVGUseElement::expandUseElementsInShadowTree(Node* element)
00564 {
00565
00566
00567
00568
00569
00570
00571
00572 if (element->hasTagName(SVGNames::useTag)) {
00573 SVGUseElement* use = static_cast<SVGUseElement*>(element);
00574
00575 String id = SVGURIReference::getTarget(use->href());
00576 Element* targetElement = document()->getElementById(id);
00577 SVGElement* target = 0;
00578 if (targetElement && targetElement->isSVGElement())
00579 target = static_cast<SVGElement*>(targetElement);
00580
00581
00582 if (target) {
00583
00584 RefPtr<SVGElement> cloneParent = new SVGGElement(SVGNames::gTag, document());
00585
00586
00587
00588 transferUseAttributesToReplacedElement(use, cloneParent.get());
00589
00590
00591
00592
00593 if (use->x().value() != 0.0 || use->y().value() != 0.0) {
00594 if (!cloneParent->hasAttribute(SVGNames::transformAttr)) {
00595 String transformString = String::format("translate(%f, %f)", use->x().value(), use->y().value());
00596 cloneParent->setAttribute(SVGNames::transformAttr, transformString);
00597 } else {
00598 String transformString = String::format(" translate(%f, %f)", use->x().value(), use->y().value());
00599 const AtomicString& transformAttribute = cloneParent->getAttribute(SVGNames::transformAttr);
00600 cloneParent->setAttribute(SVGNames::transformAttr, transformAttribute + transformString);
00601 }
00602 }
00603
00604 ExceptionCode ec = 0;
00605
00606
00607 if (isDisallowedElement(target)) {
00608
00609
00610
00611 ASSERT(use->parentNode());
00612 use->parentNode()->replaceChild(cloneParent.release(), use, ec);
00613 ASSERT(ec == 0);
00614 return;
00615 }
00616
00617 RefPtr<Node> newChild = target->cloneNode(true);
00618
00619
00620
00621
00622
00623
00624 if (subtreeContainsDisallowedElement(newChild.get()))
00625 removeDisallowedElementsFromSubtree(newChild.get());
00626
00627 SVGElement* newChildPtr = 0;
00628 if (newChild->isSVGElement())
00629 newChildPtr = static_cast<SVGElement*>(newChild.get());
00630 ASSERT(newChildPtr);
00631
00632 cloneParent->appendChild(newChild.release(), ec);
00633 ASSERT(ec == 0);
00634
00635
00636 ASSERT(use->parentNode());
00637 use->parentNode()->replaceChild(cloneParent.release(), use, ec);
00638 ASSERT(ec == 0);
00639
00640
00641 if (target->hasTagName(SVGNames::svgTag))
00642 alterShadowTreeForSVGTag(newChildPtr);
00643
00644
00645 expandUseElementsInShadowTree(m_shadowTreeRootElement.get());
00646 return;
00647 }
00648 }
00649
00650 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
00651 expandUseElementsInShadowTree(child.get());
00652 }
00653
00654 void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
00655 {
00656 if (element->hasTagName(SVGNames::symbolTag)) {
00657
00658
00659
00660
00661
00662
00663 RefPtr<SVGSVGElement> svgElement = new SVGSVGElement(SVGNames::svgTag, document());
00664
00665
00666 svgElement->attributes()->setAttributes(*element->attributes());
00667
00668
00669 String widthString = String::number(width().value());
00670 String heightString = String::number(height().value());
00671
00672 svgElement->setAttribute(SVGNames::widthAttr, hasAttribute(SVGNames::widthAttr) ? widthString : "100%");
00673 svgElement->setAttribute(SVGNames::heightAttr, hasAttribute(SVGNames::heightAttr) ? heightString : "100%");
00674
00675 ExceptionCode ec = 0;
00676
00677
00678 for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
00679 RefPtr<Node> newChild = child->cloneNode(true);
00680 svgElement->appendChild(newChild.release(), ec);
00681 ASSERT(ec == 0);
00682 }
00683
00684
00685
00686
00687
00688
00689 if (subtreeContainsDisallowedElement(svgElement.get()))
00690 removeDisallowedElementsFromSubtree(svgElement.get());
00691
00692
00693 ASSERT(element->parentNode());
00694 element->parentNode()->replaceChild(svgElement.release(), element, ec);
00695 ASSERT(ec == 0);
00696
00697
00698 expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());
00699 return;
00700 }
00701
00702 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
00703 expandSymbolElementsInShadowTree(child.get());
00704 }
00705
00706 #endif
00707
00708 void SVGUseElement::attachShadowTree()
00709 {
00710 if (!m_shadowTreeRootElement || m_shadowTreeRootElement->attached() || !attached() || !renderer())
00711 return;
00712
00713
00714 if (renderer()->childAllowed() && childShouldCreateRenderer(m_shadowTreeRootElement.get())) {
00715 RenderStyle* style = m_shadowTreeRootElement->styleForRenderer(renderer());
00716
00717 if (m_shadowTreeRootElement->rendererIsNeeded(style)) {
00718 m_shadowTreeRootElement->setRenderer(m_shadowTreeRootElement->createRenderer(document()->renderArena(), style));
00719 if (RenderObject* shadowRenderer = m_shadowTreeRootElement->renderer()) {
00720 shadowRenderer->setStyle(style);
00721 renderer()->addChild(shadowRenderer, m_shadowTreeRootElement->nextRenderer());
00722 m_shadowTreeRootElement->setAttached();
00723 }
00724 }
00725
00726
00727
00728
00729 for (Node* child = m_shadowTreeRootElement->firstChild(); child; child = child->nextSibling())
00730 child->attach();
00731 }
00732 }
00733
00734 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
00735 {
00736 if (!target || !targetInstance)
00737 return;
00738
00739 SVGElement* originalElement = targetInstance->correspondingElement();
00740
00741 if (originalElement->hasTagName(SVGNames::useTag)) {
00742 #if ENABLE(SVG) && ENABLE(SVG_USE)
00743
00744
00745 #else
00746
00747 #endif
00748 } else if (originalElement->hasTagName(SVGNames::symbolTag)) {
00749
00750 #if ENABLE(SVG) && ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT)
00751 ASSERT(target->nodeName() == SVGNames::svgTag);
00752 #endif
00753 } else
00754 ASSERT(target->nodeName() == originalElement->nodeName());
00755
00756 SVGElement* element = 0;
00757 if (target->isSVGElement())
00758 element = static_cast<SVGElement*>(target);
00759
00760 ASSERT(!targetInstance->shadowTreeElement());
00761 targetInstance->setShadowTreeElement(element);
00762
00763 Node* node = target->firstChild();
00764 for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {
00765
00766 while (node && !node->isSVGElement())
00767 node = node->nextSibling();
00768
00769 associateInstancesWithShadowTreeElements(node, instance);
00770 node = node->nextSibling();
00771 }
00772 }
00773
00774 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const
00775 {
00776 return instanceForShadowTreeElement(element, m_targetElementInstance.get());
00777 }
00778
00779 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const
00780 {
00781 ASSERT(element);
00782 ASSERT(instance);
00783 ASSERT(instance->shadowTreeElement());
00784
00785 if (element == instance->shadowTreeElement())
00786 return instance;
00787
00788 for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {
00789 SVGElementInstance* search = instanceForShadowTreeElement(element, current);
00790 if (search)
00791 return search;
00792 }
00793
00794 return 0;
00795 }
00796
00797 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
00798 {
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 }
00822
00823 }
00824
00825 #endif // ENABLE(SVG)