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