summaryrefslogtreecommitdiffstats
path: root/ksvg/impl/SVGElementImpl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ksvg/impl/SVGElementImpl.cc')
-rw-r--r--ksvg/impl/SVGElementImpl.cc713
1 files changed, 713 insertions, 0 deletions
diff --git a/ksvg/impl/SVGElementImpl.cc b/ksvg/impl/SVGElementImpl.cc
new file mode 100644
index 00000000..2f3d70c6
--- /dev/null
+++ b/ksvg/impl/SVGElementImpl.cc
@@ -0,0 +1,713 @@
+/*
+ Copyright (C) 2001-2003 KSVG Team
+ 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 <qxml.h>
+
+#include <kdebug.h>
+
+#include "SVGEvent.h"
+#include "SVGEventImpl.h"
+#include "SVGHelperImpl.h"
+#include "SVGElementImpl.h"
+#include "SVGDocumentImpl.h"
+#include "SVGSVGElementImpl.h"
+
+using namespace KSVG;
+
+#include "SVGElementImpl.lut.h"
+#include "ksvg_scriptinterpreter.h"
+#include "ksvg_ecma.h"
+
+SVGElementImpl::Factory *SVGElementImpl::Factory::m_instance = 0;
+
+SVGElementImpl::SVGElementImpl(DOM::ElementImpl *impl) : DOM::DomShared(), DOM::Element(impl), SVGDOMElementBridge(static_cast<DOM::Element>(*this))
+{
+ KSVG_EMPTY_FLAGS
+
+ m_ownerSVGElement = 0;
+ m_viewportElement = 0;
+ m_ownerDoc = 0;
+
+ m_mouseOver = false;
+ m_focus = false;
+
+ m_eventListeners.setAutoDelete(true);
+ m_attributes.setAutoDelete(true);
+}
+
+SVGElementImpl::~SVGElementImpl()
+{
+ if(m_ownerSVGElement)
+ m_ownerSVGElement->deref();
+}
+
+void SVGElementImpl::setEventListener(int id, SVGEventListener *listener)
+{
+ if(listener)
+ listener->ref();
+
+ removeEventListener(id);
+
+ if(listener)
+ {
+ SVGRegisteredEventListener *rl = new SVGRegisteredEventListener(static_cast<SVGEvent::EventId>(id), listener, false);
+ m_eventListeners.append(rl);
+
+ listener->deref();
+ }
+}
+
+int SVGElementImpl::getEventListeners(bool local)
+{
+ int events = 0;
+
+ QPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
+ for(; it.current(); ++it)
+ events |= (1 << it.current()->id);
+
+ if(local)
+ return events;
+
+ for(DOM::Node node = parentNode(); !node.isNull(); node = node.parentNode())
+ {
+ SVGElementImpl *element = ownerDoc()->getElementFromHandle(node.handle());
+
+ if(element)
+ {
+ QPtrListIterator<SVGRegisteredEventListener> it(element->m_eventListeners);
+ for(; it.current(); ++it)
+ events |= (1 << it.current()->id);
+ }
+ }
+
+ return events;
+}
+
+void SVGElementImpl::setupEventListeners(SVGDocumentImpl *doc, SVGDocumentImpl *newDoc)
+{
+ if(!doc || !newDoc)
+ return;
+
+ // Changes the document where the eventlisteners are registered
+ // Needed for parseXML'ed elements with events, their listeners
+ // are created in the temporary document fragment and need to be
+ // registered in the main document (Niko)
+ QPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
+ for(; it.current(); ++it)
+ {
+ SVGRegisteredEventListener *current = it.current();
+
+ QString valueOfCurrent = newDoc->ecmaEngine()->valueOfEventListener(current->listener);
+ setEventListener(current->id, doc->createEventListener(valueOfCurrent));
+ }
+}
+
+bool SVGElementImpl::hasEventListener(int id, bool local)
+{
+ // First check if we have the listener, locally
+ QPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
+ for(; it.current(); ++it)
+ {
+ if(it.current()->id == id)
+ return true;
+ }
+
+ // We have no local listeners, if we are just interessted
+ // in those listeners, then return now...
+ if(local)
+ return false;
+
+ // Check every parent element
+ for(DOM::Node node = parentNode(); !node.isNull(); node = node.parentNode())
+ {
+ SVGElementImpl *element = ownerDoc()->getElementFromHandle(node.handle());
+
+ if(element)
+ {
+ QPtrListIterator<SVGRegisteredEventListener> it(element->m_eventListeners);
+ for(; it.current(); ++it)
+ {
+ if(it.current()->id == id)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void SVGElementImpl::removeEventListener(int id)
+{
+ QPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
+ for(; it.current(); ++it)
+ {
+ if(it.current()->id == id)
+ {
+ m_eventListeners.removeRef(it.current());
+ break;
+ }
+ }
+}
+
+void SVGElementImpl::handleLocalEvents(SVGEventImpl *evt, bool useCapture)
+{
+ QPtrListIterator<SVGRegisteredEventListener> it(m_eventListeners);
+ for(; it.current(); ++it)
+ {
+ if(it.current()->id == evt->id() && it.current()->useCapture == useCapture)
+ {
+ it.current()->listener->handleEvent(evt);
+ break;
+ }
+ }
+}
+
+void SVGElementImpl::defaultEventHandler(SVGEventImpl *)
+{
+}
+
+/*
+@namespace KSVG
+@begin SVGElementImpl::s_hashTable 23
+ id SVGElementImpl::ElementId DontDelete
+ ownerSVGElement SVGElementImpl::OwnerSvgElement DontDelete|ReadOnly
+ viewportElement SVGElementImpl::ViewportElement DontDelete|ReadOnly
+ xmlbase SVGElementImpl::XmlBase DontDelete
+ base SVGElementImpl::XmlBase DontDelete
+ onmouseup SVGElementImpl::OnMouseUp DontDelete
+ onmousedown SVGElementImpl::OnMouseDown DontDelete
+ onmousemove SVGElementImpl::OnMouseMove DontDelete
+ onmouseover SVGElementImpl::OnMouseOver DontDelete
+ onmouseout SVGElementImpl::OnMouseOut DontDelete
+ onclick SVGElementImpl::OnClick DontDelete
+ onmouseclick SVGElementImpl::OnClick DontDelete
+ onactivate SVGElementImpl::OnActivate DontDelete
+ onkeydown SVGElementImpl::OnKeyDown DontDelete
+ onkeyup SVGElementImpl::OnKeyUp DontDelete
+ onkeypress SVGElementImpl::OnKeyPress DontDelete
+ onload SVGElementImpl::OnLoad DontDelete
+ onfocusin SVGElementImpl::OnFocusIn DontDelete
+ onfocusout SVGElementImpl::OnFocusOut DontDelete
+ onerror SVGElementImpl::OnError DontDelete
+ onabort SVGElementImpl::OnAbort DontDelete
+@end
+@namespace KSVG
+@begin SVGElementImplProto::s_hashTable 5
+ getStyle SVGElementImpl::GetStyle DontDelete|Function 0
+ setProperty SVGElementImpl::SetProperty DontDelete|Function 2
+ getPropertyValue SVGElementImpl::GetPropertyValue DontDelete|Function 1
+@end
+*/
+
+KSVG_IMPLEMENT_PROTOTYPE("SVGElement", SVGElementImplProto, SVGElementImplProtoFunc)
+
+Value SVGElementImpl::getValueProperty(ExecState *exec, int token) const
+{
+ switch(token)
+ {
+ case ElementId:
+ return String(id().string());
+ case XmlBase:
+ return String(xmlbase().string());
+ case OwnerSvgElement:
+ return getDOMNode(exec, *ownerSVGElement());
+ case ViewportElement:
+ return getDOMNode(exec, *viewportElement());
+ default:
+ kdWarning() << "Unhandled token in " << k_funcinfo << " : " << token << endl;
+ return Undefined();
+ }
+}
+
+void SVGElementImpl::putValueProperty(ExecState *exec, int token, const Value &value, int)
+{
+ switch(token)
+ {
+ case ElementId:
+ setId(value.toString(exec).string());
+ break;
+ case XmlBase:
+ setXmlbase(value.toString(exec).string());
+ break;
+ case OnMouseUp:
+ setEventListener(SVGEvent::MOUSEUP_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnMouseDown:
+ setEventListener(SVGEvent::MOUSEDOWN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnMouseMove:
+ setEventListener(SVGEvent::MOUSEMOVE_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnMouseOver:
+ setEventListener(SVGEvent::MOUSEOVER_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnMouseOut:
+ setEventListener(SVGEvent::MOUSEOUT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnClick:
+ setEventListener(SVGEvent::CLICK_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnActivate:
+ setEventListener(SVGEvent::DOMACTIVATE_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnKeyDown:
+ setEventListener(SVGEvent::KEYDOWN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnKeyUp:
+ setEventListener(SVGEvent::KEYUP_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnKeyPress:
+ setEventListener(SVGEvent::KEYPRESS_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnLoad:
+ setEventListener(SVGEvent::LOAD_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnFocusIn:
+ setEventListener(SVGEvent::DOMFOCUSIN_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnFocusOut:
+ setEventListener(SVGEvent::DOMFOCUSOUT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnError:
+ setEventListener(SVGEvent::ERROR_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ case OnAbort:
+ setEventListener(SVGEvent::ABORT_EVENT, m_ownerDoc->createEventListener(value.toString(exec).string()));
+ break;
+ default:
+ kdWarning() << k_funcinfo << "unhandled token " << token << endl;
+ }
+}
+
+Value SVGElementImplProtoFunc::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ KSVG_CHECK_THIS(SVGElementImpl)
+
+ switch(id)
+ {
+ case SVGElementImpl::GetStyle:
+ return obj->cache(exec);
+ case SVGElementImpl::SetProperty:
+ {
+ DOM::DOMString attribute = args[0].toString(exec).qstring().lower();
+ DOM::DOMString value = args[1].toString(exec).qstring();
+ obj->setAttribute(attribute, value);
+ break;
+ }
+ case SVGElementImpl::GetPropertyValue:
+ return String(obj->getAttribute(args[0].toString(exec).qstring()));
+ default:
+ break;
+ }
+
+ return Undefined();
+}
+
+QDict<DOM::DOMString> &SVGElementImpl::attributes()
+{
+ return m_attributes;
+}
+
+// khtml overrides
+void SVGElementImpl::setAttribute(const DOM::DOMString &name, const DOM::DOMString &value)
+{
+ m_attributes.replace(name.string(), new DOM::DOMString(value));
+}
+
+// Changes internal value. This will have no effect on getAttribute().
+void SVGElementImpl::setAttributeInternal(const DOM::DOMString &name, const DOM::DOMString &value)
+{
+ ExecState *exec = ownerDoc()->ecmaEngine()->globalExec();
+
+ static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeSetMode(true);
+ bridge(exec)->put(exec, Identifier(UString(name)), String(value), KJS::Internal);
+ static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeSetMode(false);
+}
+
+// This gets the actual attribute as set in the svg source
+DOM::DOMString SVGElementImpl::getAttribute(const DOM::DOMString &name) const
+{
+ DOM::DOMString *result = m_attributes[name.string()];
+ if(result)
+ return *result;
+ else
+ return DOM::DOMString();
+}
+
+// This gets the internal, real-time value. This means it can return a default value
+// for an attribute even if its not explicitly set in the svg source.
+DOM::DOMString SVGElementImpl::getAttributeInternal(const DOM::DOMString &name)
+{
+ ExecState *exec = ownerDoc()->ecmaEngine()->globalExec();
+
+ DOM::DOMString retVal;
+
+ static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeGetMode(true);
+ retVal = bridge(exec)->get(exec, Identifier(UString(name))).toString(exec).string();
+ static_cast<KSVGScriptInterpreter *>(exec->interpreter())->setAttributeGetMode(false);
+
+ return retVal;
+}
+
+bool SVGElementImpl::hasAttribute(const DOM::DOMString &name)
+{
+ return m_attributes.find(name.string()) != 0;
+}
+
+bool SVGElementImpl::hasAttributes()
+{
+ return m_attributes.count() > 0;
+}
+
+void SVGElementImpl::setApplyAttribute(const QString &name, const QString &value)
+{
+ if(hasAttribute(name))
+ {
+ QString cur = getAttribute(name).string();
+ cur = cur.simplifyWhiteSpace();
+
+ if(!cur.endsWith(";"))
+ cur += "; ";
+
+ cur += value;
+
+ setAttribute(name, cur);
+ }
+ else
+ setAttribute(name, value);
+}
+
+void SVGElementImpl::setId(DOM::DOMString id)
+{
+ setAttribute("id", id);
+
+ if(ownerDoc() && ownerDoc()->rootElement() && !id.isEmpty())
+ ownerDoc()->rootElement()->addToIdMap(id.string(), this);
+ else if(m_ownerSVGElement && !id.isEmpty())
+ m_ownerSVGElement->addToIdMap(id.string(), this);
+}
+
+DOM::DOMString SVGElementImpl::id() const
+{
+ return getAttribute("id");
+}
+
+void SVGElementImpl::setXmlbase(DOM::DOMString xmlbase)
+{
+ setAttribute("xml:base", xmlbase);
+}
+
+DOM::DOMString SVGElementImpl::xmlbase() const
+{
+ return getAttribute("xml:base");
+}
+
+void SVGElementImpl::setOwnerSVGElement(SVGSVGElementImpl *owner)
+{
+ if(m_ownerSVGElement)
+ m_ownerSVGElement->deref();
+
+ m_ownerSVGElement = owner;
+
+ if(m_ownerSVGElement)
+ m_ownerSVGElement->ref();
+}
+
+void SVGElementImpl::setViewportElement(SVGElementImpl *viewport)
+{
+ if(m_viewportElement)
+ m_viewportElement->deref();
+
+ m_viewportElement = viewport;
+
+ if(m_viewportElement)
+ m_viewportElement->ref();
+}
+
+SVGSVGElementImpl *SVGElementImpl::ownerSVGElement() const
+{
+ return m_ownerSVGElement;
+}
+
+SVGElementImpl *SVGElementImpl::viewportElement() const
+{
+ return m_viewportElement;
+}
+
+void SVGElementImpl::setAttributes(const QXmlAttributes &attrs)
+{
+ for(int i = 0; i < attrs.length(); i++)
+ {
+ setAttribute(attrs.localName(i), attrs.value(i));
+ setAttributeInternal(attrs.localName(i), attrs.value(i));
+ }
+
+ setAttributes();
+}
+
+void SVGElementImpl::setAttributes()
+{
+ // Finalize style
+ SVGStylableImpl *style = dynamic_cast<SVGStylableImpl *>(this);
+
+ if(style)
+ style->processStyle();
+}
+
+void SVGElementImpl::setAttributes(bool deep)
+{
+ // Finalize style
+ SVGStylableImpl *style = dynamic_cast<SVGStylableImpl *>(this);
+
+ if(style)
+ style->processStyle();
+
+ if(deep)
+ {
+ if(hasChildNodes())
+ {
+ DOM::Node n;
+ for(n = firstChild(); !n.isNull(); n = n.nextSibling())
+ {
+ SVGElementImpl *elem = ownerDoc()->getElementFromHandle(n.handle());
+ if(elem)
+ elem->setAttributes(true);
+ }
+ }
+ }
+}
+
+bool SVGElementImpl::prepareMouseEvent(const QPoint &p, const QPoint &a, SVGMouseEventImpl *mev)
+{
+ SVGShapeImpl *shape = dynamic_cast<SVGShapeImpl *>(this);
+ if(shape)
+ return shape->prepareMouseEvent(p, a, mev);
+
+ return false;
+}
+
+bool SVGElementImpl::dispatchEvent(int id, bool canBubbleArg, bool cancelableArg)
+{
+ SVGEventImpl *evt = new SVGEventImpl(static_cast<SVGEvent::EventId>(id), canBubbleArg, cancelableArg);
+
+ evt->ref();
+ bool ret = dispatchEvent(evt, true);
+ evt->deref();
+
+ return ret;
+}
+
+bool SVGElementImpl::dispatchEvent(SVGEventImpl *evt, bool tempEvent)
+{
+ evt->setTarget(this);
+
+ // Find out, where to send to -> collect parent nodes
+ QPtrList<SVGElementImpl> nodeChain;
+
+ for(DOM::Element e = *this; !e.isNull(); e = e.parentNode())
+ nodeChain.prepend(ownerDoc()->getElementFromHandle(e.handle()));
+
+ // Trigger any capturing event handlers on our way down
+ evt->setEventPhase(DOM::Event::CAPTURING_PHASE);
+
+ QPtrListIterator<SVGElementImpl> it(nodeChain);
+ for(; it.current() && it.current() != this && !evt->propagationStopped(); ++it)
+ {
+ evt->setCurrentTarget(it.current());
+
+ if(it.current())
+ it.current()->handleLocalEvents(evt, true);
+ }
+
+ // Dispatch to the actual target node
+ it.toLast();
+ if(!evt->propagationStopped())
+ {
+ evt->setEventPhase(DOM::Event::AT_TARGET);
+ evt->setCurrentTarget(it.current());
+
+ if(it.current())
+ it.current()->handleLocalEvents(evt, false);
+ }
+
+ --it;
+
+ // Bubble up again
+ if(evt->bubbles())
+ {
+ evt->setEventPhase(DOM::Event::BUBBLING_PHASE);
+ for(; it.current() && !evt->propagationStopped(); --it)
+ {
+ evt->setCurrentTarget(it.current());
+
+ if(it.current())
+ it.current()->handleLocalEvents(evt, false);
+ }
+ }
+
+ evt->setCurrentTarget(0);
+ evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
+ // anything about the default event handler phase.
+
+ if(evt->bubbles())
+ {
+ // now we call all default event handlers (this is not part of DOM - it is internal to ksvg)
+ it.toLast();
+ for(; it.current() && !evt->propagationStopped() && !evt->defaultPrevented() && !evt->defaultHandled(); --it)
+ it.current()->defaultEventHandler(evt);
+ }
+
+ // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
+ // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
+ // So there is no need for the interpreter to keep the event in its cache
+ if(tempEvent)
+ ownerDoc()->ecmaEngine()->finishedWithEvent(evt);
+
+ return !evt->defaultPrevented(); // ### what if defaultPrevented was called before dispatchEvent?
+}
+
+bool SVGElementImpl::dispatchKeyEvent(QKeyEvent *ke)
+{
+ DOM::AbstractView temp;
+
+ SVGEvent::EventId evtId = SVGEvent::UNKNOWN_EVENT;
+
+ if(ke->type() == QEvent::KeyRelease && !ke->isAutoRepeat())
+ evtId = SVGEvent::KEYUP_EVENT;
+ else if(ke->isAutoRepeat())
+ evtId = SVGEvent::KEYPRESS_EVENT;
+ else if(ke->type() == QEvent::KeyPress)
+ evtId = SVGEvent::KEYDOWN_EVENT;
+
+ if(evtId == SVGEvent::KEYUP_EVENT && hasEventListener(SVGEvent::DOMACTIVATE_EVENT, false))
+ dispatchEvent(SVGEvent::DOMACTIVATE_EVENT, true, true);
+
+ if(!hasEventListener(evtId, false))
+ return false;
+
+ SVGEventImpl *evt = new SVGKeyEventImpl(ke, temp, evtId);
+
+ evt->ref();
+ bool ret = dispatchEvent(evt, true);
+ evt->deref();
+
+ // Rerender now! Once! (Niko)
+ ownerDoc()->rerender();
+
+ return ret;
+}
+
+bool SVGElementImpl::dispatchMouseEvent(int id, bool canBubbleArg, bool cancelableArg, long detailArg, long screenXArg, long screenYArg, long clientXArg, long clientYArg, bool ctrlKeyArg, bool altKeyArg, bool shiftKeyArg, bool metaKeyArg, unsigned short buttonArg, SVGElementImpl *relatedTargetArg)
+{
+ DOM::AbstractView temp;
+
+ SVGEventImpl *evt = new SVGMouseEventImpl(static_cast<SVGEvent::EventId>(id),
+ canBubbleArg, cancelableArg, temp, detailArg,
+ screenXArg, screenYArg,
+ clientXArg, clientYArg,
+ ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg,
+ buttonArg, relatedTargetArg);
+
+ evt->ref();
+ bool ret = dispatchEvent(evt, true);
+ evt->deref();
+
+ return ret;
+}
+
+void SVGElementImpl::setOwnerDoc(SVGDocumentImpl *doc)
+{
+ if(m_ownerDoc)
+ m_ownerDoc->removeFromElemDict(handle());
+
+ m_ownerDoc = doc;
+
+ if(m_ownerDoc)
+ m_ownerDoc->addToElemDict(handle(), this);
+}
+
+SVGDocumentImpl *SVGElementImpl::ownerDoc() const
+{
+ return m_ownerDoc;
+}
+
+SVGElementImpl *SVGElementImpl::cloneNode(bool deep)
+{
+ DOM::Element impl = static_cast<DOM::Document *>(ownerDoc())->createElementNS("", tagName());
+ SVGElementImpl *newElement = SVGDocumentImpl::createElement(tagName(), impl.cloneNode(false), ownerDoc());
+ newElement->setOwnerSVGElement(ownerSVGElement());
+ newElement->setViewportElement(viewportElement());
+
+ SVGHelperImpl::copyAttributes(this, newElement);
+
+ // Recalc style
+ //newElement->setAttributes();
+
+ if(deep)
+ cloneChildNodes(newElement);
+
+ return newElement;
+}
+
+void SVGElementImpl::cloneChildNodes(SVGElementImpl *clone)
+{
+ DOM::Node n;
+ for(n = firstChild(); !n.isNull(); n = n.nextSibling())
+ {
+ SVGElementImpl *elem = ownerDoc()->getElementFromHandle(n.handle());
+ if(elem)
+ clone->appendChild(*elem->cloneNode(true));
+ else if(n.nodeType() == DOM::Node::TEXT_NODE)
+ clone->appendChild(n.cloneNode(true));
+ }
+}
+
+void SVGElementImpl::gotError(const QString &errorDesc)
+{
+ if(ownerDoc())
+ {
+ ownerDoc()->finishParsing(true, errorDesc);
+ if(hasEventListener(SVGEvent::ERROR_EVENT, true))
+ dispatchEvent(SVGEvent::ERROR_EVENT, false, false);
+ }
+}
+
+QString SVGElementImpl::collectText()
+{
+ QString text;
+
+ if(hasChildNodes())
+ {
+ DOM::Node node = firstChild();
+
+ for(; !node.isNull(); node = node.nextSibling())
+ {
+ if(node.nodeType() == DOM::Node::TEXT_NODE)
+ {
+ DOM::Text textNode = node;
+ text += textNode.data().string();
+ }
+ }
+ }
+
+ return text;
+}
+
+// vim:ts=4:noet