From 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 19:30:52 -0800 Subject: auto import from //depot/cupcake/@135843 --- WebCore/svg/SVGElementInstance.cpp | 572 +++++++++++++++++++++++++++++++++++++ 1 file changed, 572 insertions(+) create mode 100644 WebCore/svg/SVGElementInstance.cpp (limited to 'WebCore/svg/SVGElementInstance.cpp') diff --git a/WebCore/svg/SVGElementInstance.cpp b/WebCore/svg/SVGElementInstance.cpp new file mode 100644 index 0000000..e548900 --- /dev/null +++ b/WebCore/svg/SVGElementInstance.cpp @@ -0,0 +1,572 @@ +/* + Copyright (C) 2007, 2008 Nikolas Zimmermann + + This file is part of the KDE project + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(SVG) +#include "SVGElementInstance.h" + +#include "ContainerNodeAlgorithms.h" +#include "Document.h" +#include "Event.h" +#include "EventException.h" +#include "EventListener.h" +#include "EventNames.h" +#include "FrameView.h" +#include "GCController.h" +#include "SVGElementInstanceList.h" +#include "SVGUseElement.h" + +#include + +namespace WebCore { + +#ifndef NDEBUG +static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance"); +#endif + +SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement) + : m_needsUpdate(false) + , m_useElement(useElement) + , m_element(originalElement) + , m_previousSibling(0) + , m_nextSibling(0) + , m_firstChild(0) + , m_lastChild(0) +{ + ASSERT(m_useElement); + ASSERT(m_element); + + // Register as instance for passed element. + m_element->mapInstanceToElement(this); + +#ifndef NDEBUG + instanceCounter.increment(); +#endif +} + +SVGElementInstance::~SVGElementInstance() +{ +#ifndef NDEBUG + instanceCounter.decrement(); +#endif + + // Deregister as instance for passed element. + m_element->removeInstanceMapping(this); + + removeAllChildrenInContainer(this); +} + +PassRefPtr SVGElementInstance::childNodes() +{ + return SVGElementInstanceList::create(this); +} + +void SVGElementInstance::setShadowTreeElement(SVGElement* element) +{ + ASSERT(element); + m_shadowTreeElement = element; +} + +void SVGElementInstance::forgetWrapper() +{ + // FIXME: This is fragile, as discussed with Sam. Need to find a better solution. + // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;". + // We still have to recreate this wrapper somehow. The gc collection below, won't catch it. + + // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects + // are still holding RefPtrs of SVGElementInstance objects, which prevent us to + // be deleted (and the shadow tree is not destructed as well). Force JS GC. + gcController().garbageCollectNow(); +} + +void SVGElementInstance::appendChild(PassRefPtr child) +{ + appendChildToContainer(child.get(), this); +} + +void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) +{ + if (!element) + return; + + HashSet set = element->instancesForElement(); + if (set.isEmpty()) + return; + + // Find all use elements referencing the instances - ask them _once_ to rebuild. + HashSet::const_iterator it = set.begin(); + const HashSet::const_iterator end = set.end(); + + for (; it != end; ++it) + (*it)->setNeedsUpdate(true); +} + +void SVGElementInstance::setNeedsUpdate(bool value) +{ + m_needsUpdate = value; + + if (m_needsUpdate) + correspondingUseElement()->setChanged(); +} + +ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const +{ + if (SVGElement* element = correspondingElement()) + return element->scriptExecutionContext(); + return 0; +} + +void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr listener, bool useCapture) +{ + if (SVGElement* element = correspondingElement()) + element->addEventListener(eventType, listener, useCapture); +} + +void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +{ + if (SVGElement* element = correspondingElement()) + element->removeEventListener(eventType, listener, useCapture); +} + +bool SVGElementInstance::dispatchEvent(PassRefPtr e, ExceptionCode& ec) +{ + RefPtr evt(e); + ASSERT(!eventDispatchForbidden()); + if (!evt || evt->type().isEmpty()) { + ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; + return false; + } + + // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()! + SVGElement* element = shadowTreeElement(); + if (!element) + return false; + + evt->setTarget(this); + + RefPtr view = element->document()->view(); + return element->dispatchGenericEvent(evt.release(), ec); +} + +EventListener* SVGElementInstance::onabort() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().abortEvent); +} + +void SVGElementInstance::setOnabort(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().abortEvent, eventListener); +} + +EventListener* SVGElementInstance::onblur() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().blurEvent); +} + +void SVGElementInstance::setOnblur(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().blurEvent, eventListener); +} + +EventListener* SVGElementInstance::onchange() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().changeEvent); +} + +void SVGElementInstance::setOnchange(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().changeEvent, eventListener); +} + +EventListener* SVGElementInstance::onclick() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().clickEvent); +} + +void SVGElementInstance::setOnclick(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().clickEvent, eventListener); +} + +EventListener* SVGElementInstance::oncontextmenu() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().contextmenuEvent); +} + +void SVGElementInstance::setOncontextmenu(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().contextmenuEvent, eventListener); +} + +EventListener* SVGElementInstance::ondblclick() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dblclickEvent); +} + +void SVGElementInstance::setOndblclick(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dblclickEvent, eventListener); +} + +EventListener* SVGElementInstance::onerror() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().errorEvent); +} + +void SVGElementInstance::setOnerror(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().errorEvent, eventListener); +} + +EventListener* SVGElementInstance::onfocus() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().focusEvent); +} + +void SVGElementInstance::setOnfocus(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().focusEvent, eventListener); +} + +EventListener* SVGElementInstance::oninput() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().inputEvent); +} + +void SVGElementInstance::setOninput(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().inputEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeydown() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keydownEvent); +} + +void SVGElementInstance::setOnkeydown(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keydownEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeypress() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keypressEvent); +} + +void SVGElementInstance::setOnkeypress(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keypressEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeyup() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keyupEvent); +} + +void SVGElementInstance::setOnkeyup(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keyupEvent, eventListener); +} + +EventListener* SVGElementInstance::onload() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().loadEvent); +} + +void SVGElementInstance::setOnload(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().loadEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousedown() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousedownEvent); +} + +void SVGElementInstance::setOnmousedown(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousedownEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousemove() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousemoveEvent); +} + +void SVGElementInstance::setOnmousemove(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousemoveEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseout() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseoutEvent); +} + +void SVGElementInstance::setOnmouseout(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseoutEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseover() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseoverEvent); +} + +void SVGElementInstance::setOnmouseover(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseoverEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseup() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseupEvent); +} + +void SVGElementInstance::setOnmouseup(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseupEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousewheel() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousewheelEvent); +} + +void SVGElementInstance::setOnmousewheel(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousewheelEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforecut() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforecutEvent); +} + +void SVGElementInstance::setOnbeforecut(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforecutEvent, eventListener); +} + +EventListener* SVGElementInstance::oncut() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().cutEvent); +} + +void SVGElementInstance::setOncut(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().cutEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforecopy() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforecopyEvent); +} + +void SVGElementInstance::setOnbeforecopy(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforecopyEvent, eventListener); +} + +EventListener* SVGElementInstance::oncopy() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().copyEvent); +} + +void SVGElementInstance::setOncopy(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().copyEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforepaste() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforepasteEvent); +} + +void SVGElementInstance::setOnbeforepaste(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforepasteEvent, eventListener); +} + +EventListener* SVGElementInstance::onpaste() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().pasteEvent); +} + +void SVGElementInstance::setOnpaste(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().pasteEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragenter() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragenterEvent); +} + +void SVGElementInstance::setOndragenter(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragenterEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragover() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragoverEvent); +} + +void SVGElementInstance::setOndragover(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragoverEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragleave() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragleaveEvent); +} + +void SVGElementInstance::setOndragleave(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragleaveEvent, eventListener); +} + +EventListener* SVGElementInstance::ondrop() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dropEvent); +} + +void SVGElementInstance::setOndrop(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dropEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragstart() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragstartEvent); +} + +void SVGElementInstance::setOndragstart(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragstartEvent, eventListener); +} + +EventListener* SVGElementInstance::ondrag() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragEvent); +} + +void SVGElementInstance::setOndrag(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragend() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragendEvent); +} + +void SVGElementInstance::setOndragend(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragendEvent, eventListener); +} + +EventListener* SVGElementInstance::onreset() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().resetEvent); +} + +void SVGElementInstance::setOnreset(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().resetEvent, eventListener); +} + +EventListener* SVGElementInstance::onresize() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().resizeEvent); +} + +void SVGElementInstance::setOnresize(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().resizeEvent, eventListener); +} + +EventListener* SVGElementInstance::onscroll() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().scrollEvent); +} + +void SVGElementInstance::setOnscroll(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().scrollEvent, eventListener); +} + +EventListener* SVGElementInstance::onsearch() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().searchEvent); +} + +void SVGElementInstance::setOnsearch(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().searchEvent, eventListener); +} + +EventListener* SVGElementInstance::onselect() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().selectEvent); +} + +void SVGElementInstance::setOnselect(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().selectEvent, eventListener); +} + +EventListener* SVGElementInstance::onselectstart() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().selectstartEvent); +} + +void SVGElementInstance::setOnselectstart(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().selectstartEvent, eventListener); +} + +EventListener* SVGElementInstance::onsubmit() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().submitEvent); +} + +void SVGElementInstance::setOnsubmit(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().submitEvent, eventListener); +} + +EventListener* SVGElementInstance::onunload() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().unloadEvent); +} + +void SVGElementInstance::setOnunload(PassRefPtr eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().unloadEvent, eventListener); +} + +} + +#endif // ENABLE(SVG) -- cgit v1.1