1 /*
2 * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
4 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. 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 "SVGElementInstance.h"
26
27 #include "ContainerNodeAlgorithms.h"
28 #include "Event.h"
29 #include "EventException.h"
30 #include "EventListener.h"
31 #include "EventNames.h"
32 #include "FrameView.h"
33 #include "SVGElementInstanceList.h"
34 #include "SVGUseElement.h"
35
36 #include <wtf/RefCountedLeakCounter.h>
37
38 namespace WebCore {
39
40 #ifndef NDEBUG
41 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
42 #endif
43
SVGElementInstance(SVGUseElement * correspondingUseElement,SVGUseElement * directUseElement,PassRefPtr<SVGElement> originalElement)44 SVGElementInstance::SVGElementInstance(SVGUseElement* correspondingUseElement, SVGUseElement* directUseElement, PassRefPtr<SVGElement> originalElement)
45 : m_correspondingUseElement(correspondingUseElement)
46 , m_directUseElement(directUseElement)
47 , m_element(originalElement)
48 , m_previousSibling(0)
49 , m_nextSibling(0)
50 , m_firstChild(0)
51 , m_lastChild(0)
52 {
53 ASSERT(m_correspondingUseElement);
54 ASSERT(m_element);
55
56 // Register as instance for passed element.
57 m_element->mapInstanceToElement(this);
58
59 #ifndef NDEBUG
60 instanceCounter.increment();
61 #endif
62 }
63
~SVGElementInstance()64 SVGElementInstance::~SVGElementInstance()
65 {
66 #ifndef NDEBUG
67 instanceCounter.decrement();
68 #endif
69
70 // Deregister as instance for passed element.
71 m_element->removeInstanceMapping(this);
72
73 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
74 }
75
childNodes()76 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
77 {
78 return SVGElementInstanceList::create(this);
79 }
80
setShadowTreeElement(SVGElement * element)81 void SVGElementInstance::setShadowTreeElement(SVGElement* element)
82 {
83 ASSERT(element);
84 m_shadowTreeElement = element;
85 }
86
appendChild(PassRefPtr<SVGElementInstance> child)87 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
88 {
89 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
90 }
91
invalidateAllInstancesOfElement(SVGElement * element)92 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
93 {
94 if (!element || !element->inDocument())
95 return;
96
97 if (element->isStyled() && static_cast<SVGStyledElement*>(element)->instanceUpdatesBlocked())
98 return;
99
100 const HashSet<SVGElementInstance*>& set = element->instancesForElement();
101 if (set.isEmpty())
102 return;
103
104 // Mark all use elements referencing 'element' for rebuilding
105 const HashSet<SVGElementInstance*>::const_iterator end = set.end();
106 for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) {
107 ASSERT((*it)->correspondingElement() == element);
108 if (SVGUseElement* element = (*it)->correspondingUseElement())
109 element->invalidateShadowTree();
110 }
111
112 // Be sure to rebuild use trees, if needed
113 element->document()->updateLayoutIgnorePendingStylesheets();
114 }
115
scriptExecutionContext() const116 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
117 {
118 return m_element->document();
119 }
120
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)121 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
122 {
123 return m_element->addEventListener(eventType, listener, useCapture);
124 }
125
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)126 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
127 {
128 return m_element->removeEventListener(eventType, listener, useCapture);
129 }
130
removeAllEventListeners()131 void SVGElementInstance::removeAllEventListeners()
132 {
133 m_element->removeAllEventListeners();
134 }
135
dispatchEvent(PassRefPtr<Event> event)136 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> event)
137 {
138 SVGElement* element = shadowTreeElement();
139 if (!element)
140 return false;
141
142 return element->dispatchEvent(event);
143 }
144
eventTargetData()145 EventTargetData* SVGElementInstance::eventTargetData()
146 {
147 // EventTarget would use these methods if we were actually using its add/removeEventListener logic.
148 // As we're forwarding those calls to the correspondingElement(), no one should ever call this function.
149 ASSERT_NOT_REACHED();
150 return 0;
151 }
152
ensureEventTargetData()153 EventTargetData* SVGElementInstance::ensureEventTargetData()
154 {
155 // EventTarget would use these methods if we were actually using its add/removeEventListener logic.
156 // As we're forwarding those calls to the correspondingElement(), no one should ever call this function.
157 ASSERT_NOT_REACHED();
158 return 0;
159 }
160
161 }
162
163 #endif
164