OSDN Git Service

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