• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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