2 Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
4 This file is part of the KDE project
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.
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.
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.
23 #include "wtf/Platform.h"
26 #include "SVGElementInstance.h"
29 #include "EventListener.h"*/
30 #include "SVGElementInstanceList.h"
31 #include "SVGUseElement.h"
33 #include <wtf/Assertions.h>
37 SVGElementInstance::SVGElementInstance(SVGUseElement
* useElement
, PassRefPtr
<SVGElement
> originalElement
)
40 , m_useElement(useElement
)
41 , m_element(originalElement
)
42 , m_shadowTreeElement(0)
43 , m_previousSibling(0)
51 // Register as instance for passed element.
52 m_element
->document()->accessSVGExtensions()->mapInstanceToElement(this, m_element
.get());
55 SVGElementInstance::~SVGElementInstance()
57 for (RefPtr
<SVGElementInstance
> child
= m_firstChild
; child
; child
= child
->m_nextSibling
)
60 // Deregister as instance for passed element.
61 m_element
->document()->accessSVGExtensions()->removeInstanceMapping(this, m_element
.get());
64 SVGElement
* SVGElementInstance::correspondingElement() const
66 return m_element
.get();
69 SVGUseElement
* SVGElementInstance::correspondingUseElement() const
74 SVGElementInstance
* SVGElementInstance::parentNode() const
79 PassRefPtr
<SVGElementInstanceList
> SVGElementInstance::childNodes()
81 return SVGElementInstanceList::create(this);
84 SVGElementInstance
* SVGElementInstance::previousSibling() const
86 return m_previousSibling
;
89 SVGElementInstance
* SVGElementInstance::nextSibling() const
94 SVGElementInstance
* SVGElementInstance::firstChild() const
99 SVGElementInstance
* SVGElementInstance::lastChild() const
104 SVGElement
* SVGElementInstance::shadowTreeElement() const
106 return m_shadowTreeElement
;
109 void SVGElementInstance::setShadowTreeElement(SVGElement
* element
)
112 m_shadowTreeElement
= element
;
115 void SVGElementInstance::appendChild(PassRefPtr
<SVGElementInstance
> child
)
117 child
->setParent(this);
120 child
->m_previousSibling
= m_lastChild
;
121 m_lastChild
->m_nextSibling
= child
.get();
123 m_firstChild
= child
.get();
125 m_lastChild
= child
.get();
128 // Helper function for updateInstance
129 static bool containsUseChildNode(Node
* start
)
131 if (start
->hasTagName(SVGNames::useTag
))
134 for (Node
* current
= start
->firstChild(); current
; current
= current
->nextSibling()) {
135 if (containsUseChildNode(current
))
142 void SVGElementInstance::updateInstance(SVGElement
* element
)
144 ASSERT(element
== m_element
);
145 ASSERT(m_shadowTreeElement
);
147 // TODO: Eventually come up with a more optimized updating logic for the cases below:
149 // <symbol>: We can't just clone the original element, we need to apply
150 // the same "replace by generated content" logic that SVGUseElement does.
152 // <svg>: <use> on <svg> is too rare to actually implement it faster.
153 // If someone still wants to do it: recloning, adjusting width/height attributes is enough.
155 // <use>: Too hard to get it right in a fast way. Recloning seems the only option.
157 if (m_element
->hasTagName(SVGNames::symbolTag
) ||
158 m_element
->hasTagName(SVGNames::svgTag
) ||
159 containsUseChildNode(m_element
.get())) {
160 m_useElement
->buildPendingResource();
164 // For all other nodes this logic is sufficient.
165 WTF::PassRefPtr
<Node
> clone
= m_element
->cloneNode(true);
166 SVGUseElement::removeDisallowedElementsFromSubtree(clone
.get());
167 SVGElement
* svgClone
= 0;
168 if (clone
&& clone
->isSVGElement())
169 svgClone
= static_cast<SVGElement
*>(clone
.get());
172 // Replace node in the <use> shadow tree
173 /*ExceptionCode*//*khtml*/int ec
= 0;
174 m_shadowTreeElement
->parentNode()->replaceChild(clone
.releaseRef(), m_shadowTreeElement
, ec
);
177 m_shadowTreeElement
= svgClone
;
180 SVGElementInstance
* SVGElementInstance::toSVGElementInstance()
185 EventTargetNode
* SVGElementInstance::toNode()
187 return m_element
.get();
190 void SVGElementInstance::addEventListener(const AtomicString
& eventType
, PassRefPtr
<EventListener
> eventListener
, bool useCapture
)
195 void SVGElementInstance::removeEventListener(const AtomicString
& eventType
, EventListener
* eventListener
, bool useCapture
)
200 bool SVGElementInstance::dispatchEvent(PassRefPtr
<Event
>, ExceptionCode
& ec
, bool tempEvent
)
208 #endif // ENABLE(SVG)