initial import
[vuplus_webkit] / Source / WebCore / svg / SVGElementInstance.cpp
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
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
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     clearChildren();
74 }
75
76 void SVGElementInstance::clearChildren()
77 {
78     removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
79 }
80
81 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
82 {
83     return SVGElementInstanceList::create(this);
84 }
85
86 void SVGElementInstance::setShadowTreeElement(SVGElement* element)
87 {
88     ASSERT(element);
89     m_shadowTreeElement = element;
90 }
91
92 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
93 {
94     appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
95 }
96
97 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
98 {
99     if (!element || !element->inDocument())
100         return;
101
102     if (element->isStyled() && static_cast<SVGStyledElement*>(element)->instanceUpdatesBlocked())
103         return;
104
105     const HashSet<SVGElementInstance*>& set = element->instancesForElement();
106     if (set.isEmpty())
107         return;
108
109     // Mark all use elements referencing 'element' for rebuilding
110     const HashSet<SVGElementInstance*>::const_iterator end = set.end();
111     for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) {
112         ASSERT((*it)->shadowTreeElement());
113         ASSERT((*it)->shadowTreeElement()->correspondingElement());
114         ASSERT((*it)->correspondingElement() == element);
115         (*it)->shadowTreeElement()->setCorrespondingElement(0);
116         if (SVGUseElement* element = (*it)->correspondingUseElement()) {
117             ASSERT(element->inDocument());
118             element->invalidateShadowTree();
119         }
120     }
121
122     // Be sure to rebuild use trees, if needed
123     element->document()->updateLayoutIgnorePendingStylesheets();
124 }
125
126 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
127 {
128     return m_element->document();
129 }
130
131 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
132 {
133     return m_element->addEventListener(eventType, listener, useCapture);
134 }
135
136 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
137 {
138     return m_element->removeEventListener(eventType, listener, useCapture);
139 }
140
141 void SVGElementInstance::removeAllEventListeners()
142 {
143     m_element->removeAllEventListeners();
144 }
145
146 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> event)
147 {
148     SVGElement* element = shadowTreeElement();
149     if (!element)
150         return false;
151
152     return element->dispatchEvent(event);
153 }
154
155 EventTargetData* SVGElementInstance::eventTargetData()
156 {
157     // EventTarget would use these methods if we were actually using its add/removeEventListener logic.
158     // As we're forwarding those calls to the correspondingElement(), no one should ever call this function.
159     ASSERT_NOT_REACHED();
160     return 0;
161 }
162
163 EventTargetData* SVGElementInstance::ensureEventTargetData()
164 {
165     // EventTarget would use these methods if we were actually using its add/removeEventListener logic.
166     // As we're forwarding those calls to the correspondingElement(), no one should ever call this function.
167     ASSERT_NOT_REACHED();
168     return 0;
169 }
170
171 }
172
173 #endif