OSDN Git Service

Merge WebKit at r73109: Initial merge by git.
[android-x86/external-webkit.git] / WebCore / 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  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23
24 #if ENABLE(SVG)
25 #include "SVGUseElement.h"
26
27 #include "Attribute.h"
28 #include "CSSStyleSelector.h"
29 #include "Document.h"
30 #include "Event.h"
31 #include "EventListener.h"
32 #include "HTMLNames.h"
33 #include "NodeRenderStyle.h"
34 #include "RegisteredEventListener.h"
35 #include "RenderSVGResource.h"
36 #include "RenderSVGShadowTreeRootContainer.h"
37 #include "SVGElementInstance.h"
38 #include "SVGElementInstanceList.h"
39 #include "SVGGElement.h"
40 #include "SVGLength.h"
41 #include "SVGPreserveAspectRatio.h"
42 #include "SVGSMILElement.h"
43 #include "SVGSVGElement.h"
44 #include "SVGShadowTreeElements.h"
45 #include "SVGSymbolElement.h"
46 #include "XLinkNames.h"
47 #include "XMLDocumentParser.h"
48 #include "XMLSerializer.h"
49
50 #include <wtf/text/StringConcatenate.h>
51
52 // Dump SVGElementInstance object tree - useful to debug instanceRoot problems
53 // #define DUMP_INSTANCE_TREE
54
55 // Dump the deep-expanded shadow tree (where the renderers are built from)
56 // #define DUMP_SHADOW_TREE
57
58 namespace WebCore {
59
60 // Animated property definitions
61 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::xAttr, X, x)
62 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::yAttr, Y, y)
63 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::widthAttr, Width, width)
64 DEFINE_ANIMATED_LENGTH(SVGUseElement, SVGNames::heightAttr, Height, height)
65
66 inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document* document)
67     : SVGStyledTransformableElement(tagName, document)
68     , m_x(LengthModeWidth)
69     , m_y(LengthModeHeight)
70     , m_width(LengthModeWidth)
71     , m_height(LengthModeHeight)
72     , m_updatesBlocked(false)
73     , m_isPendingResource(false)
74     , m_needsShadowTreeRecreation(false)
75 {
76 }
77
78 PassRefPtr<SVGUseElement> SVGUseElement::create(const QualifiedName& tagName, Document* document)
79 {
80     return adoptRef(new SVGUseElement(tagName, document));
81 }
82
83 SVGElementInstance* SVGUseElement::instanceRoot() const
84 {
85     // If there is no element instance tree, force immediate SVGElementInstance tree
86     // creation by asking the document to invoke our recalcStyle function - as we can't
87     // wait for the lazy creation to happen if e.g. JS wants to access the instanceRoot
88     // object right after creating the element on-the-fly
89     if (!m_targetElementInstance)
90         document()->updateLayoutIgnorePendingStylesheets();
91
92     return m_targetElementInstance.get();
93 }
94
95 SVGElementInstance* SVGUseElement::animatedInstanceRoot() const
96 {
97     // FIXME: Implement me.
98     return 0;
99 }
100  
101 void SVGUseElement::parseMappedAttribute(Attribute* attr)
102 {
103     if (attr->name() == SVGNames::xAttr)
104         setXBaseValue(SVGLength(LengthModeWidth, attr->value()));
105     else if (attr->name() == SVGNames::yAttr)
106         setYBaseValue(SVGLength(LengthModeHeight, attr->value()));
107     else if (attr->name() == SVGNames::widthAttr) {
108         setWidthBaseValue(SVGLength(LengthModeWidth, attr->value()));
109         if (widthBaseValue().value(this) < 0.0)
110             document()->accessSVGExtensions()->reportError("A negative value for use attribute <width> is not allowed");
111     } else if (attr->name() == SVGNames::heightAttr) {
112         setHeightBaseValue(SVGLength(LengthModeHeight, attr->value()));
113         if (heightBaseValue().value(this) < 0.0)
114             document()->accessSVGExtensions()->reportError("A negative value for use attribute <height> is not allowed");
115     } else {
116         if (SVGTests::parseMappedAttribute(attr))
117             return;
118         if (SVGLangSpace::parseMappedAttribute(attr))
119             return;
120         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
121             return;
122         if (SVGURIReference::parseMappedAttribute(attr))
123             return;
124         SVGStyledTransformableElement::parseMappedAttribute(attr);
125     }
126 }
127
128 void SVGUseElement::insertedIntoDocument()
129 {
130     // This functions exists to assure assumptions made in the code regarding SVGElementInstance creation/destruction are satisfied.
131     SVGStyledTransformableElement::insertedIntoDocument();
132     ASSERT(!m_targetElementInstance || ((document()->isSVGDocument() || document()->isXHTMLDocument()) && !static_cast<XMLDocumentParser*>(document()->parser())->wellFormed()));
133     ASSERT(!m_isPendingResource);
134 }
135
136 void SVGUseElement::removedFromDocument()
137 {
138     SVGStyledTransformableElement::removedFromDocument();
139     m_targetElementInstance = 0;
140 }
141
142 void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
143 {
144     SVGStyledTransformableElement::svgAttributeChanged(attrName);
145
146     bool isXYAttribute = attrName == SVGNames::xAttr || attrName == SVGNames::yAttr;
147     bool isWidthHeightAttribute = attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr;
148
149     if (isXYAttribute || isWidthHeightAttribute)
150         updateRelativeLengthsInformation();
151
152     if (SVGTests::handleAttributeChange(this, attrName))
153         return;
154
155     RenderObject* object = renderer();
156     if (!object)
157         return;
158
159     if (SVGURIReference::isKnownAttribute(attrName)) {
160         if (m_isPendingResource) {
161             document()->accessSVGExtensions()->removePendingResource(m_resourceId);
162             m_resourceId = String();
163             m_isPendingResource = false;
164         }
165
166         invalidateShadowTree();
167         return;
168     }
169
170     if (isXYAttribute) {
171         updateContainerOffsets();
172         return;
173     }
174
175     if (isWidthHeightAttribute) {
176         updateContainerSizes();
177         return;
178     }
179
180     // Be very careful here, if svgAttributeChanged() has been called because a SVG CSS property changed, we do NOT want to reclone the tree!
181     if (SVGStyledElement::isKnownAttribute(attrName)) {
182         setNeedsStyleRecalc();
183         return;
184     }
185
186     if (SVGStyledTransformableElement::isKnownAttribute(attrName)) {
187         object->setNeedsTransformUpdate();
188         RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
189         return;
190     }
191
192     if (SVGLangSpace::isKnownAttribute(attrName)
193         || SVGExternalResourcesRequired::isKnownAttribute(attrName))
194         invalidateShadowTree();
195 }
196
197 void SVGUseElement::synchronizeProperty(const QualifiedName& attrName)
198 {
199     SVGStyledTransformableElement::synchronizeProperty(attrName);
200
201     if (attrName == anyQName()) {
202         synchronizeX();
203         synchronizeY();
204         synchronizeWidth();
205         synchronizeHeight();
206         synchronizeExternalResourcesRequired();
207         synchronizeHref();
208         SVGTests::synchronizeProperties(this, attrName);
209         return;
210     }
211
212     if (attrName == SVGNames::xAttr)
213         synchronizeX();
214     else if (attrName == SVGNames::yAttr)
215         synchronizeY();
216     else if (attrName == SVGNames::widthAttr)
217         synchronizeWidth();
218     else if (attrName == SVGNames::heightAttr)
219         synchronizeHeight();
220     else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
221         synchronizeExternalResourcesRequired();
222     else if (SVGURIReference::isKnownAttribute(attrName))
223         synchronizeHref();
224     else if (SVGTests::isKnownAttribute(attrName))
225         SVGTests::synchronizeProperties(this, attrName);
226 }
227
228 static void updateContainerSize(SVGUseElement* useElement, SVGElementInstance* targetInstance)
229 {
230     // Depth-first used to write the method in early exit style, no particular other reason.
231     for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
232         updateContainerSize(useElement, instance);
233
234     SVGElement* correspondingElement = targetInstance->correspondingElement();
235     ASSERT(correspondingElement);
236
237     bool isSymbolTag = correspondingElement->hasTagName(SVGNames::symbolTag);
238     if (!correspondingElement->hasTagName(SVGNames::svgTag) && !isSymbolTag)
239         return;
240
241     SVGElement* shadowTreeElement = targetInstance->shadowTreeElement();
242     ASSERT(shadowTreeElement);
243     ASSERT(shadowTreeElement->hasTagName(SVGNames::svgTag));
244
245     // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
246     // If attributes width and/or height are provided on the 'use' element, then these attributes
247     // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
248     // the generated 'svg' element will use values of 100% for these attributes.
249     
250     // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
251     // values will override the corresponding attributes on the 'svg' in the generated tree.
252
253     if (useElement->hasAttribute(SVGNames::widthAttr))
254         shadowTreeElement->setAttribute(SVGNames::widthAttr, useElement->getAttribute(SVGNames::widthAttr));
255     else if (isSymbolTag && shadowTreeElement->hasAttribute(SVGNames::widthAttr))
256         shadowTreeElement->setAttribute(SVGNames::widthAttr, "100%");
257
258     if (useElement->hasAttribute(SVGNames::heightAttr))
259         shadowTreeElement->setAttribute(SVGNames::heightAttr, useElement->getAttribute(SVGNames::heightAttr));
260     else if (isSymbolTag && shadowTreeElement->hasAttribute(SVGNames::heightAttr))
261         shadowTreeElement->setAttribute(SVGNames::heightAttr, "100%");
262 }   
263
264 void SVGUseElement::updateContainerSizes()
265 {
266     if (!m_targetElementInstance)
267         return;
268
269     // Update whole subtree, scanning for shadow container elements, that correspond to <svg>/<symbol> tags
270     updateContainerSize(this, m_targetElementInstance.get());
271
272     if (RenderObject* object = renderer())
273         RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
274 }
275
276 static void updateContainerOffset(SVGElementInstance* targetInstance)
277 {
278     // Depth-first used to write the method in early exit style, no particular other reason.
279     for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
280         updateContainerOffset(instance);
281
282     SVGElement* correspondingElement = targetInstance->correspondingElement();
283     ASSERT(correspondingElement);
284
285     if (!correspondingElement->hasTagName(SVGNames::useTag))
286         return;
287
288     SVGElement* shadowTreeElement = targetInstance->shadowTreeElement();
289     ASSERT(shadowTreeElement);
290     ASSERT(shadowTreeElement->hasTagName(SVGNames::gTag));
291
292     if (!static_cast<SVGGElement*>(shadowTreeElement)->isShadowTreeContainerElement())
293         return;
294
295     // Spec: An additional transformation translate(x,y) is appended to the end
296     // (i.e., right-side) of the transform attribute on the generated 'g', where x
297     // and y represent the values of the x and y attributes on the 'use' element. 
298     SVGUseElement* useElement = static_cast<SVGUseElement*>(correspondingElement);
299     SVGShadowTreeContainerElement* containerElement = static_cast<SVGShadowTreeContainerElement*>(shadowTreeElement);
300     containerElement->setContainerOffset(useElement->x(), useElement->y());
301 }
302
303 void SVGUseElement::updateContainerOffsets()
304 {
305     if (!m_targetElementInstance)
306         return;
307
308     // Update root container offset (not reachable through instance tree)
309     SVGElement* shadowRoot = m_targetElementInstance->shadowTreeElement();
310     ASSERT(shadowRoot);
311
312     ContainerNode* parentNode = shadowRoot->parentNode();
313     ASSERT(parentNode);
314     ASSERT(parentNode->isSVGElement());
315     ASSERT(parentNode->hasTagName(SVGNames::gTag));
316     ASSERT(static_cast<SVGGElement*>(parentNode)->isShadowTreeContainerElement());
317
318     SVGShadowTreeContainerElement* containerElement = static_cast<SVGShadowTreeContainerElement*>(parentNode);
319     containerElement->setContainerOffset(x(), y());
320
321     // Update whole subtree, scanning for shadow container elements, marking a cloned use subtree
322     updateContainerOffset(m_targetElementInstance.get());
323
324     if (RenderObject* object = renderer())
325         RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
326 }
327
328 void SVGUseElement::recalcStyle(StyleChange change)
329 {
330     // Eventually mark shadow root element needing style recalc
331     if (needsStyleRecalc() && m_targetElementInstance && !m_updatesBlocked) {
332         if (SVGElement* shadowRoot = m_targetElementInstance->shadowTreeElement())
333             shadowRoot->setNeedsStyleRecalc();
334     }
335
336     SVGStyledTransformableElement::recalcStyle(change);
337
338     // Assure that the shadow tree has not been marked for recreation, while we're building it.
339     if (m_updatesBlocked)
340         ASSERT(!m_needsShadowTreeRecreation);
341
342     RenderSVGShadowTreeRootContainer* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer());
343     if (!shadowRoot)
344         return;
345     
346     bool needsStyleUpdate = !m_needsShadowTreeRecreation;
347     if (m_needsShadowTreeRecreation) {
348         shadowRoot->markShadowTreeForRecreation();
349         m_needsShadowTreeRecreation = false;
350     }
351
352     shadowRoot->updateFromElement();
353
354     if (!needsStyleUpdate)
355         return;
356
357     shadowRoot->updateStyle(change);
358 }
359
360 #ifdef DUMP_INSTANCE_TREE
361 void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstance* targetInstance)
362 {
363     SVGElement* element = targetInstance->correspondingElement();
364     ASSERT(element);
365
366     SVGElement* shadowTreeElement = targetInstance->shadowTreeElement();
367     ASSERT(shadowTreeElement);
368
369     String elementId = element->getIdAttribute();
370     String elementNodeName = element->nodeName();
371     String shadowTreeElementNodeName = shadowTreeElement->nodeName();
372     String parentNodeName = element->parentNode() ? element->parentNode()->nodeName() : "null";
373     String firstChildNodeName = element->firstChild() ? element->firstChild()->nodeName() : "null";
374
375     for (unsigned int i = 0; i < depth; ++i)
376         text += "  ";
377
378     text += String::format("SVGElementInstance this=%p, (parentNode=%s (%p), firstChild=%s (%p), correspondingElement=%s (%p), shadowTreeElement=%s (%p), id=%s)\n",
379                            targetInstance, parentNodeName.latin1().data(), element->parentNode(), firstChildNodeName.latin1().data(), element->firstChild(),
380                            elementNodeName.latin1().data(), element, shadowTreeElementNodeName.latin1().data(), shadowTreeElement, elementId.latin1().data());
381
382     for (unsigned int i = 0; i < depth; ++i)
383         text += "  ";
384
385     const HashSet<SVGElementInstance*>& elementInstances = element->instancesForElement();
386     text += makeString("Corresponding element is associated with ", String::number(elementInstances.size()), " instance(s):\n");
387
388     const HashSet<SVGElementInstance*>::const_iterator end = elementInstances.end();
389     for (HashSet<SVGElementInstance*>::const_iterator it = elementInstances.begin(); it != end; ++it) {
390         for (unsigned int i = 0; i < depth; ++i)
391             text += "  ";
392
393         text += String::format(" -> SVGElementInstance this=%p, (refCount: %i, shadowTreeElement in document? %i)\n",
394                                *it, (*it)->refCount(), (*it)->shadowTreeElement()->inDocument());
395     }
396
397     ++depth;
398
399     for (SVGElementInstance* instance = targetInstance->firstChild(); instance; instance = instance->nextSibling())
400         dumpInstanceTree(depth, text, instance);
401
402     --depth;
403 }
404 #endif
405
406 static bool isDisallowedElement(Node* element)
407 {
408 #if ENABLE(SVG_FOREIGN_OBJECT)
409     // <foreignObject> should never be contained in a <use> tree. Too dangerous side effects possible.
410     if (element->hasTagName(SVGNames::foreignObjectTag))
411         return true;
412 #endif
413 #if ENABLE(SVG_ANIMATION)
414     if (SVGSMILElement::isSMILElement(element))
415         return true;
416 #endif
417
418     return false;
419 }
420
421 static bool subtreeContainsDisallowedElement(Node* start)
422 {
423     if (isDisallowedElement(start))
424         return true;
425
426     for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {
427         if (subtreeContainsDisallowedElement(cur))
428             return true;
429     }
430
431     return false;
432 }
433
434 void SVGUseElement::buildPendingResource()
435 {
436     // If we're called the first time (during shadow tree root creation from RenderSVGShadowTreeRootContainer)
437     // we either determine that our target is available or not - then we add ourselves to the pending resource list
438     // Once the pending resource appears, it will call buildPendingResource(), so we're called a second time.
439     String id = SVGURIReference::getTarget(href());
440     Element* targetElement = document()->getElementById(id);
441     ASSERT(!m_targetElementInstance);
442
443     if (!targetElement) {
444         if (m_isPendingResource || id.isEmpty())
445             return;
446
447         m_isPendingResource = true;
448         m_resourceId = id;
449         document()->accessSVGExtensions()->addPendingResource(id, this);
450         return;
451     }
452
453     if (m_isPendingResource) {
454         ASSERT(!m_targetElementInstance);
455         m_isPendingResource = false;    
456         invalidateShadowTree();
457     }
458 }
459
460 void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowRoot)
461 {
462     struct ShadowTreeUpdateBlocker {
463         ShadowTreeUpdateBlocker(SVGUseElement* currentUseElement)
464             : useElement(currentUseElement)
465         {
466             useElement->setUpdatesBlocked(true);
467         }
468
469         ~ShadowTreeUpdateBlocker()
470         {
471             useElement->setUpdatesBlocked(false);
472         }
473
474         SVGUseElement* useElement;
475     };
476
477     // When cloning the target nodes, they may decide to synchronize style and/or animated SVG attributes.
478     // That causes calls to SVGElementInstance::updateAllInstancesOfElement(), which mark the shadow tree for recreation.
479     // Solution: block any updates to the shadow tree while we're building it.
480     ShadowTreeUpdateBlocker blocker(this);
481
482     String id = SVGURIReference::getTarget(href());
483     Element* targetElement = document()->getElementById(id);
484     if (!targetElement) {
485         // The only time we should get here is when the use element has not been
486         // given a resource to target.
487         ASSERT(m_resourceId.isEmpty());
488         return;
489     }
490
491     // Do not build the shadow/instance tree for <use> elements living in a shadow tree.
492     // The will be expanded soon anyway - see expandUseElementsInShadowTree().
493     ContainerNode* parent = parentNode();
494     while (parent) {
495         if (parent->isShadowNode())
496             return;
497
498         parent = parent->parentNode();
499     }
500  
501     SVGElement* target = 0;
502     if (targetElement && targetElement->isSVGElement())
503         target = static_cast<SVGElement*>(targetElement);
504
505     if (m_targetElementInstance)
506         m_targetElementInstance = 0;
507
508     // Do not allow self-referencing.
509     // 'target' may be null, if it's a non SVG namespaced element.
510     if (!target || target == this)
511         return;
512
513     // Why a seperated instance/shadow tree? SVG demands it:
514     // The instance tree is accesable from JavaScript, and has to
515     // expose a 1:1 copy of the referenced tree, whereas internally we need
516     // to alter the tree for correct "use-on-symbol", "use-on-svg" support.  
517  
518     // Build instance tree. Create root SVGElementInstance object for the first sub-tree node.
519     //
520     // Spec: If the 'use' element references a simple graphics element such as a 'rect', then there is only a
521     // single SVGElementInstance object, and the correspondingElement attribute on this SVGElementInstance object
522     // is the SVGRectElement that corresponds to the referenced 'rect' element.
523     m_targetElementInstance = SVGElementInstance::create(this, target);
524
525     // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children
526     bool foundProblem = false;
527     buildInstanceTree(target, m_targetElementInstance.get(), foundProblem);
528
529     // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!
530     // Non-appearing <use> content is easier to debug, then half-appearing content.
531     if (foundProblem) {
532         m_targetElementInstance = 0;
533         return;
534     }
535
536     // Assure instance tree building was successfull
537     ASSERT(m_targetElementInstance);
538     ASSERT(!m_targetElementInstance->shadowTreeElement());
539     ASSERT(m_targetElementInstance->correspondingUseElement() == this);
540     ASSERT(m_targetElementInstance->correspondingElement() == target);
541
542     // Build shadow tree from instance tree
543     // This also handles the special cases: <use> on <symbol>, <use> on <svg>.
544     buildShadowTree(shadowRoot, target, m_targetElementInstance.get());
545
546 #if ENABLE(SVG) && ENABLE(SVG_USE)
547     // Expand all <use> elements in the shadow tree.
548     // Expand means: replace the actual <use> element by what it references.
549     expandUseElementsInShadowTree(shadowRoot, shadowRoot);
550
551     // Expand all <symbol> elements in the shadow tree.
552     // Expand means: replace the actual <symbol> element by the <svg> element.
553     expandSymbolElementsInShadowTree(shadowRoot, shadowRoot);
554 #endif
555
556     // Now that the shadow tree is completly expanded, we can associate
557     // shadow tree elements <-> instances in the instance tree.
558     associateInstancesWithShadowTreeElements(shadowRoot->firstChild(), m_targetElementInstance.get());
559
560     // If no shadow tree element is present, this means that the reference root
561     // element was removed, as it is disallowed (ie. <use> on <foreignObject>)
562     // Do NOT leave an inconsistent instance tree around, instead destruct it.
563     if (!m_targetElementInstance->shadowTreeElement()) {
564         shadowRoot->removeAllChildren();
565         m_targetElementInstance = 0;
566         return;
567     }
568
569     // Consistency checks - this is assumed in updateContainerOffset().
570     ASSERT(m_targetElementInstance->shadowTreeElement()->parentNode() == shadowRoot);
571
572     // Eventually dump instance tree
573 #ifdef DUMP_INSTANCE_TREE
574     String text;
575     unsigned int depth = 0;
576
577     dumpInstanceTree(depth, text, m_targetElementInstance.get());
578     fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());
579 #endif
580
581     // Eventually dump shadow tree
582 #ifdef DUMP_SHADOW_TREE
583     ExceptionCode ec = 0;
584
585     PassRefPtr<XMLSerializer> serializer = XMLSerializer::create();
586
587     String markup = serializer->serializeToString(shadowRoot, ec);
588     ASSERT(!ec);
589
590     fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
591 #endif
592
593     // Transfer event listeners assigned to the referenced element to our shadow tree elements.
594     transferEventListenersToShadowTree(m_targetElementInstance.get());
595
596     // Update container offset/size
597     updateContainerOffsets();
598     updateContainerSizes();
599
600     // Update relative length information
601     updateRelativeLengthsInformation();
602 }
603
604 RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*)
605 {
606     return new (arena) RenderSVGShadowTreeRootContainer(this);
607 }
608
609 static void updateFromElementCallback(Node* node)
610 {
611     if (RenderObject* renderer = node->renderer())
612         renderer->updateFromElement();
613 }
614
615 void SVGUseElement::attach()
616 {
617     SVGStyledTransformableElement::attach();
618
619     if (renderer())
620         queuePostAttachCallback(updateFromElementCallback, this);
621 }
622
623 void SVGUseElement::detach()
624 {
625     SVGStyledTransformableElement::detach();
626     m_targetElementInstance = 0;
627 }
628
629 static bool isDirectReference(Node* n)
630 {
631     return n->hasTagName(SVGNames::pathTag) ||
632            n->hasTagName(SVGNames::rectTag) ||
633            n->hasTagName(SVGNames::circleTag) ||
634            n->hasTagName(SVGNames::ellipseTag) ||
635            n->hasTagName(SVGNames::polygonTag) ||
636            n->hasTagName(SVGNames::polylineTag) ||
637            n->hasTagName(SVGNames::textTag);
638 }
639
640 void SVGUseElement::toClipPath(Path& path) const
641 {
642     ASSERT(path.isEmpty());
643
644     Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : 0;
645     if (!n)
646         return;
647
648     if (n->isSVGElement() && static_cast<SVGElement*>(n)->isStyledTransformable()) {
649         if (!isDirectReference(n))
650             // Spec: Indirect references are an error (14.3.5)
651             document()->accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
652         else {
653             static_cast<SVGStyledTransformableElement*>(n)->toClipPath(path);
654             path.translate(FloatSize(x().value(this), y().value(this)));
655             path.transform(animatedLocalTransform());
656         }
657     }
658 }
659
660 RenderObject* SVGUseElement::rendererClipChild() const
661 {
662     Node* n = m_targetElementInstance ? m_targetElementInstance->shadowTreeElement() : 0;
663     if (!n)
664         return 0;
665
666     if (n->isSVGElement() && isDirectReference(n))
667         return static_cast<SVGElement*>(n)->renderer();
668
669     return 0;
670 }
671
672 void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* targetInstance, bool& foundProblem)
673 {
674     ASSERT(target);
675     ASSERT(targetInstance);
676
677     // A general description from the SVG spec, describing what buildInstanceTree() actually does.
678     //
679     // Spec: If the 'use' element references a 'g' which contains two 'rect' elements, then the instance tree
680     // contains three SVGElementInstance objects, a root SVGElementInstance object whose correspondingElement
681     // is the SVGGElement object for the 'g', and then two child SVGElementInstance objects, each of which has
682     // its correspondingElement that is an SVGRectElement object.
683
684     for (Node* node = target->firstChild(); node; node = node->nextSibling()) {
685         SVGElement* element = 0;
686         if (node->isSVGElement())
687             element = static_cast<SVGElement*>(node);
688
689         // Skip any non-svg nodes or any disallowed element.
690         if (!element || isDisallowedElement(element))
691             continue;
692
693         // Create SVGElementInstance object, for both container/non-container nodes.
694         RefPtr<SVGElementInstance> instance = SVGElementInstance::create(this, element);
695         SVGElementInstance* instancePtr = instance.get();
696         targetInstance->appendChild(instance.release());
697
698         // Enter recursion, appending new instance tree nodes to the "instance" object.
699         buildInstanceTree(element, instancePtr, foundProblem);
700     }
701
702     // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced
703     // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.
704     if (target->hasTagName(SVGNames::useTag))
705         handleDeepUseReferencing(static_cast<SVGUseElement*>(target), targetInstance, foundProblem);
706 }
707
708 void SVGUseElement::handleDeepUseReferencing(SVGUseElement* use, SVGElementInstance* targetInstance, bool& foundProblem)
709 {
710     String id = SVGURIReference::getTarget(use->href());
711     Element* targetElement = document()->getElementById(id); 
712     SVGElement* target = 0;
713     if (targetElement && targetElement->isSVGElement())
714         target = static_cast<SVGElement*>(targetElement);
715
716     if (!target)
717         return;
718
719     // Cycle detection first!
720     foundProblem = (target == this);
721
722     // Shortcut for self-references
723     if (foundProblem)
724         return;
725
726     SVGElementInstance* instance = targetInstance->parentNode();
727     while (instance) {
728         SVGElement* element = instance->correspondingElement();
729
730         // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution.
731         if (element->hasID() && element->idForStyleResolution() == id) {
732             foundProblem = true;
733             return;
734         }
735     
736         instance = instance->parentNode();
737     }
738
739     // Create an instance object, even if we're dealing with a cycle
740     RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, target);
741     SVGElementInstance* newInstancePtr = newInstance.get();
742     targetInstance->appendChild(newInstance.release());
743
744     // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children
745     buildInstanceTree(target, newInstancePtr, foundProblem);
746 }
747
748 void SVGUseElement::removeDisallowedElementsFromSubtree(Node* subtree)
749 {
750     ASSERT(!subtree->inDocument());
751     ExceptionCode ec;
752     Node* node = subtree->firstChild();
753     while (node) {
754         if (isDisallowedElement(node)) {
755             Node* next = node->traverseNextSibling(subtree);
756             // The subtree is not in document so this won't generate events that could mutate the tree.
757             node->parentNode()->removeChild(node, ec);
758             node = next;
759         } else
760             node = node->traverseNextNode(subtree);
761     }
762 }
763
764 void SVGUseElement::buildShadowTree(SVGShadowTreeRootElement* shadowRoot, SVGElement* target, SVGElementInstance* targetInstance)
765 {
766     // For instance <use> on <foreignObject> (direct case).
767     if (isDisallowedElement(target))
768         return;
769
770     RefPtr<Element> newChild = targetInstance->correspondingElement()->cloneElementWithChildren();
771
772     // We don't walk the target tree element-by-element, and clone each element,
773     // but instead use cloneElementWithChildren(). This is an optimization for the common
774     // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
775     // Though if there are disallowed elements in the subtree, we have to remove them.
776     // For instance: <use> on <g> containing <foreignObject> (indirect case).
777     if (subtreeContainsDisallowedElement(newChild.get()))
778         removeDisallowedElementsFromSubtree(newChild.get());
779
780     SVGElement* newChildPtr = 0;
781     if (newChild->isSVGElement())
782         newChildPtr = static_cast<SVGElement*>(newChild.get());
783     ASSERT(newChildPtr);
784
785     ExceptionCode ec = 0;
786     shadowRoot->appendChild(newChild.release(), ec);
787     ASSERT(!ec);
788 }
789
790 #if ENABLE(SVG) && ENABLE(SVG_USE)
791 void SVGUseElement::expandUseElementsInShadowTree(SVGShadowTreeRootElement* shadowRoot, Node* element)
792 {
793     // Why expand the <use> elements in the shadow tree here, and not just
794     // do this directly in buildShadowTree, if we encounter a <use> element?
795     //
796     // Short answer: Because we may miss to expand some elements. Ie. if a <symbol>
797     // contains <use> tags, we'd miss them. So once we're done with settin' up the
798     // actual shadow tree (after the special case modification for svg/symbol) we have
799     // to walk it completely and expand all <use> elements.
800     if (element->hasTagName(SVGNames::useTag)) {
801         SVGUseElement* use = static_cast<SVGUseElement*>(element);
802
803         String id = SVGURIReference::getTarget(use->href());
804         Element* targetElement = document()->getElementById(id); 
805         SVGElement* target = 0;
806         if (targetElement && targetElement->isSVGElement())
807             target = static_cast<SVGElement*>(targetElement);
808
809         // Don't ASSERT(target) here, it may be "pending", too.
810         // Setup sub-shadow tree root node
811         RefPtr<SVGShadowTreeContainerElement> cloneParent = SVGShadowTreeContainerElement::create(document());
812         use->cloneChildNodes(cloneParent.get());
813
814         // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
815         // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
816         transferUseAttributesToReplacedElement(use, cloneParent.get());
817
818         ExceptionCode ec = 0;
819         if (target && !isDisallowedElement(target)) {
820             RefPtr<Element> newChild = target->cloneElementWithChildren();
821
822             SVGElement* newChildPtr = 0;
823             if (newChild->isSVGElement())
824                 newChildPtr = static_cast<SVGElement*>(newChild.get());
825             ASSERT(newChildPtr);
826
827             cloneParent->appendChild(newChild.release(), ec);
828             ASSERT(!ec);
829         }
830
831         // We don't walk the target tree element-by-element, and clone each element,
832         // but instead use cloneElementWithChildren(). This is an optimization for the common
833         // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
834         // Though if there are disallowed elements in the subtree, we have to remove them.
835         // For instance: <use> on <g> containing <foreignObject> (indirect case).
836         if (subtreeContainsDisallowedElement(cloneParent.get()))
837             removeDisallowedElementsFromSubtree(cloneParent.get());
838
839         // Replace <use> with referenced content.
840         ASSERT(use->parentNode()); 
841         use->parentNode()->replaceChild(cloneParent.release(), use, ec);
842         ASSERT(!ec);
843
844         // Immediately stop here, and restart expanding.
845         expandUseElementsInShadowTree(shadowRoot, shadowRoot);
846         return;
847     }
848
849     for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
850         expandUseElementsInShadowTree(shadowRoot, child.get());
851 }
852
853 void SVGUseElement::expandSymbolElementsInShadowTree(SVGShadowTreeRootElement* shadowRoot, Node* element)
854 {
855     if (element->hasTagName(SVGNames::symbolTag)) {
856         // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,
857         // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will
858         // always have explicit values for attributes width and height. If attributes width and/or
859         // height are provided on the 'use' element, then these attributes will be transferred to
860         // the generated 'svg'. If attributes width and/or height are not specified, the generated
861         // 'svg' element will use values of 100% for these attributes.
862         RefPtr<SVGSVGElement> svgElement = SVGSVGElement::create(SVGNames::svgTag, document());
863
864         // Transfer all attributes from <symbol> to the new <svg> element
865         svgElement->attributes()->setAttributes(*element->attributes());
866
867         // Only clone symbol children, and add them to the new <svg> element    
868         ExceptionCode ec = 0;
869         for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
870             RefPtr<Node> newChild = child->cloneNode(true);
871             svgElement->appendChild(newChild.release(), ec);
872             ASSERT(!ec);
873         }
874     
875         // We don't walk the target tree element-by-element, and clone each element,
876         // but instead use cloneNode(deep=true). This is an optimization for the common
877         // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
878         // Though if there are disallowed elements in the subtree, we have to remove them.
879         // For instance: <use> on <g> containing <foreignObject> (indirect case).
880         if (subtreeContainsDisallowedElement(svgElement.get()))
881             removeDisallowedElementsFromSubtree(svgElement.get());
882
883         // Replace <symbol> with <svg>.
884         ASSERT(element->parentNode()); 
885         element->parentNode()->replaceChild(svgElement.release(), element, ec);
886         ASSERT(!ec);
887
888         // Immediately stop here, and restart expanding.
889         expandSymbolElementsInShadowTree(shadowRoot, shadowRoot);
890         return;
891     }
892
893     for (RefPtr<Node> child = element->firstChild(); child; child = child->nextSibling())
894         expandSymbolElementsInShadowTree(shadowRoot, child.get());
895 }
896
897 #endif
898
899 void SVGUseElement::transferEventListenersToShadowTree(SVGElementInstance* target)
900 {
901     if (!target)
902         return;
903
904     SVGElement* originalElement = target->correspondingElement();
905     ASSERT(originalElement);
906
907     if (SVGElement* shadowTreeElement = target->shadowTreeElement()) {
908         if (EventTargetData* d = originalElement->eventTargetData()) {
909             EventListenerMap& map = d->eventListenerMap;
910             EventListenerMap::iterator end = map.end();
911             for (EventListenerMap::iterator it = map.begin(); it != end; ++it) {
912                 EventListenerVector& entry = *it->second;
913                 for (size_t i = 0; i < entry.size(); ++i) {
914                     // Event listeners created from markup have already been transfered to the shadow tree during cloning.
915                     if (entry[i].listener->wasCreatedFromMarkup())
916                         continue;
917                     shadowTreeElement->addEventListener(it->first, entry[i].listener, entry[i].useCapture);
918                 }
919             }
920         }
921     }
922
923     for (SVGElementInstance* instance = target->firstChild(); instance; instance = instance->nextSibling())
924         transferEventListenersToShadowTree(instance);
925 }
926
927 void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGElementInstance* targetInstance)
928 {
929     if (!target || !targetInstance)
930         return;
931
932     SVGElement* originalElement = targetInstance->correspondingElement();
933
934     if (originalElement->hasTagName(SVGNames::useTag)) {
935 #if ENABLE(SVG) && ENABLE(SVG_USE)
936         // <use> gets replaced by <g>
937         ASSERT(target->nodeName() == SVGNames::gTag);
938 #else 
939         ASSERT(target->nodeName() == SVGNames::gTag || target->nodeName() == SVGNames::useTag);
940 #endif
941     } else if (originalElement->hasTagName(SVGNames::symbolTag)) {
942         // <symbol> gets replaced by <svg>
943 #if ENABLE(SVG) && ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT)
944         ASSERT(target->nodeName() == SVGNames::svgTag);
945 #endif
946     } else
947         ASSERT(target->nodeName() == originalElement->nodeName());
948
949     SVGElement* element = 0;
950     if (target->isSVGElement())
951         element = static_cast<SVGElement*>(target);
952
953     ASSERT(!targetInstance->shadowTreeElement());
954     targetInstance->setShadowTreeElement(element);
955
956     Node* node = target->firstChild();
957     for (SVGElementInstance* instance = targetInstance->firstChild(); node && instance; instance = instance->nextSibling()) {
958         // Skip any non-svg elements in shadow tree
959         while (node && !node->isSVGElement())
960            node = node->nextSibling();
961
962         if (!node)
963             break;
964
965         associateInstancesWithShadowTreeElements(node, instance);
966         node = node->nextSibling();
967     }
968 }
969
970 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element) const
971 {
972     if (!m_targetElementInstance) {
973         ASSERT(!inDocument());
974         return 0;
975     }
976
977     return instanceForShadowTreeElement(element, m_targetElementInstance.get());
978 }
979
980 SVGElementInstance* SVGUseElement::instanceForShadowTreeElement(Node* element, SVGElementInstance* instance) const
981 {
982     ASSERT(element);
983     ASSERT(instance);
984
985     // We're dispatching a mutation event during shadow tree construction
986     // this instance hasn't yet been associated to a shadowTree element.
987     if (!instance->shadowTreeElement())
988         return 0;
989
990     if (element == instance->shadowTreeElement())
991         return instance;
992
993     for (SVGElementInstance* current = instance->firstChild(); current; current = current->nextSibling()) {
994         if (SVGElementInstance* search = instanceForShadowTreeElement(element, current))
995             return search;
996     }
997
998     return 0;
999 }
1000
1001 void SVGUseElement::invalidateShadowTree()
1002 {
1003     // Don't mutate the shadow tree while we're building it.
1004     if (m_updatesBlocked)
1005         return;
1006
1007     m_needsShadowTreeRecreation = true;
1008     setNeedsStyleRecalc();
1009 }
1010
1011 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
1012 {
1013     ASSERT(from);
1014     ASSERT(to);
1015
1016     to->attributes()->setAttributes(*from->attributes());
1017
1018     ExceptionCode ec = 0;
1019
1020     to->removeAttribute(SVGNames::xAttr, ec);
1021     ASSERT(!ec);
1022
1023     to->removeAttribute(SVGNames::yAttr, ec);
1024     ASSERT(!ec);
1025
1026     to->removeAttribute(SVGNames::widthAttr, ec);
1027     ASSERT(!ec);
1028
1029     to->removeAttribute(SVGNames::heightAttr, ec);
1030     ASSERT(!ec);
1031
1032     to->removeAttribute(XLinkNames::hrefAttr, ec);
1033     ASSERT(!ec);
1034 }
1035
1036 bool SVGUseElement::selfHasRelativeLengths() const
1037 {
1038     if (x().isRelative()
1039      || y().isRelative()
1040      || width().isRelative()
1041      || height().isRelative())
1042         return true;
1043
1044     if (!m_targetElementInstance)
1045         return false;
1046
1047     SVGElement* element = m_targetElementInstance->correspondingElement();
1048     if (!element || !element->isStyled())
1049         return false;
1050
1051     return static_cast<SVGStyledElement*>(element)->hasRelativeLengths();
1052 }
1053
1054 }
1055
1056 #endif // ENABLE(SVG)