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