File indexing completed on 2024-04-28 15:24:29

0001 /*
0002     Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
0003 
0004     This file is part of the KDE project
0005 
0006     This library is free software; you can redistribute it and/or
0007     modify it under the terms of the GNU Library General Public
0008     License as published by the Free Software Foundation; either
0009     version 2 of the License, or (at your option) any later version.
0010 
0011     This library is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014     Library General Public License for more details.
0015 
0016     You should have received a copy of the GNU Library General Public License
0017     along with this library; see the file COPYING.LIB.  If not, write to
0018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019     Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "wtf/Platform.h"
0023 
0024 #if ENABLE(SVG)
0025 #include "SVGElementInstance.h"
0026 
0027 /*#include "Event.h"
0028 #include "EventListener.h"*/
0029 #include "SVGElementInstanceList.h"
0030 #include "SVGUseElement.h"
0031 
0032 #include <wtf/Assertions.h>
0033 
0034 namespace WebCore
0035 {
0036 
0037 SVGElementInstance::SVGElementInstance(SVGUseElement *useElement, PassRefPtr<SVGElement> originalElement)
0038     : m_refCount(0)
0039     , m_parent(nullptr)
0040     , m_useElement(useElement)
0041     , m_element(originalElement)
0042     , m_shadowTreeElement(nullptr)
0043     , m_previousSibling(nullptr)
0044     , m_nextSibling(nullptr)
0045     , m_firstChild(nullptr)
0046     , m_lastChild(nullptr)
0047 {
0048     ASSERT(m_useElement);
0049     ASSERT(m_element);
0050 
0051     // Register as instance for passed element.
0052     m_element->document()->accessSVGExtensions()->mapInstanceToElement(this, m_element.get());
0053 }
0054 
0055 SVGElementInstance::~SVGElementInstance()
0056 {
0057     for (RefPtr<SVGElementInstance> child = m_firstChild; child; child = child->m_nextSibling) {
0058         child->setParent(nullptr);
0059     }
0060 
0061     // Deregister as instance for passed element.
0062     m_element->document()->accessSVGExtensions()->removeInstanceMapping(this, m_element.get());
0063 }
0064 
0065 SVGElement *SVGElementInstance::correspondingElement() const
0066 {
0067     return m_element.get();
0068 }
0069 
0070 SVGUseElement *SVGElementInstance::correspondingUseElement() const
0071 {
0072     return m_useElement;
0073 }
0074 
0075 SVGElementInstance *SVGElementInstance::parentNode() const
0076 {
0077     return parent();
0078 }
0079 
0080 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
0081 {
0082     return SVGElementInstanceList::create(this);
0083 }
0084 
0085 SVGElementInstance *SVGElementInstance::previousSibling() const
0086 {
0087     return m_previousSibling;
0088 }
0089 
0090 SVGElementInstance *SVGElementInstance::nextSibling() const
0091 {
0092     return m_nextSibling;
0093 }
0094 
0095 SVGElementInstance *SVGElementInstance::firstChild() const
0096 {
0097     return m_firstChild;
0098 }
0099 
0100 SVGElementInstance *SVGElementInstance::lastChild() const
0101 {
0102     return m_lastChild;
0103 }
0104 
0105 SVGElement *SVGElementInstance::shadowTreeElement() const
0106 {
0107     return m_shadowTreeElement;
0108 }
0109 
0110 void SVGElementInstance::setShadowTreeElement(SVGElement *element)
0111 {
0112     ASSERT(element);
0113     m_shadowTreeElement = element;
0114 }
0115 
0116 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
0117 {
0118     child->setParent(this);
0119 
0120     if (m_lastChild) {
0121         child->m_previousSibling = m_lastChild;
0122         m_lastChild->m_nextSibling = child.get();
0123     } else {
0124         m_firstChild = child.get();
0125     }
0126 
0127     m_lastChild = child.get();
0128 }
0129 
0130 // Helper function for updateInstance
0131 static bool containsUseChildNode(Node *start)
0132 {
0133     if (start->hasTagName(SVGNames::useTag)) {
0134         return true;
0135     }
0136 
0137     for (Node *current = start->firstChild(); current; current = current->nextSibling()) {
0138         if (containsUseChildNode(current)) {
0139             return true;
0140         }
0141     }
0142 
0143     return false;
0144 }
0145 
0146 void SVGElementInstance::updateInstance(SVGElement *element)
0147 {
0148     ASSERT(element == m_element);
0149     ASSERT(m_shadowTreeElement);
0150     Q_UNUSED(element);
0151 
0152     // TODO: Eventually come up with a more optimized updating logic for the cases below:
0153     //
0154     // <symbol>: We can't just clone the original element, we need to apply
0155     // the same "replace by generated content" logic that SVGUseElement does.
0156     //
0157     // <svg>: <use> on <svg> is too rare to actually implement it faster.
0158     // If someone still wants to do it: recloning, adjusting width/height attributes is enough.
0159     //
0160     // <use>: Too hard to get it right in a fast way. Recloning seems the only option.
0161 
0162     if (m_element->hasTagName(SVGNames::symbolTag) ||
0163             m_element->hasTagName(SVGNames::svgTag) ||
0164             containsUseChildNode(m_element.get())) {
0165         m_useElement->buildPendingResource();
0166         return;
0167     }
0168 
0169     // For all other nodes this logic is sufficient.
0170     WTF::PassRefPtr<Node> clone = m_element->cloneNode(true);
0171     SVGUseElement::removeDisallowedElementsFromSubtree(clone.get());
0172     SVGElement *svgClone = nullptr;
0173     if (clone && clone->isSVGElement()) {
0174         svgClone = static_cast<SVGElement *>(clone.get());
0175     }
0176     ASSERT(svgClone);
0177 
0178     // Replace node in the <use> shadow tree
0179     /*ExceptionCode*//*khtml*/int ec = 0;
0180     m_shadowTreeElement->parentNode()->replaceChild(clone.releaseRef(), m_shadowTreeElement, ec);
0181     ASSERT(ec == 0);
0182 
0183     m_shadowTreeElement = svgClone;
0184 }
0185 
0186 SVGElementInstance *SVGElementInstance::toSVGElementInstance()
0187 {
0188     return this;
0189 }
0190 
0191 EventTargetNode *SVGElementInstance::toNode()
0192 {
0193     return m_element.get();
0194 }
0195 
0196 void SVGElementInstance::addEventListener(const AtomicString &eventType, PassRefPtr<EventListener> eventListener, bool useCapture)
0197 {
0198     Q_UNUSED(eventType);
0199     Q_UNUSED(eventListener);
0200     Q_UNUSED(useCapture);
0201     // FIXME!
0202 }
0203 
0204 void SVGElementInstance::removeEventListener(const AtomicString &eventType, EventListener *eventListener, bool useCapture)
0205 {
0206     Q_UNUSED(eventType);
0207     Q_UNUSED(eventListener);
0208     Q_UNUSED(useCapture);
0209     // FIXME!
0210 }
0211 
0212 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event>, ExceptionCode &ec, bool tempEvent)
0213 {
0214     Q_UNUSED(ec);
0215     Q_UNUSED(tempEvent);
0216     // FIXME!
0217     return false;
0218 }
0219 
0220 }
0221 
0222 #endif // ENABLE(SVG)
0223