File indexing completed on 2024-04-28 15:24:29
0001 /* 0002 Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> 0004 0005 This file is part of the KDE project 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "wtf/Platform.h" 0024 0025 #if ENABLE(SVG) 0026 #include "SVGElement.h" 0027 0028 /*#include "DOMImplementation.h"*/ 0029 /*#include "Event.h" 0030 #include "EventListener.h" 0031 #include "EventNames.h" 0032 #include "FrameView.h" 0033 #include "HTMLNames.h" 0034 #include "PlatformString.h" 0035 #include "RenderObject.h" 0036 #include "SVGElementInstance.h"*/ 0037 #include "SVGSVGElement.h" 0038 /*#include "SVGURIReference.h" 0039 #include "SVGUseElement.h" 0040 #include "RegisteredEventListener.h"*/ 0041 0042 namespace WebCore 0043 { 0044 0045 using namespace DOM; 0046 0047 //using namespace HTMLNames; 0048 //using namespace EventNames; 0049 0050 SVGElement::SVGElement(const QualifiedName &tagName, Document *doc) 0051 : StyledElement(doc) // it's wrong, remove it!!! FIXME: vtokarev 0052 // : StyledElement(tagName, doc) 0053 // , m_shadowParent(0) 0054 { 0055 m_prefix = tagName.prefixId(); 0056 } 0057 0058 SVGElement::~SVGElement() 0059 { 0060 } 0061 0062 bool SVGElement::isSupported(StringImpl *feature, StringImpl *version) const 0063 { 0064 return DOMImplementation::hasFeature(feature, version); 0065 } 0066 0067 String SVGElement::attrid() const 0068 { 0069 return getAttribute(idAttr); 0070 } 0071 0072 void SVGElement::setId(const String &value, ExceptionCode &) 0073 { 0074 setAttribute(idAttr, value); 0075 } 0076 0077 String SVGElement::xmlbase() const 0078 { 0079 return getAttribute(ATTR_XML_BASE); 0080 } 0081 0082 void SVGElement::setXmlbase(const String &value, ExceptionCode &) 0083 { 0084 setAttribute(ATTR_XML_BASE, value); 0085 } 0086 0087 SVGSVGElement *SVGElement::ownerSVGElement() const 0088 { 0089 Node *n = isShadowNode() ? const_cast<SVGElement *>(this)->shadowParentNode() : parentNode(); 0090 while (n) { 0091 if (/*n->hasTagName(SVGNames::svgTag)*/n->id() == SVGNames::svgTag.id()) { 0092 return static_cast<SVGSVGElement *>(n); 0093 } 0094 0095 n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode(); 0096 } 0097 0098 return nullptr; 0099 } 0100 0101 SVGElement *SVGElement::viewportElement() const 0102 { 0103 // This function needs shadow tree support - as RenderSVGContainer uses this function 0104 // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise. 0105 /*Node* n = isShadowNode() ? const_cast<SVGElement*>(this)->shadowParentNode() : parentNode(); 0106 while (n) { 0107 if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::symbolTag)) 0108 return static_cast<SVGElement*>(n); 0109 0110 n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode(); 0111 }*/ 0112 0113 return nullptr; 0114 } 0115 0116 void SVGElement::addSVGEventListener(/*const AtomicString& eventType*/const EventImpl::EventId &eventType, const Attribute *attr) 0117 { 0118 // qCDebug(KHTML_LOG) << "add listener for: " << EventName::fromId(eventType).toString(); 0119 Element::setHTMLEventListener(EventName::fromId(eventType), document()->accessSVGExtensions()-> 0120 createSVGEventListener(attr->localName().string(), attr->value(), this)); 0121 } 0122 0123 void SVGElement::parseMappedAttribute(MappedAttribute *attr) 0124 { 0125 // standard events 0126 if (/*attr->name() == onloadAttr*/attr->id() == ATTR_ONLOAD) { 0127 addSVGEventListener(/*loadEvent*/EventImpl::LOAD_EVENT, attr); 0128 } else if (/*attr->name() == onclickAttr*/attr->id() == ATTR_ONCLICK) { 0129 addSVGEventListener(/*clickEvent*/EventImpl::CLICK_EVENT, attr); 0130 } else /*if (attr->name() == onmousedownAttr) 0131 addSVGEventListener(mousedownEvent, attr); 0132 else if (attr->name() == onmousemoveAttr) 0133 addSVGEventListener(mousemoveEvent, attr); 0134 else if (attr->name() == onmouseoutAttr) 0135 addSVGEventListener(mouseoutEvent, attr); 0136 else if (attr->name() == onmouseoverAttr) 0137 addSVGEventListener(mouseoverEvent, attr); 0138 else if (attr->name() == onmouseupAttr) 0139 addSVGEventListener(mouseupEvent, attr); 0140 else if (attr->name() == SVGNames::onfocusinAttr) 0141 addSVGEventListener(DOMFocusInEvent, attr); 0142 else if (attr->name() == SVGNames::onfocusoutAttr) 0143 addSVGEventListener(DOMFocusOutEvent, attr); 0144 else if (attr->name() == SVGNames::onactivateAttr) 0145 addSVGEventListener(DOMActivateEvent, attr); 0146 else*/ if (attr->id() == ATTR_ID) { 0147 setHasID(); 0148 document()->incDOMTreeVersion(DocumentImpl::TV_IDNameHref); 0149 } else { 0150 StyledElement::parseAttribute(attr); 0151 } 0152 } 0153 0154 bool SVGElement::haveLoadedRequiredResources() 0155 { 0156 Node *child = firstChild(); 0157 while (child) { 0158 if (child->isSVGElement() && !static_cast<SVGElement *>(child)->haveLoadedRequiredResources()) { 0159 return false; 0160 } 0161 child = child->nextSibling(); 0162 } 0163 return true; 0164 } 0165 0166 static bool hasLoadListener(SVGElement *node) 0167 { 0168 Node *currentNode = node; 0169 while (currentNode && currentNode->isElementNode()) { 0170 QList<RegisteredEventListener> *list = static_cast<Element *>(currentNode)->localEventListeners(); 0171 if (list) { 0172 QList<RegisteredEventListener>::Iterator end = list->end(); 0173 for (QList<RegisteredEventListener>::Iterator it = list->begin(); it != end; ++it) 0174 if ((*it).useCapture || (*it).eventName.id() == EventImpl::LOAD_EVENT/* || currentNode == node*/) { 0175 return true; 0176 } 0177 /*if ((*it)->eventType() == loadEvent && 0178 (*it)->useCapture() == true || currentNode == node) 0179 return true;*/ 0180 } 0181 currentNode = currentNode->parentNode(); 0182 } 0183 0184 return false; 0185 } 0186 0187 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents) 0188 { 0189 // qCDebug(KHTML_LOG) << "send svg load event"; 0190 RefPtr<SVGElement> currentTarget = this; 0191 // qCDebug(KHTML_LOG) << currentTarget << currentTarget->haveLoadedRequiredResources(); 0192 while (currentTarget && currentTarget->haveLoadedRequiredResources()) { 0193 RefPtr<Node> parent; 0194 if (sendParentLoadEvents) { 0195 parent = currentTarget->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree 0196 } 0197 // qCDebug(KHTML_LOG) << hasLoadListener(currentTarget.get()); 0198 if (hasLoadListener(currentTarget.get())) { 0199 //Event* event = new Event(EventImpl::LOAD_EVENT, true/*false*/, false); 0200 //event->setTarget(currentTarget.get()); 0201 //ExceptionCode ignored = 0; 0202 //dispatchGenericEvent(/*currentTarget.get(), */event, ignored/*, false*/); 0203 dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false); 0204 } 0205 currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>(); 0206 } 0207 } 0208 0209 void SVGElement::finishParsingChildren() 0210 { 0211 // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>) 0212 // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish 0213 sendSVGLoadEventIfPossible(); 0214 } 0215 0216 bool SVGElement::childShouldCreateRenderer(Node *child) const 0217 { 0218 if (child->isSVGElement()) { 0219 return static_cast<SVGElement *>(child)->isValid(); 0220 } 0221 return false; 0222 } 0223 0224 void SVGElement::insertedIntoDocument() 0225 { 0226 StyledElement::insertedIntoDocument(); 0227 /*SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 0228 0229 String resourceId = SVGURIReference::getTarget(id()); 0230 if (extensions->isPendingResource(resourceId)) { 0231 std::unique_ptr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId)); 0232 if (clients->isEmpty()) 0233 return; 0234 0235 HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); 0236 const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); 0237 0238 for (; it != end; ++it) 0239 (*it)->buildPendingResource(); 0240 0241 SVGResource::invalidateClients(*clients); 0242 }*/ 0243 } 0244 0245 static Node *shadowTreeParentElementForShadowTreeElement(Node *node) 0246 { 0247 for (Node *n = node; n; n = n->parentNode()) { 0248 /*if (n->isShadowNode()) 0249 return n->shadowParentNode();*/ 0250 } 0251 0252 return nullptr; 0253 } 0254 0255 bool SVGElement::dispatchEvent(Event *e, ExceptionCode &ec, bool tempEvent) 0256 { 0257 Q_UNUSED(e); 0258 Q_UNUSED(ec); 0259 Q_UNUSED(tempEvent); 0260 // qCDebug(KHTML_LOG) << "dispatch event"; 0261 // TODO: This function will be removed in a follow-up patch! 0262 0263 /*EventTarget* target = this; 0264 Node* useNode = shadowTreeParentElementForShadowTreeElement(this); 0265 0266 // If we are a hidden shadow tree element, the target must 0267 // point to our corresponding SVGElementInstance object 0268 if (useNode) { 0269 ASSERT(useNode->hasTagName(SVGNames::useTag)); 0270 SVGUseElement* use = static_cast<SVGUseElement*>(useNode); 0271 0272 SVGElementInstance* instance = use->instanceForShadowTreeElement(this); 0273 0274 if (instance) 0275 target = instance; 0276 } 0277 0278 e->setTarget(target); 0279 0280 RefPtr<FrameView> view = document()->view(); 0281 return EventTargetNode::dispatchGenericEvent(this, e, ec, tempEvent);*/ 0282 ASSERT(false); 0283 return false; 0284 } 0285 0286 void SVGElement::attributeChanged(Attribute *attr, bool preserveDecls) 0287 { 0288 ASSERT(attr); 0289 if (!attr) { 0290 return; 0291 } 0292 0293 StyledElement::attributeChanged(attr, preserveDecls); 0294 svgAttributeChanged(attr->name()); 0295 } 0296 0297 // for KHTML compatibility 0298 void SVGElement::addCSSProperty(Attribute *attr, int id, const String &value) 0299 { 0300 Q_UNUSED(attr); 0301 // qCDebug(KHTML_LOG) << "called with: " << id << " " << value; 0302 /* WARNING: copy&past'ed from HTMLElementImpl class */ 0303 if (!m_hasCombinedStyle) { 0304 createNonCSSDecl(); 0305 } 0306 nonCSSStyleDecls()->setProperty(id, value, false); 0307 setChanged(); 0308 } 0309 0310 void SVGElement::addCSSProperty(Attribute *attr, int id, int value) 0311 { 0312 Q_UNUSED(attr); 0313 // qCDebug(KHTML_LOG) << "called with: " << id << " " << value; 0314 /* WARNING: copy&past'ed from HTMLElementImpl class */ 0315 if (!m_hasCombinedStyle) { 0316 createNonCSSDecl(); 0317 } 0318 nonCSSStyleDecls()->setProperty(id, value, false); 0319 setChanged(); 0320 } 0321 0322 } 0323 0324 #endif // ENABLE(SVG)