diff options
Diffstat (limited to 'ksvg/impl/SVGDocumentImpl.cc')
-rw-r--r-- | ksvg/impl/SVGDocumentImpl.cc | 703 |
1 files changed, 0 insertions, 703 deletions
diff --git a/ksvg/impl/SVGDocumentImpl.cc b/ksvg/impl/SVGDocumentImpl.cc deleted file mode 100644 index ce6de16e..00000000 --- a/ksvg/impl/SVGDocumentImpl.cc +++ /dev/null @@ -1,703 +0,0 @@ -/* - 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 <kdebug.h> - -#define USE_VALGRIND 0 - -#if USE_VALGRIND -#include <valgrind/calltree.h> -#endif - -#include "SVGEvent.h" -#include "SVGMatrixImpl.h" -#include "SVGWindowImpl.h" -#include "SVGElementImpl.h" -#include "SVGDocumentImpl.moc" -#include "SVGSVGElementImpl.h" -#include "SVGImageElementImpl.h" -#include "SVGScriptElementImpl.h" -#include "SVGTitleElementImpl.h" -#include "SVGAnimationElementImpl.h" - -#include "KSVGReader.h" -#include "KSVGLoader.h" -#include "KSVGCanvas.h" -#include "CanvasItem.h" - -#include <tqpaintdevicemetrics.h> - -using namespace KSVG; - -#include "SVGDocumentImpl.lut.h" -#include "ksvg_scriptinterpreter.h" -#include "ksvg_bridge.h" -#include "ksvg_ecma.h" - -// A sequence of prime numbers that sets the m_elemDict's hash table size as the -// number of elements in the dictionary passes each level. This keeps the lookup -// performance high as the number of elements grows. See the TQDict documentation. -unsigned int SVGDocumentImpl::elemDictHashSizes [] = -{ - 101, - 211, - 401, - 809, - 1601, - 3203, - 6421, - 12809, - 25601, - 51203, - 102407, - 204803, - 409609, - 819229 -}; - -const int SVGDocumentImpl::numElemDictHashSizes = sizeof(elemDictHashSizes) / sizeof(elemDictHashSizes[0]); - -SVGDocumentImpl::SVGDocumentImpl(bool anim, bool fit, SVGImageElementImpl *parentImage) : TQObject(), DOM::DomShared(), DOM::Document(), SVGDOMNodeBridge(static_cast<DOM::Node>(*this)) -{ - m_animations = anim; - - m_reader = 0; - m_loader = 0; - m_canvas = 0; - m_rootElement = 0; - m_lastTarget = 0; - m_window = 0; - - m_elemDictHashSizeIndex = 0; - m_elemDict.resize(elemDictHashSizes[m_elemDictHashSizeIndex]); - - m_timeScheduler = new SVGTimeScheduler(this); - m_ecmaEngine = new KSVGEcma(this); - m_ecmaEngine->setup(); - - m_finishedParsing = false; - m_finishedLoading = false; - m_resortZIndicesOnFinishedLoading = false; - m_fit = fit; - - m_parentImage = parentImage; - if(m_parentImage) - m_parentImage->ref(); -} - -SVGDocumentImpl::~SVGDocumentImpl() -{ - if(rootElement() && rootElement()->hasEventListener(SVGEvent::UNLOAD_EVENT, true)) - rootElement()->dispatchEvent(SVGEvent::UNLOAD_EVENT, false, false); - - TQPtrList<SVGShapeImpl> killList; - - DOM::Node node = firstChild(); - for(; !node.isNull(); node = node.nextSibling()) - { - SVGShapeImpl *shape = dynamic_cast<SVGShapeImpl *>(getElementFromHandle(node.handle())); - if(shape) - killList.append(shape); - } - - SVGShapeImpl *rend = 0; - for(rend = killList.first(); rend; rend = killList.next()) - delete rend; - - delete m_timeScheduler; - delete m_ecmaEngine; - delete m_reader; - delete m_loader; - - if(m_window) - m_window->deref(); - - if(m_parentImage) - m_parentImage->deref(); -} - -SVGWindowImpl *SVGDocumentImpl::window() -{ - if(!m_window) - { - m_window = new SVGWindowImpl(const_cast<SVGDocumentImpl *>(this)); - m_window->ref(); - } - - return m_window; -} - -float SVGDocumentImpl::screenPixelsPerMillimeterX() const -{ - if(canvas() && canvas()->drawWindow()) - { - TQPaintDeviceMetrics metrics(canvas()->drawWindow()); - return float(metrics.width()) / float(metrics.widthMM()); - } - else - return 90.0; -} - -float SVGDocumentImpl::screenPixelsPerMillimeterY() const -{ - if(canvas() && canvas()->drawWindow()) - { - TQPaintDeviceMetrics metrics(canvas()->drawWindow()); - return float(metrics.height()) / float(metrics.heightMM()); - } - else - return 90.0; -} - -DOM::DOMString SVGDocumentImpl::title() const -{ - DOM::Node n; - for(n = rootElement()->firstChild(); !n.isNull(); n = n.nextSibling()) - { - SVGElementImpl *elem = getElementFromHandle(n.handle()); - if(dynamic_cast<SVGTitleElementImpl *>(elem)) - return elem->collectText(); - } - return ""; -} - -DOM::DOMString SVGDocumentImpl::referrer() const -{ - return m_referrer; -} - -DOM::DOMString SVGDocumentImpl::domain() const -{ - return m_baseURL.host(); -} - -DOM::DOMString SVGDocumentImpl::URL() const -{ - return m_baseURL.prettyURL(); -} - -void SVGDocumentImpl::setReferrer(const DOM::DOMString &referrer) -{ - // TODO : better may be to request for referrer instead of storing it - m_referrer = referrer; -} - -void SVGDocumentImpl::setRootElement(SVGSVGElementImpl *elem) -{ - m_rootElement = elem; -} - -SVGSVGElementImpl *SVGDocumentImpl::rootElement() const -{ - return m_rootElement; -} - -SVGElementImpl *SVGDocumentImpl::createElement(const DOM::DOMString &name, DOM::Element impl, SVGDocumentImpl *doc) -{ - DOM::ElementImpl *handle = reinterpret_cast<DOM::ElementImpl *>(impl.handle()); - SVGElementImpl *element = SVGElementImpl::Factory::self()->create(std::string(name.string().latin1()), handle); - - if(!element) - element = new SVGElementImpl(handle); - - element->setOwnerDoc(doc); - element->ref(); - return element; -} - -bool SVGDocumentImpl::open(const ::KURL &url) -{ - if(!url.prettyURL().isEmpty()) - { - m_baseURL = url; - - if(!m_loader) - m_loader = new KSVGLoader(); - - connect(m_loader, TQT_SIGNAL(gotResult(TQIODevice *)), this, TQT_SLOT(slotSVGContent(TQIODevice *))); - m_loader->getSVGContent(url); - } - else - return false; - - return true; -} - -void SVGDocumentImpl::slotSVGContent(TQIODevice *dev) -{ - TQXmlInputSource *inputSource = new TQXmlInputSource(dev); - - if(m_reader) - delete m_reader; - - KSVGReader::ParsingArgs args; - args.fit = m_fit; - args.getURLMode = false; - - TQString url = m_baseURL.prettyURL(); - int pos = url.find('#'); // url can become like this.svg#svgView(viewBox(63,226,74,74)), get part after '#' - if(pos > -1) - args.SVGFragmentId = url.mid(pos + 1); - - m_reader = new KSVGReader(this, m_canvas, args); - connect(m_reader, TQT_SIGNAL(finished(bool, const TQString &)), this, TQT_SLOT(slotFinishedParsing(bool, const TQString &))); - m_t.start(); - -#if USE_VALGRIND - CALLTREE_ZERO_STATS(); -#endif - - m_reader->parse(inputSource); - delete dev; -} - -void SVGDocumentImpl::parseSVG(TQXmlInputSource *inputSource, bool getURLMode) -{ - if(m_reader) - delete m_reader; - - KSVGReader::ParsingArgs args; - args.fit = m_fit; - args.getURLMode = getURLMode; - m_reader = new KSVGReader(this, 0, args); - connect(m_reader, TQT_SIGNAL(finished(bool, const TQString &)), this, TQT_SLOT(slotFinishedParsing(bool, const TQString &))); - -#if USE_VALGRIND - CALLTREE_ZERO_STATS(); -#endif - - m_reader->parse(inputSource); -} - -void SVGDocumentImpl::finishParsing(bool error, const TQString &errorDesc) -{ - if(m_reader) - m_reader->finishParsing(error, errorDesc); -} - -void SVGDocumentImpl::slotFinishedParsing(bool error, const TQString &errorDesc) -{ - kdDebug(26000) << k_funcinfo << "total time : " << m_t.elapsed() << endl; - -#if USE_VALGRIND - CALLTREE_DUMP_STATS(); -#endif - - if(m_animations) - m_timeScheduler->startAnimations(); - - if(m_canvas && !error && rootElement()) - executeScripts(); - - m_finishedParsing = true; - - emit finishedParsing(error, errorDesc); - if(!error) - emit finishedRendering(); - - checkFinishedLoading(); -} - -void SVGDocumentImpl::newImageJob(SVGImageElementImpl *image) -{ - kdDebug(26002) << "SVGDocumentImpl::newImageJob, " << image << endl; - m_loader->newImageJob(image, m_baseURL); -} - -void SVGDocumentImpl::notifyImageLoading(SVGImageElementImpl *image) -{ - m_imagesLoading.append(image); -} - -void SVGDocumentImpl::notifyImageLoaded(SVGImageElementImpl *image) -{ - m_imagesLoading.remove(image); - - if(m_imagesLoading.isEmpty()) - checkFinishedLoading(); -} - -void SVGDocumentImpl::checkFinishedLoading() -{ - if(m_finishedParsing && m_imagesLoading.isEmpty()) - { - m_finishedLoading = true; - - if(m_resortZIndicesOnFinishedLoading) - { - // Only resort if we're the 'outermost' document, i.e. we're not an svg image - // inside another document. We could resort as each image finishes loading, but it - // slows down the parsing phase. - if(m_parentImage == 0 && m_canvas && m_rootElement) - { - m_canvas->setElementItemZIndexRecursive(m_rootElement, 0); - m_canvas->update(); - } - } - - emit finishedLoading(); - } -} - -void SVGDocumentImpl::addForwardReferencingUseElement(SVGUseElementImpl *use) -{ - if(!m_forwardReferencingUseElements.contains(use)) - m_forwardReferencingUseElements.append(use); -} - -void SVGDocumentImpl::slotPaint() -{ - rerender(); -} - -void SVGDocumentImpl::rerender() -{ - m_canvas->update(); - emit finishedRendering(); -} - -void SVGDocumentImpl::attach(KSVG::KSVGCanvas *c) -{ - m_canvas = c; -} - -void SVGDocumentImpl::detach() -{ - m_canvas = 0; -} - -KSVG::KSVGCanvas *SVGDocumentImpl::canvas() const -{ - return m_canvas; -} - -void SVGDocumentImpl::syncCachedMatrices() -{ - if(rootElement()) - { - SVGMatrixImpl *parentMatrix = SVGSVGElementImpl::createSVGMatrix(); - rootElement()->checkCachedScreenCTM(parentMatrix); - parentMatrix->deref(); - } -} - -void SVGDocumentImpl::executeScriptsRecursive(DOM::Node start) -{ - DOM::Node node = start.firstChild(); - - for(; !node.isNull(); node = node.nextSibling()) - { - SVGElementImpl *element = getElementFromHandle(node.handle()); - - SVGContainerImpl *container = dynamic_cast<SVGContainerImpl *>(element); - if(container) - executeScriptsRecursive(node); - - SVGScriptElementImpl *script = dynamic_cast<SVGScriptElementImpl *>(element); - - if(script) - script->executeScript(DOM::Node()); - } -} - -bool SVGDocumentImpl::executeScriptsRecursiveCheck(DOM::Node start) -{ - bool test = true; - - DOM::Node node = start.firstChild(); - - for(; !node.isNull(); node = node.nextSibling()) - { - SVGElementImpl *element = getElementFromHandle(node.handle()); - - SVGContainerImpl *container = dynamic_cast<SVGContainerImpl *>(element); - if(container) - { - if(!executeScriptsRecursiveCheck(node)) - return false; - } - - SVGScriptElementImpl *script = dynamic_cast<SVGScriptElementImpl *>(element); - - if(script) - { - if(!script->canExecuteScript()) - { - test = false; - break; - } - } - } - - return test; -} - -void SVGDocumentImpl::executeScripts() -{ - bool test = executeScriptsRecursiveCheck(*rootElement()); - - if(!test) - TQTimer::singleShot(50, this, TQT_SLOT(executeScripts())); - else - { - executeScriptsRecursive(*rootElement()); - - // mop: only rerender if an loadevent has been found - if(dispatchRecursiveEvent(SVGEvent::LOAD_EVENT, lastChild())) - m_canvas->update(); - } -} - -// Dispatches a non-cancelable, non-bubbles event to every child -bool SVGDocumentImpl::dispatchRecursiveEvent(SVGEvent::EventId id, DOM::Node start) -{ - bool eventExecuted = false; - - // Iterate the tree, backwards, and dispatch the event to every child - DOM::Node node = start; - for(; !node.isNull(); node = node.previousSibling()) - { - SVGElementImpl *element = getElementFromHandle(node.handle()); - - if(element && element->hasChildNodes()) - { - // Dispatch to all children - eventExecuted = dispatchRecursiveEvent(id, element->lastChild()) ? true : eventExecuted; - - // Dispatch, locally - if(element->hasEventListener(id, true)) - { - element->dispatchEvent(id, false, false); - eventExecuted = true; - } - } - else if(element && element->hasEventListener(id, true)) - { - element->dispatchEvent(id, false, false); - eventExecuted = true; - } - } - - return eventExecuted; -} - -SVGEventListener *SVGDocumentImpl::createEventListener(DOM::DOMString type) -{ - return m_ecmaEngine->createEventListener(type); -} - -SVGElementImpl *SVGDocumentImpl::recursiveSearch(DOM::Node start, const DOM::DOMString &id) -{ - DOM::Node node = start.firstChild(); - for(; !node.isNull(); node = node.nextSibling()) - { - SVGElementImpl *test = getElementFromHandle(node.handle()); - - // Look in containers - SVGContainerImpl *container = dynamic_cast<SVGContainerImpl *>(test); - if(container) - { - SVGElementImpl *found = recursiveSearch(node, id); - if(found) - return found; - } - - // Look in SVGSVGElementImpl's - SVGSVGElementImpl *svgtest = dynamic_cast<SVGSVGElementImpl *>(test); - if(svgtest) - { - SVGElementImpl *element = svgtest->getElementById(id); - if(element) - return element; - } - } - - return 0; -} - -/* -@namespace KSVG -@begin SVGDocumentImpl::s_hashTable 9 - title SVGDocumentImpl::Title DontDelete|ReadOnly - referrer SVGDocumentImpl::Referrer DontDelete|ReadOnly - domain SVGDocumentImpl::Domain DontDelete|ReadOnly - URL SVGDocumentImpl::Url DontDelete|ReadOnly - doctype SVGDocumentImpl::DocType DontDelete|ReadOnly - implementation SVGDocumentImpl::Implementation DontDelete|ReadOnly - rootElement SVGDocumentImpl::RootElement DontDelete|ReadOnly - documentElement SVGDocumentImpl::DocumentElement DontDelete|ReadOnly -@end -@namespace KSVG -@begin SVGDocumentImplProto::s_hashTable 7 - createTextNode SVGDocumentImpl::CreateTextNode DontDelete|Function 1 - createElement SVGDocumentImpl::CreateElement DontDelete|Function 1 - createElementNS SVGDocumentImpl::CreateElementNS DontDelete|Function 2 - getElementById SVGDocumentImpl::GetElementById DontDelete|Function 1 - getElementsByTagName SVGDocumentImpl::GetElementsByTagName DontDelete|Function 1 - getElementsByTagNameNS SVGDocumentImpl::GetElementsByTagNameNS DontDelete|Function 2 -@end -*/ - -KSVG_IMPLEMENT_PROTOTYPE("SVGDocument", SVGDocumentImplProto, SVGDocumentImplProtoFunc) - -Value SVGDocumentImpl::getValueProperty(ExecState *exec, int token) const -{ - switch(token) - { - case Title: - return String(title().string()); - case Referrer: - return String(referrer().string()); - case Domain: - return String(domain().string()); - case Url: - return String(URL().string()); - case DocType: - return getDOMNode(exec, doctype()); - case Implementation: - return (new SVGDOMDOMImplementationBridge(implementation()))->cache(exec); - case RootElement: - case DocumentElement: - return m_rootElement->cache(exec); - default: - kdWarning() << "Unhandled token in " << k_funcinfo << " : " << token << endl; - return Undefined(); - } -} - -Value SVGDocumentImplProtoFunc::call(ExecState *exec, Object &thisObj, const List &args) -{ - KSVG_CHECK_THIS(SVGDocumentImpl) - - switch(id) - { - case SVGDocumentImpl::CreateTextNode: - return getDOMNode(exec, obj->createTextNode(args[0].toString(exec).string())); - case SVGDocumentImpl::CreateElement: - case SVGDocumentImpl::CreateElementNS: - { - SVGElementImpl *newElement = 0; - - if(id == SVGDocumentImpl::CreateElement) - newElement = obj->createElement(args[0].toString(exec).qstring(), static_cast<DOM::Document *>(obj)->createElement(args[0].toString(exec).string()), obj); - else if(id == SVGDocumentImpl::CreateElementNS) - newElement = obj->createElement(args[1].toString(exec).qstring(), static_cast<DOM::Document *>(obj)->createElementNS(args[0].toString(exec).string(), args[1].toString(exec).string()), obj); - - newElement->setOwnerSVGElement(obj->rootElement()); // FIXME: Correct in all situations? - newElement->setViewportElement(obj->rootElement()); - newElement->setAttributes(); - - return getDOMNode(exec, *newElement); - } - case SVGDocumentImpl::GetElementById: - { - Value ret; - - SVGElementImpl *element = obj->rootElement()->getElementById(args[0].toString(exec).string()); - - if(element) - ret = getDOMNode(exec, *element); - else - { - element = obj->recursiveSearch(*obj, args[0].toString(exec).string()); - if(!element) - return Null(); - - ret = getDOMNode(exec, *element); - } - - return ret; - } - case SVGDocumentImpl::GetElementsByTagName: - return (new SVGDOMNodeListBridge(obj->getElementsByTagName(args[0].toString(exec).string())))->cache(exec); - case SVGDocumentImpl::GetElementsByTagNameNS: - return (new SVGDOMNodeListBridge(obj->getElementsByTagNameNS(args[0].toString(exec).string(), args[1].toString(exec).string())))->cache(exec); - default: - break; - } - - return KJS::Undefined(); -} - -SVGElementImpl *SVGDocumentImpl::getElementFromHandle(DOM::NodeImpl *handle) const -{ - return m_elemDict[handle]; -} - -void SVGDocumentImpl::addToElemDict(DOM::NodeImpl *handle, SVGElementImpl *obj) -{ - m_elemDict.insert(handle, obj); - - if(m_elemDict.count()>m_elemDict.size() && m_elemDictHashSizeIndex<numElemDictHashSizes-1) - { - // Increase the hash table size to maintain good lookup speed. - m_elemDictHashSizeIndex++; - m_elemDict.resize(elemDictHashSizes[m_elemDictHashSizeIndex]); - } -} - -void SVGDocumentImpl::removeFromElemDict(DOM::NodeImpl *handle) -{ - m_elemDict.remove(handle); -} - -SVGDocumentImpl *SVGDocumentImpl::getDocumentFromHandle(DOM::NodeImpl *handle) const -{ - return m_documentDict[handle]; -} - -void SVGDocumentImpl::addToDocumentDict(DOM::NodeImpl *handle, SVGDocumentImpl *obj) -{ - m_documentDict.insert(handle, obj); -} - -SVGElementImpl *SVGDocumentImpl::getElementByIdRecursive(SVGSVGElementImpl *start, const DOM::DOMString &elementId, bool dontSearch) -{ - SVGElementImpl *element = 0; - - // #1 Look in passed SVGSVGElementImpl - if(start) - { - element = start->getElementById(elementId); - - if(element) - return element; - } - - // #2 Search in all child SVGSVGElementImpl's - element = recursiveSearch(*this, elementId); - - if(element) - return element; - - // #3 Search in other documents - if(!dontSearch) - { - TQPtrDictIterator<SVGDocumentImpl> it(m_documentDict); - for(; it.current(); ++it) - { - SVGElementImpl *temp = it.current()->getElementByIdRecursive(0, elementId, true); - if(temp) - return temp; - } - } - - return element; -} |