1 /* 2 * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) 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 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this); 74 } 75 76 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() 77 { 78 return SVGElementInstanceList::create(this); 79 } 80 81 void SVGElementInstance::setShadowTreeElement(SVGElement* element) 82 { 83 ASSERT(element); 84 m_shadowTreeElement = element; 85 } 86 87 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) 88 { 89 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); 90 } 91 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 116 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const 117 { 118 return m_element->document(); 119 } 120 121 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 122 { 123 return m_element->addEventListener(eventType, listener, useCapture); 124 } 125 126 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 127 { 128 return m_element->removeEventListener(eventType, listener, useCapture); 129 } 130 131 void SVGElementInstance::removeAllEventListeners() 132 { 133 m_element->removeAllEventListeners(); 134 } 135 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 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 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