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