15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 University of Szeged
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Renata Hodovan <reni@webkit.org>
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGUseElement.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XLinkNames.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
32e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/dom/ElementTraversal.h"
3306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/Event.h"
34e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "core/dom/shadow/ElementShadow.h"
35e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "core/dom/shadow/ShadowRoot.h"
36e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/FetchRequest.h"
37e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/ResourceFetcher.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResource.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGTransformableContainer.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGGElement.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGLengthContext.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGSVGElement.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/parser/XMLDocumentParser.h"
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)inline SVGUseElement::SVGUseElement(Document& document)
4851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    : SVGGraphicsElement(SVGNames::useTag, document)
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , SVGURIReference(this)
5007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
5107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
5207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
5307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_haveFiredLoadEvent(false)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_needsShadowTreeRecreation(false)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(hasCustomStyleCallbacks());
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_x);
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_y);
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_width);
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addToPropertyMap(m_height);
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
66d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)PassRefPtrWillBeRawPtr<SVGUseElement> SVGUseElement::create(Document& document)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
68aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // Always build a user agent #shadow-root for SVGUseElement.
695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    RefPtrWillBeRawPtr<SVGUseElement> use = adoptRefWillBeNoop(new SVGUseElement(document));
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    use->ensureUserAgentShadowRoot();
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return use.release();
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGUseElement::~SVGUseElement()
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
763c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    setDocumentResource(0);
77f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#if !ENABLE(OILPAN)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearResourceReferences();
79f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#endif
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (supportedAttributes.isEmpty()) {
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGURIReference::addSupportedAttributes(supportedAttributes);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::xAttr);
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::yAttr);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::widthAttr);
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        supportedAttributes.add(SVGNames::heightAttr);
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
92591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
97c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    parseAttributeNew(name, value);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool isWellFormedDocument(Document* document)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (document->isXMLDocument())
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return static_cast<XMLDocumentParser*>(document->parser())->wellFormed();
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode* rootParent)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This functions exists to assure assumptions made in the code regarding SVGElementInstance creation/destruction are satisfied.
112591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SVGGraphicsElement::insertedInto(rootParent);
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!rootParent->inDocument())
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return InsertionDone;
1158abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(!m_targetElementInstance || !isWellFormedDocument(&document()));
1168abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(!hasPendingResources() || !isWellFormedDocument(&document()));
117d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    invalidateShadowTree();
118d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!isStructurallyExternal())
119d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        sendSVGLoadEventIfPossibleAsynchronously();
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return InsertionDone;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::removedFrom(ContainerNode* rootParent)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
125591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SVGGraphicsElement::removedFrom(rootParent);
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rootParent->inDocument())
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearResourceReferences();
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13010f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochTreeScope* SVGUseElement::referencedScope() const
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!isExternalURIReference(hrefString(), document()))
13310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return &treeScope();
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return externalDocument();
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Document* SVGUseElement::externalDocument() const
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1393c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (m_resource && m_resource->isLoaded()) {
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Gracefully handle error condition.
1413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        if (m_resource->errorOccurred())
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return 0;
1433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        ASSERT(m_resource->document());
1443c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return m_resource->document();
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
149323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void transferUseWidthAndHeightIfNeeded(const SVGUseElement& use, SVGElement* shadowElement, const SVGElement& originalElement)
150323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    DEFINE_STATIC_LOCAL(const AtomicString, hundredPercentString, ("100%", AtomicString::ConstructFromLiteral));
152323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    ASSERT(shadowElement);
153323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (isSVGSymbolElement(*shadowElement)) {
154323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
155323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // If attributes width and/or height are provided on the 'use' element, then these attributes
156323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
157323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // the generated 'svg' element will use values of 100% for these attributes.
1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        shadowElement->setAttribute(SVGNames::widthAttr, use.width()->isSpecified() ? AtomicString(use.width()->currentValue()->valueAsString()) : hundredPercentString);
1597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        shadowElement->setAttribute(SVGNames::heightAttr, use.height()->isSpecified() ? AtomicString(use.height()->currentValue()->valueAsString()) : hundredPercentString);
160323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    } else if (isSVGSVGElement(*shadowElement)) {
161323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
162323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // values will override the corresponding attributes on the 'svg' in the generated tree.
163323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (use.width()->isSpecified())
164323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            shadowElement->setAttribute(SVGNames::widthAttr, AtomicString(use.width()->currentValue()->valueAsString()));
165323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        else
166323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            shadowElement->setAttribute(SVGNames::widthAttr, originalElement.getAttribute(SVGNames::widthAttr));
167323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (use.height()->isSpecified())
168323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            shadowElement->setAttribute(SVGNames::heightAttr, AtomicString(use.height()->currentValue()->valueAsString()));
169323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        else
170323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            shadowElement->setAttribute(SVGNames::heightAttr, originalElement.getAttribute(SVGNames::heightAttr));
171323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
172323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
173323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSupportedAttribute(attrName)) {
177591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SVGGraphicsElement::svgAttributeChanged(attrName);
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
181323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGElement::InvalidationGuard invalidationGuard(this);
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = this->renderer();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attrName == SVGNames::xAttr
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::yAttr
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::widthAttr
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || attrName == SVGNames::heightAttr) {
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateRelativeLengthsInformation();
189323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        if (m_targetElementInstance) {
190323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            ASSERT(m_targetElementInstance->correspondingElement());
1915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_targetElementInstance->correspondingElement());
192323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        }
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (renderer)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (SVGURIReference::isKnownAttribute(attrName)) {
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        bool isExternalReference = isExternalURIReference(hrefString(), document());
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isExternalReference) {
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            KURL url = document().completeURL(hrefString());
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (url.hasFragmentIdentifier()) {
2037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                FetchRequest request(ResourceRequest(url), localName());
2048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)                setDocumentResource(document().fetcher()->fetchSVGDocument(request));
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2063c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        } else {
2073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            setDocumentResource(0);
2083c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        }
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
210d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        invalidateShadowTree();
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!renderer)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isDisallowedElement(Node* node)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is potentially a template object that can be re-used
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // (i.e., "instanced") in the SVG document via a 'use' element."
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'path', 'polygon', 'polyline', 'rect', 'text'
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Excluded are anything that is used by reference or that only make sense to appear once in a document.
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We must also allow the shadow roots of other use elements.
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node->isShadowRoot() || node->isTextNode())
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node->isSVGElement())
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Element* element = toElement(node);
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ());
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (allowedElementTags.isEmpty()) {
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::aTag);
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::circleTag);
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::descTag);
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::ellipseTag);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::gTag);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::imageTag);
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::lineTag);
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::metadataTag);
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::pathTag);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::polygonTag);
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::polylineTag);
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::rectTag);
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::svgTag);
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::switchTag);
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::symbolTag);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::textTag);
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::textPathTag);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::titleTag);
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::tspanTag);
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        allowedElementTags.add(SVGNames::useTag);
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return !allowedElementTags.contains<SVGAttributeHashTranslator>(element->tagQName());
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool subtreeContainsDisallowedElement(Node* start)
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isDisallowedElement(start))
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) {
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (subtreeContainsDisallowedElement(cur))
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGUseElement::scheduleShadowTreeRecreation()
27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
27710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (!referencedScope() || inUseShadowTree())
27809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
27909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_needsShadowTreeRecreation = true;
28009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    document().scheduleUseShadowTreeUpdate(*this);
28109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
28209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::clearResourceReferences()
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (m_targetElementInstance)
286d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_targetElementInstance = nullptr;
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
288323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // FIXME: We should try to optimize this, to at least allow partial reclones.
289323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (ShadowRoot* shadowTreeRootElement = userAgentShadowRoot())
290323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        shadowTreeRootElement->removeChildren();
291323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_needsShadowTreeRecreation = false;
29309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    document().unscheduleUseShadowTreeUpdate(*this);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    removeAllOutgoingReferences();
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::buildPendingResource()
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
30010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (!referencedScope() || inUseShadowTree())
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearResourceReferences();
303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!inDocument())
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AtomicString id;
30710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id, externalDocument());
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!target || !target->inDocument()) {
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // If we can't find the target of an external element, just give up.
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We can't observe if the target somewhen enters the external document, nor should we do it.
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (externalDocument())
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (id.isEmpty())
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        referencedScope()->document().accessSVGExtensions().addPendingResource(id, this);
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(hasPendingResources());
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (target->isSVGElement()) {
322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        buildShadowAndInstanceTree(toSVGElement(target));
323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        invalidateDependentShadowTrees();
324926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
325926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_needsShadowTreeRecreation);
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static PassRefPtrWillBeRawPtr<Node> cloneNodeAndAssociate(Node& toClone)
3305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles){
3315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    RefPtrWillBeRawPtr<Node> clone = toClone.cloneNode(false);
3325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!clone->isSVGElement())
3335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return clone.release();
3345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
3355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    SVGElement& svgElement = toSVGElement(toClone);
3365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    ASSERT(!svgElement.correspondingElement());
3375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    toSVGElement(clone.get())->setCorrespondingElement(&svgElement);
3385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (EventTargetData* data = toClone.eventTargetData())
3395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(clone.get());
3405d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    TrackExceptionState exceptionState;
3415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Node* node = toClone.firstChild(); node && !exceptionState.hadException(); node = node->nextSibling())
3425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        clone->appendChild(cloneNodeAndAssociate(*node), exceptionState);
3435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return clone.release();
3445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
3455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!m_targetElementInstance);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
350aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // <use> creates a "user agent" shadow root. Do not build the shadow/instance tree for <use>
351aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // elements living in a user agent shadow tree because they will get expanded in a second
352aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // pass -- see expandUseElementsInShadowTree().
35310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (inUseShadowTree())
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Do not allow self-referencing.
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 'target' may be null, if it's a non SVG namespaced element.
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!target || target == this)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Set up root SVG element in shadow tree.
3625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren();
3635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    m_targetElementInstance = toSVGElement(newChild.get());
3645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    ShadowRoot* shadowTreeRootElement = userAgentShadowRoot();
3655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    shadowTreeRootElement->appendChild(newChild.release());
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Clone the target subtree into the shadow tree, not handling <use> and <symbol> yet.
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Non-appearing <use> content is easier to debug, then half-appearing content.
3715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!buildShadowTree(target, m_targetElementInstance.get(), false)) {
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearResourceReferences();
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (instanceTreeIsLoading(m_targetElementInstance.get()))
3775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return;
3785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
3795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Assure shadow tree building was successfull
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_targetElementInstance);
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_targetElementInstance->correspondingUseElement() == this);
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_targetElementInstance->correspondingElement() == target);
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Expand all <use> elements in the shadow tree.
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Expand means: replace the actual <use> element by what it references.
3865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) {
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearResourceReferences();
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Expand all <symbol> elements in the shadow tree.
3925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Expand means: replace the actual <symbol> element by the <svg> element.
3935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstChild()));
394323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
3955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild());
3965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_targetElementInstance->correspondingElement());
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement);
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Update relative length information.
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateRelativeLengthsInformation();
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
404591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochRenderObject* SVGUseElement::createRenderer(RenderStyle*)
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
406f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return new RenderSVGTransformableContainer(this);
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
409c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static bool isDirectReference(const SVGElement& element)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
411c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return isSVGPathElement(element)
412c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGRectElement(element)
413c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGCircleElement(element)
414c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGEllipseElement(element)
415c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGPolygonElement(element)
416c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGPolylineElement(element)
417c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        || isSVGTextElement(element);
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::toClipPath(Path& path)
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(path.isEmpty());
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
424323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    Node* n = userAgentShadowRoot()->firstChild();
425c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!n || !n->isSVGElement())
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
427c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SVGElement& element = toSVGElement(*n);
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
429c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (element.isSVGGraphicsElement()) {
430c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (!isDirectReference(element)) {
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Spec: Indirect references are an error (14.3.5)
432d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            document().accessSVGExtensions().reportError("Not allowed to use indirect reference in <clip-path>");
4338abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        } else {
434c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            toSVGGraphicsElement(element).toClipPath(path);
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SVGLengthContext lengthContext(this);
43709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            path.translate(FloatSize(m_x->currentValue()->value(lengthContext), m_y->currentValue()->value(lengthContext)));
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            path.transform(animatedLocalTransform());
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderObject* SVGUseElement::rendererClipChild() const
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
445323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (Node* n = userAgentShadowRoot()->firstChild()) {
446c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (n->isSVGElement() && isDirectReference(toSVGElement(*n)))
447c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            return n->renderer();
448323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    }
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool SVGUseElement::buildShadowTree(SVGElement* target, SVGElement* targetInstance, bool foundUse)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(target);
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(targetInstance);
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: If the referenced object is itself a 'use', or if there are 'use' subelements within the referenced
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // object, the instance tree will contain recursive expansion of the indirect references to form a complete tree.
4605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (isSVGUseElement(*target)) {
461926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // We only need to track first degree <use> dependencies. Indirect references are handled
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // as the invalidation bubbles up the dependency chain.
463197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!foundUse && !isStructurallyExternal()) {
464197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            addReferenceTo(target);
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            foundUse = true;
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else if (isDisallowedElement(target)) {
4685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return false;
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    targetInstance->setCorrespondingElement(target);
4725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (EventTargetData* data = target->eventTargetData())
4735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        data->eventListenerMap.copyEventListenersNotCreatedFromMarkupToTarget(targetInstance);
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (Node* child = target->firstChild(); child; child = child->nextSibling()) {
47643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        // Skip any disallowed element.
4775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (isDisallowedElement(child))
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false);
4815d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        targetInstance->appendChild(newChild.get());
4825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (newChild->isSVGElement()) {
4835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // Enter recursion, appending new instance tree nodes to the "instance" object.
4845d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            if (!buildShadowTree(toSVGElement(child), toSVGElement(newChild), foundUse))
4855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                return false;
4865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return true;
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, ContainerNode* targetInstance, SVGElement*& newTarget)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
49310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    ASSERT(referencedScope());
49410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    Element* targetElement = SVGURIReference::targetElementFromIRIString(use->hrefString(), *referencedScope());
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newTarget = 0;
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (targetElement && targetElement->isSVGElement())
497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        newTarget = toSVGElement(targetElement);
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!newTarget)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Shortcut for self-references
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newTarget == this)
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AtomicString targetId = newTarget->getIdAttribute();
5075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    ContainerNode* instance = targetInstance->parentNode();
5085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    while (instance && instance->isSVGElement()) {
5095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        SVGElement* element = toSVGElement(instance);
5101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        if (element->hasID() && element->getIdAttribute() == targetId && element->document() == newTarget->document())
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        instance = instance->parentNode();
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
51851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static inline void removeDisallowedElementsFromSubtree(Element& subtree)
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
52051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    ASSERT(!subtree.inDocument());
521926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Element* element = ElementTraversal::firstWithin(subtree);
522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (element) {
523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (isDisallowedElement(element)) {
52451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            Element* next = ElementTraversal::nextSkippingChildren(*element, &subtree);
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // The subtree is not in document so this won't generate events that could mutate the tree.
526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            element->parentNode()->removeChild(element);
527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            element = next;
52851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        } else {
52951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            element = ElementTraversal::next(*element, &subtree);
53051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool SVGUseElement::expandUseElementsInShadowTree(SVGElement* element)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
536d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(element);
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Why expand the <use> elements in the shadow tree here, and not just
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // do this directly in buildShadowTree, if we encounter a <use> element?
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //
540aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // Short answer: Because we may miss to expand some elements. For example, if a <symbol>
541aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    // contains <use> tags, we'd miss them. So once we're done with setting up the
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // actual shadow tree (after the special case modification for svg/symbol) we have
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // to walk it completely and expand all <use> elements.
544d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isSVGUseElement(*element)) {
5457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        SVGUseElement* use = toSVGUseElement(element);
5463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        ASSERT(!use->resourceIsStillLoading());
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGElement* target = 0;
5495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (hasCycleUseReferencing(toSVGUseElement(use->correspondingElement()), use, target))
5505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return false;
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (target && isDisallowedElement(target))
5535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return false;
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Don't ASSERT(target) here, it may be "pending", too.
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Setup sub-shadow tree root node
556d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(referencedScope()->document());
5575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        cloneParent->setCorrespondingElement(use->correspondingElement());
5585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
5595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // Move already cloned elements to the new <g> element
5605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        for (Node* child = use->firstChild(); child; ) {
5615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            Node* nextChild = child->nextSibling();
5625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            cloneParent->appendChild(child);
5635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            child = nextChild;
5645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: In the generated content, the 'use' will be replaced by 'g', where all attributes from the
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // 'use' element except for x, y, width, height and xlink:href are transferred to the generated 'g' element.
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        transferUseAttributesToReplacedElement(use, cloneParent.get());
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (target) {
5715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            RefPtrWillBeRawPtr<Node> newChild = cloneNodeAndAssociate(*target);
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(newChild->isSVGElement());
573323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            transferUseWidthAndHeightIfNeeded(*use, toSVGElement(newChild.get()), *target);
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            cloneParent->appendChild(newChild.release());
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We don't walk the target tree element-by-element, and clone each element,
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // but instead use cloneElementWithChildren(). This is an optimization for the common
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Though if there are disallowed elements in the subtree, we have to remove them.
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For instance: <use> on <g> containing <foreignObject> (indirect case).
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (subtreeContainsDisallowedElement(cloneParent.get()))
58351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            removeDisallowedElementsFromSubtree(*cloneParent);
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get());
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Replace <use> with referenced content.
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(use->parentNode());
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        use->parentNode()->replaceChild(cloneParent.release(), use);
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Expand the siblings because the *element* is replaced and we will
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // lose the sibling chain when we are back from recursion.
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        element = replacingElement.get();
5945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        for (RefPtrWillBeRawPtr<SVGElement> sibling = Traversal<SVGElement>::nextSibling(*element); sibling; sibling = Traversal<SVGElement>::nextSibling(*sibling)) {
5955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            if (!expandUseElementsInShadowTree(sibling.get()))
5965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                return false;
5975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChild(*element); child; child = Traversal<SVGElement>::nextSibling(*child)) {
6015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (!expandUseElementsInShadowTree(child.get()))
6025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return false;
6035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
6045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return true;
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void SVGUseElement::expandSymbolElementsInShadowTree(SVGElement* element)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
609d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(element);
610d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (isSVGSymbolElement(*element)) {
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: The referenced 'symbol' and its contents are deep-cloned into the generated tree,
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // with the exception that the 'symbol' is replaced by an 'svg'. This generated 'svg' will
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // always have explicit values for attributes width and height. If attributes width and/or
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // height are provided on the 'use' element, then these attributes will be transferred to
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // the generated 'svg'. If attributes width and/or height are not specified, the generated
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // 'svg' element will use values of 100% for these attributes.
61710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        ASSERT(referencedScope());
618d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(referencedScope()->document());
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Transfer all data (attributes, etc.) from <symbol> to the new <svg> element.
6205d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        svgElement->cloneDataFromElement(*element);
6215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        svgElement->setCorrespondingElement(element->correspondingElement());
6225d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
6235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // Move already cloned elements to the new <svg> element
6245d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        for (Node* child = element->firstChild(); child; ) {
6255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            Node* nextChild = child->nextSibling();
6265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            svgElement->appendChild(child);
6275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            child = nextChild;
6285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We don't walk the target tree element-by-element, and clone each element,
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // but instead use cloneNode(deep=true). This is an optimization for the common
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // case where <use> doesn't contain disallowed elements (ie. <foreignObject>).
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Though if there are disallowed elements in the subtree, we have to remove them.
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For instance: <use> on <g> containing <foreignObject> (indirect case).
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (subtreeContainsDisallowedElement(svgElement.get()))
63651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            removeDisallowedElementsFromSubtree(*svgElement);
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get());
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Replace <symbol> with <svg>.
6415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        ASSERT(element->parentNode());
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        element->parentNode()->replaceChild(svgElement.release(), element);
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Expand the siblings because the *element* is replaced and we will
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // lose the sibling chain when we are back from recursion.
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        element = replacingElement.get();
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (RefPtrWillBeRawPtr<SVGElement> child = Traversal<SVGElement>::firstChild(*element); child; child = Traversal<SVGElement>::nextSibling(*child))
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        expandSymbolElementsInShadowTree(child.get());
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::invalidateShadowTree()
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
65519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)    if (!inActiveDocument() || m_needsShadowTreeRecreation)
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
65709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    scheduleShadowTreeRecreation();
658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    invalidateDependentShadowTrees();
659926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
661926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SVGUseElement::invalidateDependentShadowTrees()
662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Recursively invalidate dependent <use> shadow trees
664323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >& instances = instancesForElement();
665323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    const WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = instances.end();
666323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    for (WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = instances.begin(); it != end; ++it) {
667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ASSERT(element->inDocument());
669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            element->invalidateShadowTree();
670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
671926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(from);
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(to);
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->cloneDataFromElement(*from);
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->removeAttribute(SVGNames::xAttr);
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->removeAttribute(SVGNames::yAttr);
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->removeAttribute(SVGNames::widthAttr);
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->removeAttribute(SVGNames::heightAttr);
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    to->removeAttribute(XLinkNames::hrefAttr);
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGUseElement::selfHasRelativeLengths() const
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
69009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_x->currentValue()->isRelative()
69109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_y->currentValue()->isRelative()
69209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_width->currentValue()->isRelative()
69309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        || m_height->currentValue()->isRelative())
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_targetElementInstance)
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_targetElementInstance->hasRelativeLengths();
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
702fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid SVGUseElement::notifyFinished(Resource* resource)
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!inDocument())
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    invalidateShadowTree();
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (resource->errorOccurred())
7091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        dispatchEvent(Event::create(EventTypeNames::error));
71009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    else if (!resource->wasCanceled()) {
711d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (m_haveFiredLoadEvent)
71209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return;
71309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!isStructurallyExternal())
71409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return;
71509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ASSERT(!m_haveFiredLoadEvent);
71609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_haveFiredLoadEvent = true;
717d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        sendSVGLoadEventIfPossibleAsynchronously();
71809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochbool SVGUseElement::resourceIsStillLoading()
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7233c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (m_resource && m_resource->isLoading())
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool SVGUseElement::instanceTreeIsLoading(SVGElement* targetInstance)
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    for (SVGElement* element = Traversal<SVGElement>::firstChild(*targetInstance); element; element = Traversal<SVGElement>::nextSibling(*element)) {
7315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (SVGUseElement* use = element->correspondingUseElement()) {
7323c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            if (use->resourceIsStillLoading())
7333c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch                return true;
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (element->hasChildren() && instanceTreeIsLoading(element))
7365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return true;
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid SVGUseElement::setDocumentResource(ResourcePtr<DocumentResource> resource)
742926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
7433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (m_resource == resource)
744926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
745926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (m_resource)
7473c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        m_resource->removeClient(this);
748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_resource = resource;
7503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (m_resource)
7513c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        m_resource->addClient(this);
752926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
753926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
754323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void SVGUseElement::trace(Visitor* visitor)
755323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
756323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    visitor->trace(m_targetElementInstance);
757323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    SVGGraphicsElement::trace(visitor);
758323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
759323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
761