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 38namespace WebCore { 39 40#ifndef NDEBUG 41static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance"); 42#endif 43 44SVGElementInstance::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 64SVGElementInstance::~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 76PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() 77{ 78 return SVGElementInstanceList::create(this); 79} 80 81void SVGElementInstance::setShadowTreeElement(SVGElement* element) 82{ 83 ASSERT(element); 84 m_shadowTreeElement = element; 85} 86 87void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) 88{ 89 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); 90} 91 92void 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 116ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const 117{ 118 return m_element->document(); 119} 120 121bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 122{ 123 return m_element->addEventListener(eventType, listener, useCapture); 124} 125 126bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 127{ 128 return m_element->removeEventListener(eventType, listener, useCapture); 129} 130 131void SVGElementInstance::removeAllEventListeners() 132{ 133 m_element->removeAllEventListeners(); 134} 135 136bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> event) 137{ 138 SVGElement* element = shadowTreeElement(); 139 if (!element) 140 return false; 141 142 return element->dispatchEvent(event); 143} 144 145EventTargetData* 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 153EventTargetData* 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