KHtml

SVGElement.cpp
1 /*
2  Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <[email protected]>
3  2004, 2005, 2006, 2008 Rob Buis <[email protected]>
4 
5  This file is part of the KDE project
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "wtf/Platform.h"
24 
25 #if ENABLE(SVG)
26 #include "SVGElement.h"
27 
28 /*#include "DOMImplementation.h"*/
29 /*#include "Event.h"
30 #include "EventListener.h"
31 #include "EventNames.h"
32 #include "FrameView.h"
33 #include "HTMLNames.h"
34 #include "PlatformString.h"
35 #include "RenderObject.h"
36 #include "SVGElementInstance.h"*/
37 #include "SVGSVGElement.h"
38 /*#include "SVGURIReference.h"
39 #include "SVGUseElement.h"
40 #include "RegisteredEventListener.h"*/
41 
42 namespace WebCore
43 {
44 
45 using namespace DOM;
46 
47 //using namespace HTMLNames;
48 //using namespace EventNames;
49 
50 SVGElement::SVGElement(const QualifiedName &tagName, Document *doc)
51  : StyledElement(doc) // it's wrong, remove it!!! FIXME: vtokarev
52 // : StyledElement(tagName, doc)
53 // , m_shadowParent(0)
54 {
55  m_prefix = tagName.prefixId();
56 }
57 
58 SVGElement::~SVGElement()
59 {
60 }
61 
62 bool SVGElement::isSupported(StringImpl *feature, StringImpl *version) const
63 {
64  return DOMImplementation::hasFeature(feature, version);
65 }
66 
67 String SVGElement::attrid() const
68 {
69  return getAttribute(idAttr);
70 }
71 
72 void SVGElement::setId(const String &value, ExceptionCode &)
73 {
74  setAttribute(idAttr, value);
75 }
76 
77 String SVGElement::xmlbase() const
78 {
79  return getAttribute(ATTR_XML_BASE);
80 }
81 
82 void SVGElement::setXmlbase(const String &value, ExceptionCode &)
83 {
84  setAttribute(ATTR_XML_BASE, value);
85 }
86 
87 SVGSVGElement *SVGElement::ownerSVGElement() const
88 {
89  Node *n = isShadowNode() ? const_cast<SVGElement *>(this)->shadowParentNode() : parentNode();
90  while (n) {
91  if (/*n->hasTagName(SVGNames::svgTag)*/n->id() == SVGNames::svgTag.id()) {
92  return static_cast<SVGSVGElement *>(n);
93  }
94 
95  n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode();
96  }
97 
98  return nullptr;
99 }
100 
101 SVGElement *SVGElement::viewportElement() const
102 {
103  // This function needs shadow tree support - as RenderSVGContainer uses this function
104  // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise.
105  /*Node* n = isShadowNode() ? const_cast<SVGElement*>(this)->shadowParentNode() : parentNode();
106  while (n) {
107  if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::symbolTag))
108  return static_cast<SVGElement*>(n);
109 
110  n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode();
111  }*/
112 
113  return nullptr;
114 }
115 
116 void SVGElement::addSVGEventListener(/*const AtomicString& eventType*/const EventImpl::EventId &eventType, const Attribute *attr)
117 {
118  // qCDebug(KHTML_LOG) << "add listener for: " << EventName::fromId(eventType).toString();
119  Element::setHTMLEventListener(EventName::fromId(eventType), document()->accessSVGExtensions()->
120  createSVGEventListener(attr->localName().string(), attr->value(), this));
121 }
122 
123 void SVGElement::parseMappedAttribute(MappedAttribute *attr)
124 {
125  // standard events
126  if (/*attr->name() == onloadAttr*/attr->id() == ATTR_ONLOAD) {
127  addSVGEventListener(/*loadEvent*/EventImpl::LOAD_EVENT, attr);
128  } else if (/*attr->name() == onclickAttr*/attr->id() == ATTR_ONCLICK) {
129  addSVGEventListener(/*clickEvent*/EventImpl::CLICK_EVENT, attr);
130  } else /*if (attr->name() == onmousedownAttr)
131  addSVGEventListener(mousedownEvent, attr);
132  else if (attr->name() == onmousemoveAttr)
133  addSVGEventListener(mousemoveEvent, attr);
134  else if (attr->name() == onmouseoutAttr)
135  addSVGEventListener(mouseoutEvent, attr);
136  else if (attr->name() == onmouseoverAttr)
137  addSVGEventListener(mouseoverEvent, attr);
138  else if (attr->name() == onmouseupAttr)
139  addSVGEventListener(mouseupEvent, attr);
140  else if (attr->name() == SVGNames::onfocusinAttr)
141  addSVGEventListener(DOMFocusInEvent, attr);
142  else if (attr->name() == SVGNames::onfocusoutAttr)
143  addSVGEventListener(DOMFocusOutEvent, attr);
144  else if (attr->name() == SVGNames::onactivateAttr)
145  addSVGEventListener(DOMActivateEvent, attr);
146  else*/ if (attr->id() == ATTR_ID) {
147  setHasID();
148  document()->incDOMTreeVersion(DocumentImpl::TV_IDNameHref);
149  } else {
150  StyledElement::parseAttribute(attr);
151  }
152 }
153 
154 bool SVGElement::haveLoadedRequiredResources()
155 {
156  Node *child = firstChild();
157  while (child) {
158  if (child->isSVGElement() && !static_cast<SVGElement *>(child)->haveLoadedRequiredResources()) {
159  return false;
160  }
161  child = child->nextSibling();
162  }
163  return true;
164 }
165 
166 static bool hasLoadListener(SVGElement *node)
167 {
168  Node *currentNode = node;
169  while (currentNode && currentNode->isElementNode()) {
170  QList<RegisteredEventListener> *list = static_cast<Element *>(currentNode)->localEventListeners();
171  if (list) {
173  for (QList<RegisteredEventListener>::Iterator it = list->begin(); it != end; ++it)
174  if ((*it).useCapture || (*it).eventName.id() == EventImpl::LOAD_EVENT/* || currentNode == node*/) {
175  return true;
176  }
177  /*if ((*it)->eventType() == loadEvent &&
178  (*it)->useCapture() == true || currentNode == node)
179  return true;*/
180  }
181  currentNode = currentNode->parentNode();
182  }
183 
184  return false;
185 }
186 
187 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents)
188 {
189  // qCDebug(KHTML_LOG) << "send svg load event";
190  RefPtr<SVGElement> currentTarget = this;
191  // qCDebug(KHTML_LOG) << currentTarget << currentTarget->haveLoadedRequiredResources();
192  while (currentTarget && currentTarget->haveLoadedRequiredResources()) {
193  RefPtr<Node> parent;
194  if (sendParentLoadEvents) {
195  parent = currentTarget->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree
196  }
197  // qCDebug(KHTML_LOG) << hasLoadListener(currentTarget.get());
198  if (hasLoadListener(currentTarget.get())) {
199  //Event* event = new Event(EventImpl::LOAD_EVENT, true/*false*/, false);
200  //event->setTarget(currentTarget.get());
201  //ExceptionCode ignored = 0;
202  //dispatchGenericEvent(/*currentTarget.get(), */event, ignored/*, false*/);
203  dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
204  }
205  currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>();
206  }
207 }
208 
209 void SVGElement::finishParsingChildren()
210 {
211  // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>)
212  // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish
213  sendSVGLoadEventIfPossible();
214 }
215 
216 bool SVGElement::childShouldCreateRenderer(Node *child) const
217 {
218  if (child->isSVGElement()) {
219  return static_cast<SVGElement *>(child)->isValid();
220  }
221  return false;
222 }
223 
224 void SVGElement::insertedIntoDocument()
225 {
226  StyledElement::insertedIntoDocument();
227  /*SVGDocumentExtensions* extensions = document()->accessSVGExtensions();
228 
229  String resourceId = SVGURIReference::getTarget(id());
230  if (extensions->isPendingResource(resourceId)) {
231  std::unique_ptr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId));
232  if (clients->isEmpty())
233  return;
234 
235  HashSet<SVGStyledElement*>::const_iterator it = clients->begin();
236  const HashSet<SVGStyledElement*>::const_iterator end = clients->end();
237 
238  for (; it != end; ++it)
239  (*it)->buildPendingResource();
240 
241  SVGResource::invalidateClients(*clients);
242  }*/
243 }
244 
245 static Node *shadowTreeParentElementForShadowTreeElement(Node *node)
246 {
247  for (Node *n = node; n; n = n->parentNode()) {
248  /*if (n->isShadowNode())
249  return n->shadowParentNode();*/
250  }
251 
252  return nullptr;
253 }
254 
255 bool SVGElement::dispatchEvent(Event *e, ExceptionCode &ec, bool tempEvent)
256 {
257  Q_UNUSED(e);
258  Q_UNUSED(ec);
259  Q_UNUSED(tempEvent);
260  // qCDebug(KHTML_LOG) << "dispatch event";
261  // TODO: This function will be removed in a follow-up patch!
262 
263  /*EventTarget* target = this;
264  Node* useNode = shadowTreeParentElementForShadowTreeElement(this);
265 
266  // If we are a hidden shadow tree element, the target must
267  // point to our corresponding SVGElementInstance object
268  if (useNode) {
269  ASSERT(useNode->hasTagName(SVGNames::useTag));
270  SVGUseElement* use = static_cast<SVGUseElement*>(useNode);
271 
272  SVGElementInstance* instance = use->instanceForShadowTreeElement(this);
273 
274  if (instance)
275  target = instance;
276  }
277 
278  e->setTarget(target);
279 
280  RefPtr<FrameView> view = document()->view();
281  return EventTargetNode::dispatchGenericEvent(this, e, ec, tempEvent);*/
282  ASSERT(false);
283  return false;
284 }
285 
286 void SVGElement::attributeChanged(Attribute *attr, bool preserveDecls)
287 {
288  ASSERT(attr);
289  if (!attr) {
290  return;
291  }
292 
293  StyledElement::attributeChanged(attr, preserveDecls);
294  svgAttributeChanged(attr->name());
295 }
296 
297 // for KHTML compatibility
298 void SVGElement::addCSSProperty(Attribute *attr, int id, const String &value)
299 {
300  Q_UNUSED(attr);
301  // qCDebug(KHTML_LOG) << "called with: " << id << " " << value;
302  /* WARNING: copy&past'ed from HTMLElementImpl class */
303  if (!m_hasCombinedStyle) {
304  createNonCSSDecl();
305  }
306  nonCSSStyleDecls()->setProperty(id, value, false);
307  setChanged();
308 }
309 
310 void SVGElement::addCSSProperty(Attribute *attr, int id, int value)
311 {
312  Q_UNUSED(attr);
313  // qCDebug(KHTML_LOG) << "called with: " << id << " " << value;
314  /* WARNING: copy&past'ed from HTMLElementImpl class */
315  if (!m_hasCombinedStyle) {
316  createNonCSSDecl();
317  }
318  nonCSSStyleDecls()->setProperty(id, value, false);
319  setChanged();
320 }
321 
322 }
323 
324 #endif // ENABLE(SVG)
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:278
By far the vast majority of objects (apart from text) that authors encounter when traversing a docume...
Definition: dom_element.h:212
Node parentNode() const
The parent of this node.
Definition: dom_node.cpp:250
MESSAGECORE_EXPORT KMime::Content * firstChild(const KMime::Content *node)
The Document interface represents the entire HTML or XML document.
Definition: dom_doc.h:246
QList::iterator end()
This library provides a full-featured HTML parser and widget.
const QList< QKeySequence > & end()
Introduced in DOM Level 2.
Definition: dom2_events.h:116
bool isValid(QStringView ifopt)
QList::iterator begin()
Node nextSibling() const
The node immediately following this node.
Definition: dom_node.cpp:290
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:09 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.