Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
      5  * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
      6  * Copyright (C) 2012 University of Szeged
      7  * Copyright (C) 2012 Renata Hodovan <reni (at) webkit.org>
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #include "config.h"
     26 
     27 #include "core/svg/SVGUseElement.h"
     28 
     29 #include "XLinkNames.h"
     30 #include "bindings/v8/ExceptionStatePlaceholder.h"
     31 #include "core/dom/Document.h"
     32 #include "core/dom/ElementTraversal.h"
     33 #include "core/events/Event.h"
     34 #include "core/dom/shadow/ElementShadow.h"
     35 #include "core/dom/shadow/ShadowRoot.h"
     36 #include "core/fetch/FetchRequest.h"
     37 #include "core/fetch/ResourceFetcher.h"
     38 #include "core/rendering/svg/RenderSVGResource.h"
     39 #include "core/rendering/svg/RenderSVGTransformableContainer.h"
     40 #include "core/svg/SVGElementInstance.h"
     41 #include "core/svg/SVGGElement.h"
     42 #include "core/svg/SVGLengthContext.h"
     43 #include "core/svg/SVGSVGElement.h"
     44 #include "core/xml/parser/XMLDocumentParser.h"
     45 
     46 // Dump SVGElementInstance object tree - useful to debug instanceRoot problems
     47 // #define DUMP_INSTANCE_TREE
     48 
     49 // Dump the deep-expanded shadow tree (where the renderers are built from)
     50 // #define DUMP_SHADOW_TREE
     51 
     52 namespace WebCore {
     53 
     54 // Animated property definitions
     55 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::xAttr, X, x)
     56 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::yAttr, Y, y)
     57 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::widthAttr, Width, width)
     58 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::heightAttr, Height, height)
     59 DEFINE_ANIMATED_STRING(SVGUseElement, XLinkNames::hrefAttr, Href, href)
     60 DEFINE_ANIMATED_BOOLEAN(SVGUseElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     61 
     62 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGUseElement)
     63     REGISTER_LOCAL_ANIMATED_PROPERTY(x)
     64     REGISTER_LOCAL_ANIMATED_PROPERTY(y)
     65     REGISTER_LOCAL_ANIMATED_PROPERTY(width)
     66     REGISTER_LOCAL_ANIMATED_PROPERTY(height)
     67     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
     68     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
     69     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
     70 END_REGISTER_ANIMATED_PROPERTIES
     71 
     72 inline SVGUseElement::SVGUseElement(Document& document, bool wasInsertedByParser)
     73     : SVGGraphicsElement(SVGNames::useTag, document)
     74     , m_x(LengthModeWidth)
     75     , m_y(LengthModeHeight)
     76     , m_width(LengthModeWidth)
     77     , m_height(LengthModeHeight)
     78     , m_wasInsertedByParser(wasInsertedByParser)
     79     , m_haveFiredLoadEvent(false)
     80     , m_needsShadowTreeRecreation(false)
     81     , m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired)
     82 {
     83     ASSERT(hasCustomStyleCallbacks());
     84     ScriptWrappable::init(this);
     85     registerAnimatedPropertiesForSVGUseElement();
     86 }
     87 
     88 PassRefPtr<SVGUseElement> SVGUseElement::create(Document& document, bool wasInsertedByParser)
     89 {
     90     // Always build a #shadow-root for SVGUseElement.
     91     RefPtr<SVGUseElement> use = adoptRef(new SVGUseElement(document, wasInsertedByParser));
     92     use->ensureUserAgentShadowRoot();
     93     return use.release();
     94 }
     95 
     96 SVGUseElement::~SVGUseElement()
     97 {
     98     setDocumentResource(0);
     99 
    100     clearResourceReferences();
    101 }
    102 
    103 SVGElementInstance* SVGUseElement::instanceRoot()
    104 {
    105     // If there is no element instance tree, force immediate SVGElementInstance tree
    106     // creation by asking the document to invoke our recalcStyle function - as we can't
    107     // wait for the lazy creation to happen if e.g. JS wants to access the instanceRoot
    108     // object right after creating the element on-the-fly
    109     if (!m_targetElementInstance)
    110         document().updateStyleIfNeeded();
    111 
    112     return m_targetElementInstance.get();
    113 }
    114 
    115 SVGElementInstance* SVGUseElement::animatedInstanceRoot() const
    116 {
    117     // FIXME: Implement me.
    118     return 0;
    119 }
    120 
    121 bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
    122 {
    123     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    124     if (supportedAttributes.isEmpty()) {
    125         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
    126         SVGURIReference::addSupportedAttributes(supportedAttributes);
    127         supportedAttributes.add(SVGNames::xAttr);
    128         supportedAttributes.add(SVGNames::yAttr);
    129         supportedAttributes.add(SVGNames::widthAttr);
    130         supportedAttributes.add(SVGNames::heightAttr);
    131     }
    132     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
    133 }
    134 
    135 void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    136 {
    137     SVGParsingError parseError = NoError;
    138 
    139     if (!isSupportedAttribute(name))
    140         SVGGraphicsElement::parseAttribute(name, value);
    141     else if (name == SVGNames::xAttr)
    142         setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
    143     else if (name == SVGNames::yAttr)
    144         setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
    145     else if (name == SVGNames::widthAttr)
    146         setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
    147     else if (name == SVGNames::heightAttr)
    148         setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
    149     else if (SVGExternalResourcesRequired::parseAttribute(name, value)
    150              || SVGURIReference::parseAttribute(name, value)) {
    151     } else
    152         ASSERT_NOT_REACHED();
    153 
    154     reportAttributeParsingError(parseError, name, value);
    155 }
    156 
    157 #if !ASSERT_DISABLED
    158 static inline bool isWellFormedDocument(Document* document)
    159 {
    160     if (document->isSVGDocument() || document->isXHTMLDocument())
    161         return static_cast<XMLDocumentParser*>(document->parser())->wellFormed();
    162     return true;
    163 }
    164 #endif
    165 
    166 Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode* rootParent)
    167 {
    168     // This functions exists to assure assumptions made in the code regarding SVGElementInstance creation/destruction are satisfied.
    169     SVGGraphicsElement::insertedInto(rootParent);
    170     if (!rootParent->inDocument())
    171         return InsertionDone;
    172     ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document()));
    173     ASSERT(!hasPendingResources() || !isWellFormedDocument(&document()));
    174     if (!m_wasInsertedByParser)
    175         buildPendingResource();
    176     SVGExternalResourcesRequired::insertedIntoDocument(this);
    177     return InsertionDone;
    178 }
    179 
    180 void SVGUseElement::removedFrom(ContainerNode* rootParent)
    181 {
    182     SVGGraphicsElement::removedFrom(rootParent);
    183     if (rootParent->inDocument())
    184         clearResourceReferences();
    185 }
    186 
    187 Document* SVGUseElement::referencedDocument() const
    188 {
    189     if (!isExternalURIReference(hrefCurrentValue(), document()))
    190         return &document();
    191     return externalDocument();
    192 }
    193 
    194 Document* SVGUseElement::externalDocument() const
    195 {
    196     if (m_resource && m_resource->isLoaded()) {
    197         // Gracefully handle error condition.
    198         if (m_resource->errorOccurred())
    199             return 0;
    200         ASSERT(m_resource->document());
    201         return m_resource->document();
    202     }
    203     return 0;
    204 }
    205 
    206 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
    207 {
    208     if (!isSupportedAttribute(attrName)) {
    209         SVGGraphicsElement::svgAttributeChanged(attrName);
    210         return;
    211     }
    212 
    213     SVGElementInstance::InvalidationGuard invalidationGuard(this);
    214 
    215     RenderObject* renderer = this->renderer();
    216     if (attrName == SVGNames::xAttr
    217         || attrName == SVGNames::yAttr
    218         || attrName == SVGNames::widthAttr
    219         || attrName == SVGNames::heightAttr) {
    220         updateRelativeLengthsInformation();
    221         if (renderer)
    222             RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    223         return;
    224     }
    225 
    226     if (SVGExternalResourcesRequired::handleAttributeChange(this, attrName))
    227         return;
    228 
    229     if (SVGURIReference::isKnownAttribute(attrName)) {
    230         bool isExternalReference = isExternalURIReference(hrefCurrentValue(), document());
    231         if (isExternalReference) {
    232             KURL url = document().completeURL(hrefCurrentValue());
    233             if (url.hasFragmentIdentifier()) {
    234                 FetchRequest request(ResourceRequest(url.string()), localName());
    235                 setDocumentResource(document().fetcher()->fetchSVGDocument(request));
    236             }
    237         } else {
    238             setDocumentResource(0);
    239         }
    240 
    241         if (!m_wasInsertedByParser)
    242             buildPendingResource();
    243 
    244         return;
    245     }
    246 
    247     if (!renderer)
    248         return;
    249 
    250     if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
    251         invalidateShadowTree();
    252         return;
    253     }
    254 
    255     ASSERT_NOT_REACHED();
    256 }
    257 
    258 void SVGUseElement::attach(const AttachContext& context)
    259 {
    260     if (m_needsShadowTreeRecreation)
    261         buildPendingResource();
    262     SVGGraphicsElement::attach(context);
    263 }
    264 
    265 void SVGUseElement::willRecalcStyle(StyleRecalcChange)
    266 {
    267     if (!m_wasInsertedByParser && m_needsShadowTreeRecreation && renderer() && needsStyleRecalc())
    268         buildPendingResource();
    269 }
    270 
    271 #ifdef DUMP_INSTANCE_TREE
    272 static void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance)
    273 {
    274     SVGElement* element = targetInstance->correspondingElement();
    275     ASSERT(element);
    276 
    277     if (element->hasTagName(SVGNames::useTag)) {
    278         if (toSVGUseElement(element)->resourceIsStillLoading())
    279             return;
    280     }
    281 
    282     SVGElement* shadowTreeElement = targetInstance->shadowTreeElement();
    283     ASSERT(shadowTreeElement);
    284 
    285     SVGUseElement* directUseElement = targetInstance->directUseElement();
    286     String directUseElementName = directUseElement ? directUseElement->nodeName() : "null";
    287 
    288     String elementId = element->getIdAttribute();
    289     String elementNodeName = element->nodeName();
    290     String shadowTreeElementNodeName = shadowTreeElement->nodeName();
    291     String parentNodeName = element->parentNode() ? element->parentNode()->nodeName() : "null";
    292     String firstChildNodeName = element->firstChild() ? element->firstChild()->nodeName() : "null";
    293 
    294     for (unsigned int i = 0; i < depth; ++i)
    295         text += "  ";
    296 
    297     text += String::format("SVGElementInstance this=%p, (parentNode=%s (%p), firstChild=%s (%p), correspondingElement=%s (%p), directUseElement=%s (%p), shadowTreeElement=%s (%p), id=%s)\n",
    298                            targetInstance, parentNodeName.latin1().data(), element->parentNode(), firstChildNodeName.latin1().data(), element->firstChild(),
    299                            elementNodeName.latin1().data(), element, directUseElementName.latin1().data(), directUseElement, shadowTreeElementNodeName.latin1().data(), shadowTreeElement, elementId.latin1().data());
    300 
    301     for (unsigned int i = 0; i < depth; ++i)
    302         text += "  ";
    303 
    304     const HashSet<SVGElementInstance*>& elementInstances = element->instancesForElement();
    305     text += "Corresponding element is associated with " + String::number(elementInstances.size()) + " instance(s):\n";
    306 
    307     const HashSet<SVGElementInstance*>::const_iterator end = elementInstances.end();
    308     for (HashSet<SVGElementInstance*>::const_iterator it = elementInstances.begin(); it != end; ++it) {
    309         for (unsigned int i = 0; i < depth; ++i)
    310             text += "  ";
    311 
    312         text += String::format(" -> SVGElementInstance this=%p, (refCount: %i, shadowTreeElement in document? %i)\n",
    313                                *it, (*it)->refCount(), (*it)->shadowTreeElement()->inDocument());
    314     }
    315 
    316     ++depth;
    317 
    318     for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
    319         dumpInstanceTree(depth, text, instance);
    320 
    321     --depth;
    322 }
    323 #endif
    324 
    325 static bool isDisallowedElement(Node* node)
    326 {
    327     // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is potentially a template object that can be re-used
    328     // (i.e., "instanced") in the SVG document via a 'use' element."
    329     // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline', 'rect', 'text'
    330     // Excluded are anything that is used by reference or that only make sense to appear once in a document.
    331     // We must also allow the shadow roots of other use elements.
    332     if (node->isShadowRoot() || node->isTextNode())
    333         return false;
    334 
    335     if (!node->isSVGElement())
    336         return true;
    337 
    338     Element* element = toElement(node);
    339 
    340     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ());
    341     if (allowedElementTags.isEmpty()) {
    342         allowedElementTags.add(SVGNames::aTag);
    343         allowedElementTags.add(SVGNames::circleTag);
    344         allowedElementTags.add(SVGNames::descTag);
    345         allowedElementTags.add(SVGNames::ellipseTag);
    346         allowedElementTags.add(SVGNames::gTag);
    347         allowedElementTags.add(SVGNames::imageTag);
    348         allowedElementTags.add(SVGNames::lineTag);
    349         allowedElementTags.add(SVGNames::metadataTag);
    350         allowedElementTags.add(SVGNames::pathTag);
    351         allowedElementTags.add(SVGNames::polygonTag);
    352         allowedElementTags.add(SVGNames::polylineTag);
    353         allowedElementTags.add(SVGNames::rectTag);
    354         allowedElementTags.add(SVGNames::svgTag);
    355         allowedElementTags.add(SVGNames::switchTag);
    356         allowedElementTags.add(SVGNames::symbolTag);
    357         allowedElementTags.add(SVGNames::textTag);
    358         allowedElementTags.add(SVGNames::textPathTag);
    359         allowedElementTags.add(SVGNames::titleTag);
    360         allowedElementTags.add(SVGNames::tspanTag);
    361         allowedElementTags.add(SVGNames::useTag);
    362     }
    363     return !allowedElementTags.contains<SVGAttributeHashTranslator>(element->tagQName());
    364 }
    365 
    366 static bool subtreeContainsDisallowedElement(Node* start)
    367 {
    368     if (isDisallowedElement(start))
    369         return true;
    370 
    371     for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {
    372         if (subtreeContainsDisallowedElement(cur))
    373             return true;
    374     }
    375 
    376     return false;
    377 }
    378 
    379 void SVGUseElement::clearResourceReferences()
    380 {
    381     // FIXME: We should try to optimize this, to at least allow partial reclones.
    382     if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot())
    383         shadowTreeRootElement->removeChildren();
    384 
    385     if (m_targetElementInstance) {
    386         m_targetElementInstance->detach();
    387         m_targetElementInstance = 0;
    388     }
    389 
    390     m_needsShadowTreeRecreation = false;
    391 
    392     document().accessSVGExtensions()->removeAllTargetReferencesForElement(this);
    393 }
    394 
    395 void SVGUseElement::buildPendingResource()
    396 {
    397     if (!referencedDocument() || isInShadowTree())
    398         return;
    399     clearResourceReferences();
    400     if (!inDocument())
    401         return;
    402 
    403     String id;
    404     Element* target = SVGURIReference::targetElementFromIRIString(hrefCurrentValue(), document(), &id, externalDocument());
    405     if (!target || !target->inDocument()) {
    406         // If we can't find the target of an external element, just give up.
    407         // We can't observe if the target somewhen enters the external document, nor should we do it.
    408         if (externalDocument())
    409             return;
    410         if (id.isEmpty())
    411             return;
    412 
    413         referencedDocument()->accessSVGExtensions()->addPendingResource(id, this);
    414         ASSERT(hasPendingResources());
    415         return;
    416     }
    417 
    418     if (target->isSVGElement()) {
    419         buildShadowAndInstanceTree(toSVGElement(target));
    420         invalidateDependentShadowTrees();
    421     }
    422 
    423     ASSERT(!m_needsShadowTreeRecreation);
    424 }
    425 
    426 void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
    427 {
    428     ASSERT(!m_targetElementInstance);
    429 
    430     // Do not build the shadow/instance tree for <use> elements living in a shadow tree.
    431     // The will be expanded soon anyway - see expandUseElementsInShadowTree().
    432     if (isInShadowTree())
    433         return;
    434 
    435     // Do not allow self-referencing.
    436     // 'target' may be null, if it's a non SVG namespaced element.
    437     if (!target || target == this)
    438         return;
    439 
    440     // Why a seperated instance/shadow tree? SVG demands it:
    441     // The instance tree is accesable from JavaScript, and has to
    442     // expose a 1:1 copy of the referenced tree, whereas internally we need
    443     // to alter the tree for correct "use-on-symbol", "use-on-svg" support.
    444 
    445     // Build instance tree. Create root SVGElementInstance object for the first sub-tree node.
    446     //
    447     // Spec: If the 'use' element references a simple graphics element such as a 'rect', then there is only a
    448     // single SVGElementInstance object, and the correspondingElement attribute on this SVGElementInstance object
    449     // is the SVGRectElement that corresponds to the referenced 'rect' element.
    450     m_targetElementInstance = SVGElementInstance::create(this, this, target);
    451 
    452     // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children
    453     bool foundProblem = false;
    454     buildInstanceTree(target, m_targetElementInstance.get(), foundProblem, false);
    455 
    456     if (instanceTreeIsLoading(m_targetElementInstance.get()))
    457         return;
    458 
    459     // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!
    460     // Non-appearing <use> content is easier to debug, then half-appearing content.
    461     if (foundProblem) {
    462         clearResourceReferences();
    463         return;
    464     }
    465 
    466     // Assure instance tree building was successfull
    467     ASSERT(m_targetElementInstance);
    468     ASSERT(!m_targetElementInstance->shadowTreeElement());
    469     ASSERT(m_targetElementInstance->correspondingUseElement() == this);
    470     ASSERT(m_targetElementInstance->directUseElement() == this);
    471     ASSERT(m_targetElementInstance->correspondingElement() == target);
    472 
    473     ShadowRoot* shadowTreeRootElement = userAgentShadowRoot();
    474     ASSERT(shadowTreeRootElement);
    475 
    476     // Build shadow tree from instance tree
    477     // This also handles the special cases: <use> on <symbol>, <use> on <svg>.
    478     buildShadowTree(target, m_targetElementInstance.get());
    479 
    480     // Expand all <use> elements in the shadow tree.
    481     // Expand means: replace the actual <use> element by what it references.
    482     expandUseElementsInShadowTree(shadowTreeRootElement);
    483 
    484     // Expand all <symbol> elements in the shadow tree.
    485     // Expand means: replace the actual <symbol> element by the <svg> element.
    486     expandSymbolElementsInShadowTree(shadowTreeRootElement);
    487 
    488     // Now that the shadow tree is completly expanded, we can associate
    489     // shadow tree elements <-> instances in the instance tree.
    490     associateInstancesWithShadowTreeElements(shadowTreeRootElement->firstChild(), m_targetElementInstance.get());
    491 
    492     // If no shadow tree element is present, this means that the reference root
    493     // element was removed, as it is disallowed (ie. <use> on <foreignObject>)
    494     // Do NOT leave an inconsistent instance tree around, instead destruct it.
    495     if (!m_targetElementInstance->shadowTreeElement()) {
    496         clearResourceReferences();
    497         return;
    498     }
    499 
    500     ASSERT(m_targetElementInstance->shadowTreeElement()->parentNode() == shadowTreeRootElement);
    501 
    502     // Transfer event listeners assigned to the referenced element to our shadow tree elements.
    503     transferEventListenersToShadowTree(m_targetElementInstance.get());
    504 
    505     // Update relative length information.
    506     updateRelativeLengthsInformation();
    507 
    508     // Eventually dump instance tree
    509 #ifdef DUMP_INSTANCE_TREE
    510     String text;
    511     unsigned int depth = 0;
    512 
    513     dumpInstanceTree(depth, text, m_targetElementInstance.get());
    514     fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());
    515 #endif
    516 
    517     // Eventually dump shadow tree
    518 #ifdef DUMP_SHADOW_TREE
    519     RefPtr<XMLSerializer> serializer = XMLSerializer::create();
    520     String markup = serializer->serializeToString(shadowTreeRootElement, ASSERT_NO_EXCEPTION);
    521     fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
    522 #endif
    523 }
    524 
    525 RenderObject* SVGUseElement::createRenderer(RenderStyle*)
    526 {
    527     return new RenderSVGTransformableContainer(this);
    528 }
    529 
    530 static bool isDirectReference(const Node* node)
    531 {
    532     return node->hasTagName(SVGNames::pathTag)
    533            || node->hasTagName(SVGNames::rectTag)
    534            || node->hasTagName(SVGNames::circleTag)
    535            || node->hasTagName(SVGNames::ellipseTag)
    536            || node->hasTagName(SVGNames::polygonTag)
    537            || node->hasTagName(SVGNames::polylineTag)
    538            || node->hasTagName(SVGNames::textTag);
    539 }
    540 
    541 void SVGUseElement::toClipPath(Path& path)
    542 {
    543     ASSERT(path.isEmpty());
    544 
    545     Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : 0;
    546     if (!n)
    547         return;
    548 
    549     if (n->isSVGElement() && toSVGElement(n)->isSVGGraphicsElement()) {
    550         if (!isDirectReference(n)) {
    551             // Spec: Indirect references are an error (14.3.5)
    552             document().accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
    553         } else {
    554             toSVGGraphicsElement(n)->toClipPath(path);
    555             // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
    556             SVGLengthContext lengthContext(this);
    557             path.translate(FloatSize(xCurrentValue().value(lengthContext), yCurrentValue().value(lengthContext)));
    558             path.transform(animatedLocalTransform());
    559         }
    560     }
    561 }
    562 
    563 RenderObject* SVGUseElement::rendererClipChild() const
    564 {
    565     Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : 0;
    566     if (!n)
    567         return 0;
    568 
    569     if (n->isSVGElement() && isDirectReference(n))
    570         return toSVGElement(n)->renderer();
    571 
    572     return 0;
    573 }
    574 
    575 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem, bool foundUse)
    576 {
    577     ASSERT(target);
    578     ASSERT(targetInstance);
    579 
    580     // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced
    581     // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.
    582     bool targetHasUseTag = target->hasTagName(SVGNames::useTag);
    583     SVGElement* newTarget = 0;
    584     if (targetHasUseTag) {
    585         foundProblem = hasCycleUseReferencing(toSVGUseElement(target), targetInstance, newTarget);
    586         if (foundProblem)
    587             return;
    588 
    589         // We only need to track first degree <use> dependencies. Indirect references are handled
    590         // as the invalidation bubbles up the dependency chain.
    591         if (!foundUse) {
    592             document().accessSVGExtensions()->addElementReferencingTarget(this, target);
    593             foundUse = true;
    594         }
    595     } else if (isDisallowedElement(target)) {
    596         foundProblem = true;
    597         return;
    598     }
    599 
    600     // A general description from the SVG spec, describing what buildInstanceTree() actually does.
    601     //
    602     // Spec: If the 'use' element references a 'g' which contains two 'rect' elements, then the instance tree
    603     // contains three SVGElementInstance objects, a root SVGElementInstance object whose correspondingElement
    604     // is the SVGGElement object for the 'g', and then two child SVGElementInstance objects, each of which has
    605     // its correspondingElement that is an SVGRectElement object.
    606 
    607     for (Node* node = target->firstChild(); node; node = node->nextSibling()) {
    608         SVGElement* element = 0;
    609         if (node->isSVGElement())
    610             element = toSVGElement(node);
    611 
    612         // Skip any non-svg nodes or any disallowed element.
    613         if (!element || isDisallowedElement(element))
    614             continue;
    615 
    616         // Create SVGElementInstance object, for both container/non-container nodes.
    617         RefPtr<SVGElementInstance> instance = SVGElementInstance::create(this, 0, element);
    618         SVGElementInstance* instancePtr = instance.get();
    619         targetInstance->appendChild(instance.release());
    620 
    621         // Enter recursion, appending new instance tree nodes to the "instance" object.
    622         buildInstanceTree(element, instancePtr, foundProblem, foundUse);
    623         if (foundProblem)
    624             return;
    625     }
    626 
    627     if (!targetHasUseTag || !newTarget)
    628         return;
    629 
    630     RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, toSVGUseElement(target), newTarget);
    631     SVGElementInstance* newInstancePtr = newInstance.get();
    632     targetInstance->appendChild(newInstance.release());
    633     buildInstanceTree(newTarget, newInstancePtr, foundProblem, foundUse);
    634 }
    635 
    636 bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, SVGElement*& newTarget)
    637 {
    638     ASSERT(referencedDocument());
    639     Element* targetElement = SVGURIReference::targetElementFromIRIString(use->hrefCurrentValue(), *referencedDocument());
    640     newTarget = 0;
    641     if (targetElement && targetElement->isSVGElement())
    642         newTarget = toSVGElement(targetElement);
    643 
    644     if (!newTarget)
    645         return false;
    646 
    647     // Shortcut for self-references
    648     if (newTarget == this)
    649         return true;
    650 
    651     AtomicString targetId = newTarget->getIdAttribute();
    652     SVGElementInstance* instance = targetInstance->parentNode();
    653     while (instance) {
    654         SVGElement* element = instance->correspondingElement();
    655 
    656         if (element->hasID() && element->getIdAttribute() == targetId && element->document() == newTarget->document())
    657             return true;
    658 
    659         instance = instance->parentNode();
    660     }
    661     return false;
    662 }
    663 
    664 static inline void removeDisallowedElementsFromSubtree(Element& subtree)
    665 {
    666     ASSERT(!subtree.inDocument());
    667     Element* element = ElementTraversal::firstWithin(subtree);
    668     while (element) {
    669         if (isDisallowedElement(element)) {
    670             Element* next = ElementTraversal::nextSkippingChildren(*element, &subtree);
    671             // The subtree is not in document so this won't generate events that could mutate the tree.
    672             element->parentNode()->removeChild(element);
    673             element = next;
    674         } else {
    675             element = ElementTraversal::next(*element, &subtree);
    676         }
    677     }
    678 }
    679 
    680 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targetInstance)
    681 {
    682     // For instance <use> on <foreignObject> (direct case).
    683     if (isDisallowedElement(target))
    684         return;
    685 
    686     RefPtr<Element> newChild = targetInstance->correspondingElement()->cloneElementWithChildren();
    687 
    688     // We don't walk the target tree element-by-element, and clone each element,
    689     // but instead use cloneElementWithChildren(). This is an optimization for the common
    690     // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
    691     // Though if there are disallowed elements in the subtree, we have to remove them.
    692     // For instance: <use> on <g> containing <foreignObject> (indirect case).
    693     if (subtreeContainsDisallowedElement(newChild.get()))
    694         removeDisallowedElementsFromSubtree(*newChild);
    695 
    696     userAgentShadowRoot()->appendChild(newChild.release());
    697 }
    698 
    699 void SVGUseElement::expandUseElementsInShadowTree(Node* element)
    700 {
    701     // Why expand the <use> elements in the shadow tree here, and not just
    702     // do this directly in buildShadowTree, if we encounter a <use> element?
    703     //
    704     // Short answer: Because we may miss to expand some elements. Ie. if a <symbol>
    705     // contains <use> tags, we'd miss them. So once we're done with settin' up the
    706     // actual shadow tree (after the special case modification for svg/symbol) we have
    707     // to walk it completely and expand all <use> elements.
    708     if (element->hasTagName(SVGNames::useTag)) {
    709         SVGUseElement* use = toSVGUseElement(element);
    710         ASSERT(!use->resourceIsStillLoading());
    711 
    712         ASSERT(referencedDocument());
    713         Element* targetElement = SVGURIReference::targetElementFromIRIString(use->hrefCurrentValue(), *referencedDocument());
    714         SVGElement* target = 0;
    715         if (targetElement && targetElement->isSVGElement())
    716             target = toSVGElement(targetElement);
    717 
    718         // Don't ASSERT(target) here, it may be "pending", too.
    719         // Setup sub-shadow tree root node
    720         RefPtr<SVGGElement> cloneParent = SVGGElement::create(*referencedDocument());
    721         use->cloneChildNodes(cloneParent.get());
    722 
    723         // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
    724         // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
    725         transferUseAttributesToReplacedElement(use, cloneParent.get());
    726 
    727         if (target && !isDisallowedElement(target)) {
    728             RefPtr<Element> newChild = target->cloneElementWithChildren();
    729             ASSERT(newChild->isSVGElement());
    730             cloneParent->appendChild(newChild.release());
    731         }
    732 
    733         // We don't walk the target tree element-by-element, and clone each element,
    734         // but instead use cloneElementWithChildren(). This is an optimization for the common
    735         // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
    736         // Though if there are disallowed elements in the subtree, we have to remove them.
    737         // For instance: <use> on <g> containing <foreignObject> (indirect case).
    738         if (subtreeContainsDisallowedElement(cloneParent.get()))
    739             removeDisallowedElementsFromSubtree(*cloneParent);
    740 
    741         RefPtr<Node> replacingElement(cloneParent.get());
    742 
    743         // Replace <use> with referenced content.
    744         ASSERT(use->parentNode());
    745         use->parentNode()->replaceChild(cloneParent.release(), use);
    746 
    747         // Expand the siblings because the *element* is replaced and we will
    748         // lose the sibling chain when we are back from recursion.
    749         element = replacingElement.get();
    750         for (RefPtr<Node> sibling = element->nextSibling(); sibling; sibling = sibling->nextSibling())
    751             expandUseElementsInShadowTree(sibling.get());
    752     }
    753 
    754     for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
    755         expandUseElementsInShadowTree(child.get());
    756 }
    757 
    758 void SVGUseElement::expandSymbolElementsInShadowTree(Node* element)
    759 {
    760     if (element->hasTagName(SVGNames::symbolTag)) {
    761         // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,
    762         // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will
    763         // always have explicit values for attributes width and height. If attributes width and/or
    764         // height are provided on the 'use' element, then these attributes will be transferred to
    765         // the generated 'svg'. If attributes width and/or height are not specified, the generated
    766         // 'svg' element will use values of 100% for these attributes.
    767         ASSERT(referencedDocument());
    768         RefPtr<SVGSVGElement> svgElement = SVGSVGElement::create(*referencedDocument());
    769 
    770         // Transfer all data (attributes, etc.) from <symbol> to the new <svg> element.
    771         svgElement->cloneDataFromElement(*toElement(element));
    772 
    773         // Only clone symbol children, and add them to the new <svg> element
    774         for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
    775             RefPtr<Node> newChild = child->cloneNode(true);
    776             svgElement->appendChild(newChild.release());
    777         }
    778 
    779         // We don't walk the target tree element-by-element, and clone each element,
    780         // but instead use cloneNode(deep=true). This is an optimization for the common
    781         // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
    782         // Though if there are disallowed elements in the subtree, we have to remove them.
    783         // For instance: <use> on <g> containing <foreignObject> (indirect case).
    784         if (subtreeContainsDisallowedElement(svgElement.get()))
    785             removeDisallowedElementsFromSubtree(*svgElement);
    786 
    787         RefPtr<Node> replacingElement(svgElement.get());
    788 
    789         // Replace <symbol> with <svg>.
    790         element->parentNode()->replaceChild(svgElement.release(), element);
    791 
    792         // Expand the siblings because the *element* is replaced and we will
    793         // lose the sibling chain when we are back from recursion.
    794         element = replacingElement.get();
    795         for (RefPtr<Node> sibling = element->nextSibling(); sibling; sibling = sibling->nextSibling())
    796             expandSymbolElementsInShadowTree(sibling.get());
    797     }
    798 
    799     for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
    800         expandSymbolElementsInShadowTree(child.get());
    801 }
    802 
    803 void SVGUseElement::transferEventListenersToShadowTree(SVGElementInstance* target)
    804 {
    805     if (!target)
    806         return;
    807 
    808     SVGElement* originalElement = target->correspondingElement();
    809     ASSERT(originalElement);
    810 
    811     if (SVGElement* shadowTreeElement = target->shadowTreeElement()) {
    812         if (EventTargetData* data = originalElement->eventTargetData())
    813             data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(shadowTreeElement);
    814     }
    815 
    816     for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())
    817         transferEventListenersToShadowTree(instance);
    818 }
    819 
    820 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
    821 {
    822     if (!target || !targetInstance)
    823         return;
    824 
    825     SVGElement* originalElement = targetInstance->correspondingElement();
    826 
    827     if (originalElement->hasTagName(SVGNames::useTag)) {
    828         // <use> gets replaced by <g>
    829         ASSERT(target->nodeName() == SVGNames::gTag);
    830     } else if (originalElement->hasTagName(SVGNames::symbolTag)) {
    831         // <symbol> gets replaced by <svg>
    832         ASSERT(target->nodeName() == SVGNames::svgTag);
    833     } else
    834         ASSERT(target->nodeName() == originalElement->nodeName());
    835 
    836     SVGElement* element = 0;
    837     if (target->isSVGElement())
    838         element = toSVGElement(target);
    839 
    840     ASSERT(!targetInstance->shadowTreeElement());
    841     targetInstance->setShadowTreeElement(element);
    842     element->setCorrespondingElement(originalElement);
    843 
    844     Node* node = target->firstChild();
    845     for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {
    846         // Skip any non-svg elements in shadow tree
    847         while (node && !node->isSVGElement())
    848            node = node->nextSibling();
    849 
    850         if (!node)
    851             break;
    852 
    853         associateInstancesWithShadowTreeElements(node, instance);
    854         node = node->nextSibling();
    855     }
    856 }
    857 
    858 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const
    859 {
    860     if (!m_targetElementInstance) {
    861         ASSERT(!inDocument());
    862         return 0;
    863     }
    864 
    865     return instanceForShadowTreeElement(element, m_targetElementInstance.get());
    866 }
    867 
    868 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const
    869 {
    870     ASSERT(element);
    871     ASSERT(instance);
    872 
    873     // We're dispatching a mutation event during shadow tree construction
    874     // this instance hasn't yet been associated to a shadowTree element.
    875     if (!instance->shadowTreeElement())
    876         return 0;
    877 
    878     if (element == instance->shadowTreeElement())
    879         return instance;
    880 
    881     for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {
    882         if (SVGElementInstance* search = instanceForShadowTreeElement(element, current))
    883             return search;
    884     }
    885 
    886     return 0;
    887 }
    888 
    889 void SVGUseElement::invalidateShadowTree()
    890 {
    891     if (!inActiveDocument() || m_needsShadowTreeRecreation)
    892         return;
    893     m_needsShadowTreeRecreation = true;
    894     setNeedsStyleRecalc();
    895     invalidateDependentShadowTrees();
    896 }
    897 
    898 void SVGUseElement::invalidateDependentShadowTrees()
    899 {
    900     // Recursively invalidate dependent <use> shadow trees
    901     const HashSet<SVGElementInstance*>& instances = instancesForElement();
    902     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
    903     for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
    904         if (SVGUseElement* element = (*it)->correspondingUseElement()) {
    905             ASSERT(element->inDocument());
    906             element->invalidateShadowTree();
    907         }
    908     }
    909 }
    910 
    911 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
    912 {
    913     ASSERT(from);
    914     ASSERT(to);
    915 
    916     to->cloneDataFromElement(*from);
    917 
    918     to->removeAttribute(SVGNames::xAttr);
    919     to->removeAttribute(SVGNames::yAttr);
    920     to->removeAttribute(SVGNames::widthAttr);
    921     to->removeAttribute(SVGNames::heightAttr);
    922     to->removeAttribute(XLinkNames::hrefAttr);
    923 }
    924 
    925 bool SVGUseElement::selfHasRelativeLengths() const
    926 {
    927     if (xCurrentValue().isRelative()
    928         || yCurrentValue().isRelative()
    929         || widthCurrentValue().isRelative()
    930         || heightCurrentValue().isRelative())
    931         return true;
    932 
    933     if (!m_targetElementInstance)
    934         return false;
    935 
    936     SVGElement* element = m_targetElementInstance->correspondingElement();
    937     if (!element)
    938         return false;
    939 
    940     return element->hasRelativeLengths();
    941 }
    942 
    943 void SVGUseElement::notifyFinished(Resource* resource)
    944 {
    945     if (!inDocument())
    946         return;
    947 
    948     invalidateShadowTree();
    949     if (resource->errorOccurred())
    950         dispatchEvent(Event::create(EventTypeNames::error));
    951     else if (!resource->wasCanceled())
    952         SVGExternalResourcesRequired::dispatchLoadEvent(this);
    953 }
    954 
    955 bool SVGUseElement::resourceIsStillLoading()
    956 {
    957     if (m_resource && m_resource->isLoading())
    958         return true;
    959     return false;
    960 }
    961 
    962 bool SVGUseElement::instanceTreeIsLoading(SVGElementInstance* targetElementInstance)
    963 {
    964     for (SVGElementInstance* instance = targetElementInstance->firstChild(); instance; instance = instance->nextSibling()) {
    965         if (SVGUseElement* use = instance->correspondingUseElement()) {
    966             if (use->resourceIsStillLoading())
    967                 return true;
    968         }
    969         if (instance->hasChildNodes())
    970             instanceTreeIsLoading(instance);
    971     }
    972     return false;
    973 }
    974 
    975 void SVGUseElement::finishParsingChildren()
    976 {
    977     SVGGraphicsElement::finishParsingChildren();
    978     SVGExternalResourcesRequired::finishParsingChildren();
    979     if (m_wasInsertedByParser) {
    980         buildPendingResource();
    981         m_wasInsertedByParser = false;
    982     }
    983 }
    984 
    985 void SVGUseElement::setDocumentResource(ResourcePtr<DocumentResource> resource)
    986 {
    987     if (m_resource == resource)
    988         return;
    989 
    990     if (m_resource)
    991         m_resource->removeClient(this);
    992 
    993     m_resource = resource;
    994     if (m_resource)
    995         m_resource->addClient(this);
    996 }
    997 
    998 }
    999