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 "css/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 newStyle->ref();
00180 StyleChange ch = m_shadowTreeRootElement->diff((m_shadowTreeRootElement->renderer() ? m_shadowTreeRootElement->renderer()->style() : 0), newStyle);
00181 if (ch == Detach) {
00182 ASSERT(m_shadowTreeRootElement->attached());
00183 m_shadowTreeRootElement->detach();
00184 attachShadowTree();
00185
00186
00187 m_shadowTreeRootElement->setChanged(false);
00188 m_shadowTreeRootElement->setHasChangedChild(false);
00189 newStyle->deref();
00190 return;
00191 }
00192
00193 newStyle->deref();
00194 }
00195
00196
00197 m_shadowTreeRootElement->recalcStyle(change);
00198 }
00199
00200 #ifdef DUMP_INSTANCE_TREE
00201 void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance)
00202 {
00203 SVGElement* element = targetInstance->correspondingElement();
00204 ASSERT(element);
00205
00206 String elementId = element->getIDAttribute();
00207 String elementNodeName = element->nodeName();
00208 String parentNodeName = element->parentNode() ? element->parentNode()->nodeName() : "null";
00209 String firstChildNodeName = element->firstChild() ? element->firstChild()->nodeName() : "null";
00210
00211 for (unsigned int i = 0; i < depth; ++i)
00212 text += " ";
00213
00214 text += String::format("SVGElementInstance (parentNode=%s, firstChild=%s, correspondingElement=%s, id=%s)\n",
00215 parentNodeName.latin1().data(), firstChildNodeName.latin1().data(), elementNodeName.latin1().data(), elementId.latin1().data());
00216
00217 depth++;
00218
00219 for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
00220 dumpInstanceTree(depth, text, instance);
00221
00222 depth--;
00223 }
00224 #endif
00225
00226 static bool isDisallowedElement(Node* element)
00227 {
00228 #if ENABLE(SVG_FOREIGN_OBJECT)
00229
00230 if (element->hasTagName(SVGNames::foreignObjectTag))
00231 return true;
00232 #endif
00233 #if ENABLE(SVG_ANIMATION)
00234 if (SVGSMILElement::isSMILElement(element))
00235 return true;
00236 #endif
00237
00238 return false;
00239 }
00240
00241 static bool subtreeContainsDisallowedElement(Node* start)
00242 {
00243 if (isDisallowedElement(start))
00244 return true;
00245
00246 for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {
00247 if (subtreeContainsDisallowedElement(cur))
00248 return true;
00249 }
00250
00251 return false;
00252 }
00253
00254 void SVGUseElement::buildPendingResource()
00255 {
00256 String id = SVGURIReference::getTarget(href());
00257 Element* targetElement = document()->getElementById(id);
00258
00259 if (!targetElement) {
00260
00261
00262 document()->accessSVGExtensions()->addPendingResource(id, this);
00263 return;
00264 }
00265
00266
00267
00268 Node* parent = parentNode();
00269 while (parent) {
00270 if (parent->isShadowNode())
00271 return;
00272
00273 parent = parent->parentNode();
00274 }
00275
00276 SVGElement* target = 0;
00277 if (targetElement && targetElement->isSVGElement())
00278 target = static_cast<SVGElement*>(targetElement);
00279
00280
00281
00282 if (!target || target == this) {
00283 m_targetElementInstance = 0;
00284 m_shadowTreeRootElement = 0;
00285 return;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 m_targetElementInstance = new SVGElementInstance(this, target);
00299
00300
00301 bool foundProblem = false;
00302 buildInstanceTree(target, m_targetElementInstance.get(), foundProblem);
00303
00304
00305
00306 if (foundProblem) {
00307 m_targetElementInstance = 0;
00308 m_shadowTreeRootElement = 0;
00309 return;
00310 }
00311
00312
00313 ASSERT(m_targetElementInstance);
00314 ASSERT(m_targetElementInstance->correspondingUseElement() == this);
00315
00316
00317 m_shadowTreeRootElement = new SVGGElement(SVGNames::gTag, document());
00318 m_shadowTreeRootElement->setInDocument();
00319 m_shadowTreeRootElement->setShadowParentNode(this);
00320
00321
00322
00323
00324 if (x().value() != 0.0 || y().value() != 0.0) {
00325 String transformString = String::format("translate(%f, %f)", x().value(), y().value());
00326 m_shadowTreeRootElement->setAttribute(SVGNames::transformAttr, transformString);
00327 }
00328
00329
00330
00331 buildShadowTree(target, m_targetElementInstance.get());
00332
00333 #if ENABLE(SVG) && ENABLE(SVG_USE)
00334
00335
00336 expandUseElementsInShadowTree(m_shadowTreeRootElement.get());
00337
00338
00339
00340 expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());
00341
00342 #endif
00343
00344
00345
00346 associateInstancesWithShadowTreeElements(m_shadowTreeRootElement->firstChild(), m_targetElementInstance.get());
00347
00348
00349 #ifdef DUMP_INSTANCE_TREE
00350 String text;
00351 unsigned int depth = 0;
00352
00353 dumpInstanceTree(depth, text, m_targetElementInstance.get());
00354 fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());
00355 #endif
00356
00357
00358 #ifdef DUMP_SHADOW_TREE
00359 ExceptionCode ec = 0;
00360
00361 PassRefPtr<XMLSerializer> serializer = XMLSerializer::create();
00362
00363 String markup = serializer->serializeToString(m_shadowTreeRootElement.get(), ec);
00364 ASSERT(ec == 0);
00365
00366 fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
00367 #endif
00368
00369
00370
00371 attachShadowTree();
00372 }
00373
00374 RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*)
00375 {
00376 return new (arena) RenderSVGTransformableContainer(this);
00377 }
00378
00379 void SVGUseElement::attach()
00380 {
00381 SVGStyledTransformableElement::attach();
00382
00383
00384 attachShadowTree();
00385 }
00386
00387 void SVGUseElement::detach()
00388 {
00389 if (m_shadowTreeRootElement)
00390 m_shadowTreeRootElement->detach();
00391
00392 SVGStyledTransformableElement::detach();
00393 }
00394
00395 static bool isDirectReference(Node* n)
00396 {
00397 return n->hasTagName(SVGNames::pathTag) ||
00398 n->hasTagName(SVGNames::rectTag) ||
00399 n->hasTagName(SVGNames::circleTag) ||
00400 n->hasTagName(SVGNames::ellipseTag) ||
00401 n->hasTagName(SVGNames::polygonTag) ||
00402 n->hasTagName(SVGNames::polylineTag) ||
00403 n->hasTagName(SVGNames::textTag);
00404 }
00405
00406 Path SVGUseElement::toClipPath() const
00407 {
00408 if (!m_shadowTreeRootElement)
00409 const_cast<SVGUseElement*>(this)->buildPendingResource();
00410
00411 Node* n = m_shadowTreeRootElement->firstChild();
00412 if (n->isSVGElement() && static_cast<SVGElement*>(n)->isStyledTransformable()) {
00413 if (!isDirectReference(n))
00414
00415 document()->accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
00416 else
00417 return static_cast<SVGStyledTransformableElement*>(n)->toClipPath();
00418 }
00419
00420 return Path();
00421 }
00422
00423 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem)
00424 {
00425 ASSERT(target);
00426 ASSERT(targetInstance);
00427
00428
00429
00430
00431
00432
00433
00434
00435 for (Node* node = target->firstChild(); node; node = node->nextSibling()) {
00436 SVGElement* element = 0;
00437 if (node->isSVGElement())
00438 element = static_cast<SVGElement*>(node);
00439
00440
00441 if (!element || isDisallowedElement(element))
00442 continue;
00443
00444
00445 SVGElementInstance* instancePtr = new SVGElementInstance(this, element);
00446
00447 RefPtr<SVGElementInstance> instance = instancePtr;
00448 targetInstance->appendChild(instance.release());
00449
00450
00451 if (element->hasChildNodes())
00452 buildInstanceTree(element, instancePtr, foundProblem);
00453
00454
00455
00456 if (element->hasTagName(SVGNames::useTag))
00457 handleDeepUseReferencing(element, instancePtr, foundProblem);
00458 }
00459
00460
00461
00462 if (target->hasTagName(SVGNames::useTag))
00463 handleDeepUseReferencing(target, targetInstance, foundProblem);
00464 }
00465
00466 void SVGUseElement::handleDeepUseReferencing(SVGElement* use, SVGElementInstance* targetInstance, bool& foundProblem)
00467 {
00468 String id = SVGURIReference::getTarget(use->href());
00469 Element* targetElement = document()->getElementById(id);
00470 SVGElement* target = 0;
00471 if (targetElement && targetElement->isSVGElement())
00472 target = static_cast<SVGElement*>(targetElement);
00473
00474 if (!target)
00475 return;
00476
00477
00478 foundProblem = (target == this);
00479
00480
00481 if (foundProblem)
00482 return;
00483
00484 SVGElementInstance* instance = targetInstance->parentNode();
00485 while (instance) {
00486 SVGElement* element = instance->correspondingElement();
00487
00488 if (element->getIDAttribute() == id) {
00489 foundProblem = true;
00490 return;
00491 }
00492
00493 instance = instance->parentNode();
00494 }
00495
00496
00497 SVGElementInstance* newInstance = new SVGElementInstance(this, target);
00498 targetInstance->appendChild(newInstance);
00499
00500
00501 buildInstanceTree(target, newInstance, foundProblem);
00502 }
00503
00504 void SVGUseElement::alterShadowTreeForSVGTag(SVGElement* target)
00505 {
00506 String widthString = String::number(width().value());
00507 String heightString = String::number(height().value());
00508
00509 if (hasAttribute(SVGNames::widthAttr))
00510 target->setAttribute(SVGNames::widthAttr, widthString);
00511
00512 if (hasAttribute(SVGNames::heightAttr))
00513 target->setAttribute(SVGNames::heightAttr, heightString);
00514 }
00515
00516 void SVGUseElement::removeDisallowedElementsFromSubtree(Node* subtree)
00517 {
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 }
00532
00533 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance)
00534 {
00535
00536 if (isDisallowedElement(target))
00537 return;
00538
00539 PassRefPtr<NodeImpl> newChild = targetInstance->correspondingElement()->cloneNode(true);
00540
00541
00542
00543
00544
00545
00546 if (subtreeContainsDisallowedElement(newChild.get()))
00547 removeDisallowedElementsFromSubtree(newChild.get());
00548
00549 SVGElement* newChildPtr = 0;
00550 if (newChild->isSVGElement())
00551 newChildPtr = static_cast<SVGElement*>(newChild.get());
00552 ASSERT(newChildPtr);
00553
00554 int ec = 0;
00555 m_shadowTreeRootElement->appendChild(newChild.releaseRef(), ec);
00556 ASSERT(ec == 0);
00557
00558
00559 if (target->hasTagName(SVGNames::svgTag))
00560 alterShadowTreeForSVGTag(newChildPtr);
00561 }
00562
00563 #if ENABLE(SVG) && ENABLE(SVG_USE)
00564 void SVGUseElement::expandUseElementsInShadowTree(Node* element)
00565 {
00566
00567
00568
00569
00570
00571
00572
00573 if (element->hasTagName(SVGNames::useTag)) {
00574 SVGUseElement* use = static_cast<SVGUseElement*>(element);
00575
00576 String id = SVGURIReference::getTarget(use->href());
00577 Element* targetElement = document()->getElementById(id);
00578 SVGElement* target = 0;
00579 if (targetElement && targetElement->isSVGElement())
00580 target = static_cast<SVGElement*>(targetElement);
00581
00582
00583 if (target) {
00584
00585 RefPtr<SVGElement> cloneParent = new SVGGElement(SVGNames::gTag, document());
00586
00587
00588
00589 transferUseAttributesToReplacedElement(use, cloneParent.get());
00590
00591
00592
00593
00594 if (use->x().value() != 0.0 || use->y().value() != 0.0) {
00595 if (!cloneParent->hasAttribute(SVGNames::transformAttr)) {
00596 String transformString = String::format("translate(%f, %f)", use->x().value(), use->y().value());
00597 cloneParent->setAttribute(SVGNames::transformAttr, transformString);
00598 } else {
00599 String transformString = String::format(" translate(%f, %f)", use->x().value(), use->y().value());
00600 const AtomicString& transformAttribute = cloneParent->getAttribute(SVGNames::transformAttr);
00601 cloneParent->setAttribute(SVGNames::transformAttr, transformAttribute + transformString);
00602 }
00603 }
00604
00605 ExceptionCode ec = 0;
00606
00607
00608 if (isDisallowedElement(target)) {
00609
00610
00611
00612 ASSERT(use->parentNode());
00613 use->parentNode()->replaceChild(cloneParent.release(), use, ec);
00614 ASSERT(ec == 0);
00615 return;
00616 }
00617
00618 RefPtr<Node> newChild = target->cloneNode(true);
00619
00620
00621
00622
00623
00624
00625 if (subtreeContainsDisallowedElement(newChild.get()))
00626 removeDisallowedElementsFromSubtree(newChild.get());
00627
00628 SVGElement* newChildPtr = 0;
00629 if (newChild->isSVGElement())
00630 newChildPtr = static_cast<SVGElement*>(newChild.get());
00631 ASSERT(newChildPtr);
00632
00633 cloneParent->appendChild(newChild.release(), ec);
00634 ASSERT(ec == 0);
00635
00636
00637 ASSERT(use->parentNode());
00638 use->parentNode()->replaceChild(cloneParent.release(), use, ec);
00639 ASSERT(ec == 0);
00640
00641
00642 if (target->hasTagName(SVGNames::svgTag))
00643 alterShadowTreeForSVGTag(newChildPtr);
00644
00645
00646 expandUseElementsInShadowTree(m_shadowTreeRootElement.get());
00647 return;
00648 }
00649 }
00650
00651 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
00652 expandUseElementsInShadowTree(child.get());
00653 }
00654
00655 void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
00656 {
00657 if (element->hasTagName(SVGNames::symbolTag)) {
00658
00659
00660
00661
00662
00663
00664 RefPtr<SVGSVGElement> svgElement = new SVGSVGElement(SVGNames::svgTag, document());
00665
00666
00667 svgElement->attributes()->setAttributes(*element->attributes());
00668
00669
00670 String widthString = String::number(width().value());
00671 String heightString = String::number(height().value());
00672
00673 svgElement->setAttribute(SVGNames::widthAttr, hasAttribute(SVGNames::widthAttr) ? widthString : "100%");
00674 svgElement->setAttribute(SVGNames::heightAttr, hasAttribute(SVGNames::heightAttr) ? heightString : "100%");
00675
00676 ExceptionCode ec = 0;
00677
00678
00679 for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
00680 RefPtr<Node> newChild = child->cloneNode(true);
00681 svgElement->appendChild(newChild.release(), ec);
00682 ASSERT(ec == 0);
00683 }
00684
00685
00686
00687
00688
00689
00690 if (subtreeContainsDisallowedElement(svgElement.get()))
00691 removeDisallowedElementsFromSubtree(svgElement.get());
00692
00693
00694 ASSERT(element->parentNode());
00695 element->parentNode()->replaceChild(svgElement.release(), element, ec);
00696 ASSERT(ec == 0);
00697
00698
00699 expandSymbolElementsInShadowTree(m_shadowTreeRootElement.get());
00700 return;
00701 }
00702
00703 for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
00704 expandSymbolElementsInShadowTree(child.get());
00705 }
00706
00707 #endif
00708
00709 void SVGUseElement::attachShadowTree()
00710 {
00711 if (!m_shadowTreeRootElement || m_shadowTreeRootElement->attached() || !attached() || !renderer())
00712 return;
00713
00714
00715 if (renderer()->childAllowed() && childShouldCreateRenderer(m_shadowTreeRootElement.get())) {
00716 RenderStyle* style = m_shadowTreeRootElement->styleForRenderer(renderer());
00717 style->ref();
00718
00719 if (m_shadowTreeRootElement->rendererIsNeeded(style)) {
00720 m_shadowTreeRootElement->setRenderer(m_shadowTreeRootElement->createRenderer(document()->renderArena(), style));
00721 if (RenderObject* shadowRenderer = m_shadowTreeRootElement->renderer()) {
00722 shadowRenderer->setStyle(style);
00723 renderer()->addChild(shadowRenderer, m_shadowTreeRootElement->nextRenderer());
00724 m_shadowTreeRootElement->setAttached();
00725 }
00726 }
00727
00728 style->deref();
00729
00730
00731 for (Node* child = m_shadowTreeRootElement->firstChild(); child; child = child->nextSibling())
00732 child->attach();
00733 }
00734 }
00735
00736 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
00737 {
00738 if (!target || !targetInstance)
00739 return;
00740
00741 SVGElement* originalElement = targetInstance->correspondingElement();
00742
00743 if (originalElement->hasTagName(SVGNames::useTag)) {
00744 #if ENABLE(SVG) && ENABLE(SVG_USE)
00745
00746
00747 #else
00748
00749 #endif
00750 } else if (originalElement->hasTagName(SVGNames::symbolTag)) {
00751
00752 #if ENABLE(SVG) && ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT)
00753 ASSERT(target->nodeName() == SVGNames::svgTag);
00754 #endif
00755 } else
00756 ASSERT(target->nodeName() == originalElement->nodeName());
00757
00758 SVGElement* element = 0;
00759 if (target->isSVGElement())
00760 element = static_cast<SVGElement*>(target);
00761
00762 ASSERT(!targetInstance->shadowTreeElement());
00763 targetInstance->setShadowTreeElement(element);
00764
00765 Node* node = target->firstChild();
00766 for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {
00767
00768 while (node && !node->isSVGElement())
00769 node = node->nextSibling();
00770
00771 associateInstancesWithShadowTreeElements(node, instance);
00772 node = node->nextSibling();
00773 }
00774 }
00775
00776 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const
00777 {
00778 return instanceForShadowTreeElement(element, m_targetElementInstance.get());
00779 }
00780
00781 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const
00782 {
00783 ASSERT(element);
00784 ASSERT(instance);
00785 ASSERT(instance->shadowTreeElement());
00786
00787 if (element == instance->shadowTreeElement())
00788 return instance;
00789
00790 for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {
00791 SVGElementInstance* search = instanceForShadowTreeElement(element, current);
00792 if (search)
00793 return search;
00794 }
00795
00796 return 0;
00797 }
00798
00799 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
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 }
00826
00827 #endif // ENABLE(SVG)