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