KHtml

SVGStyledElement.cpp
1 /*
2  Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <[email protected]>
3  2004, 2005, 2007 Rob Buis <[email protected]>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "wtf/Platform.h"
22 
23 #if ENABLE(SVG)
24 #include "SVGStyledElement.h"
25 
26 /*#include "Attr.h"
27 #include "CSSParser.h"
28 #include "CSSStyleSelector.h"
29 #include "CString.h"*/
30 #include "cssstyleselector.h"
31 #include "Document.h"
32 /*#include "HTMLNames.h"*/
33 #include "PlatformString.h"
34 /*#include "SVGElementInstance.h"*/
35 #include "SVGNames.h"
36 #include "RenderObject.h"
37 #include "SVGRenderStyle.h"
38 /*#include "SVGResource.h"*/
39 #include "SVGSVGElement.h"
40 #include <wtf/Assertions.h>
41 
42 // khtml
43 #include "css_base.h"
44 
45 namespace WebCore
46 {
47 
48 using namespace SVGNames;
49 using namespace DOM;
50 
51 static HashSet<const SVGStyledElement *> *gElementsWithInstanceUpdatesBlocked = nullptr;
52 
53 SVGStyledElement::SVGStyledElement(const QualifiedName &tagName, Document *doc)
54  : SVGElement(tagName, doc)
55 {
56 }
57 
58 SVGStyledElement::~SVGStyledElement()
59 {
60 // SVGResource::removeClient(this);
61 }
62 
63 ANIMATED_PROPERTY_DEFINITIONS(SVGStyledElement, String, String, string, ClassName, className, HTMLNames::classAttr, m_className)
64 
65 bool SVGStyledElement::rendererIsNeeded(RenderStyle *style)
66 {
67  // https://www.w3.org/TR/SVG/extend.html#PrivateData
68  // Prevent anything other than SVG renderers from appearing in our render tree
69  // Spec: SVG allows inclusion of elements from foreign namespaces anywhere
70  // with the SVG content. In general, the SVG user agent will include the unknown
71  // elements in the DOM but will otherwise ignore unknown elements.
72  if (!parentNode() || parentNode()->isSVGElement()) {
73  return StyledElement::rendererIsNeeded(style);
74  }
75 
76  return false;
77 }
78 
79 static void mapAttributeToCSSProperty(HashMap<DOMStringImpl *, int> *propertyNameToIdMap, const QualifiedName &attrName)
80 {
81  /*int propertyId = cssPropertyID(attrName.localName());*/
82  QString propName = attrName.localName().string();
83  int propertyId = DOM::getPropertyID(propName.toLatin1(), propName.length());
84  ASSERT(propertyId > 0);
85  propertyNameToIdMap->set(attrName.localName().implementation(), propertyId);
86 }
87 
88 int SVGStyledElement::cssPropertyIdForSVGAttributeName(const QualifiedName &attrName)
89 {
90  if (!attrName.namespaceURI().isEmpty()/*khtml fix, was isNull()*/) {
91  return 0;
92  }
93 
94  // ### I think this is better redone as a switch.
95  static HashMap<DOMStringImpl *, int> *propertyNameToIdMap = nullptr;
96  if (!propertyNameToIdMap) {
97  propertyNameToIdMap = new HashMap<DOMStringImpl *, int>;
98  // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes
99  mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr);
100  mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr);
101  mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr);
102  mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr);
103  mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr);
104  mapAttributeToCSSProperty(propertyNameToIdMap, colorAttr);
105  mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr);
106  mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr);
107  mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr);
108  mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr);
109  mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr);
110  mapAttributeToCSSProperty(propertyNameToIdMap, directionAttr);
111  mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr);
112  mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr);
113  mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr);
114  mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr);
115  mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr);
116  mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr);
117  mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr);
118  mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr);
119  mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr);
120  mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr);
121  mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr);
122  mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr);
123  mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr);
124  mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr);
125  mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr);
126  mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr);
127  mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr);
128  mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr);
129  mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr);
130  mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr);
131  mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr);
132  mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr);
133  mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr);
134  mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr);
135  mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr);
136  mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr);
137  mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr);
138  mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr);
139  mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr);
140  mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr);
141  mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr);
142  mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr);
143  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr);
144  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr);
145  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr);
146  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr);
147  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr);
148  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr);
149  mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr);
150  mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr);
151  mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr);
152  mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr);
153  mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr);
154  mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr);
155  mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr);
156  mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr);
157  }
158  return propertyNameToIdMap->get(attrName.localName().implementation());
159 }
160 
161 /*bool SVGStyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
162 {
163  if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName) > 0) {
164  result = eSVG;
165  return false;
166  }
167  return SVGElement::mapToEntry(attrName, result);
168 }*/
169 
170 void SVGStyledElement::parseMappedAttribute(MappedAttribute *attr)
171 {
172  // NOTE: Any subclass which overrides parseMappedAttribute for a property handled by
173  // cssPropertyIdForSVGAttributeName will also have to override mapToEntry to disable the default eSVG mapping
174  int id = attr->id();
175  if (id == ATTR_STYLE) {
176  if (inlineStyleDecls()) {
177  inlineStyleDecls()->clear();
178  } else {
179  createInlineDecl();
180  }
181  inlineStyleDecls()->setProperty(attr->value());
182  setChanged();
183  return;
184  }
185  int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attr->name());
186  if (propId > 0) {
187  addCSSProperty(attr, propId, attr->value());
188  setChanged();
189  return;
190  }
191 
192  // id and class are handled by StyledElement
193  SVGElement::parseMappedAttribute(attr);
194 }
195 
196 bool SVGStyledElement::isKnownAttribute(const QualifiedName &attrName)
197 {
198  // Recognize all style related SVG CSS properties
199  int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName);
200  if (propId > 0) {
201  return true;
202  }
203  return (attrName.id() == ATTR_ID || attrName.id() == ATTR_STYLE);
204  /*return (attrName == HTMLNames::idAttr || attrName == HTMLNames::styleAttr); */
205 }
206 
207 void SVGStyledElement::svgAttributeChanged(const QualifiedName &attrName)
208 {
209  SVGElement::svgAttributeChanged(attrName);
210 
211  // If we're the child of a resource element, be sure to invalidate it.
212  invalidateResourcesInAncestorChain();
213 
214  SVGDocumentExtensions *extensions = document()->accessSVGExtensions();
215  if (!extensions) {
216  return;
217  }
218 
219  // TODO: Fix bug https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
220 
221  // In case we're referenced by a <use> element, we have element instances registered
222  // to us in the SVGDocumentExtensions. If notifyAttributeChange() is called, we need
223  // to recursively update all children including ourselves.
224  updateElementInstance(extensions);
225 }
226 
227 void SVGStyledElement::invalidateResourcesInAncestorChain() const
228 {
229  Node *node = parentNode();
230  while (node) {
231  if (!node->isSVGElement()) {
232  break;
233  }
234 
235  SVGElement *element = static_cast<SVGElement *>(node);
236  if (SVGStyledElement *styledElement = static_cast<SVGStyledElement *>(element->isStyled() ? element : nullptr)) {
237  /*if (SVGResource* resource = styledElement->canvasResource())
238  resource->invalidate();*/
239  }
240 
241  node = node->parentNode();
242  }
243 }
244 
245 void SVGStyledElement::childrenChanged(bool changedByParser, Node *beforeChange, Node *afterChange, int childCountDelta)
246 {
247  Q_UNUSED(changedByParser);
248  Q_UNUSED(beforeChange);
249  Q_UNUSED(afterChange);
250  Q_UNUSED(childCountDelta);
251  SVGElement::childrenChanged();
252  /*SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
253  if (document()->parsing())
254  return;
255 
256  SVGDocumentExtensions* extensions = document()->accessSVGExtensions();
257  if (!extensions)
258  return;
259 
260  // TODO: Fix bug https://bugs.webkit.org/show_bug.cgi?id=15430 (SVGElementInstances should rebuild themselves lazily)
261 
262  // In case we're referenced by a <use> element, we have element instances registered
263  // to us in the SVGDocumentExtensions. If childrenChanged() is called, we need
264  // to recursively update all children including ourselves.
265  updateElementInstance(extensions);*/
266 }
267 
268 void SVGStyledElement::updateElementInstance(SVGDocumentExtensions *extensions) const
269 {
270  Q_UNUSED(extensions);
271  /*if (gElementsWithInstanceUpdatesBlocked && gElementsWithInstanceUpdatesBlocked->contains(this))
272  return;
273 
274  SVGStyledElement* nonConstThis = const_cast<SVGStyledElement*>(this);
275  HashSet<SVGElementInstance*>* set = extensions->instancesForElement(nonConstThis);
276  if (!set || set->isEmpty())
277  return;
278 
279  // We need to be careful here, as the instancesForElement
280  // hash set may be modified after we call updateInstance!
281  HashSet<SVGElementInstance*> localCopy;
282 
283  // First create a local copy of the hashset
284  HashSet<SVGElementInstance*>::const_iterator it1 = set->begin();
285  const HashSet<SVGElementInstance*>::const_iterator end1 = set->end();
286 
287  for (; it1 != end1; ++it1)
288  localCopy.add(*it1);
289 
290  // Actually nofify instances to update
291  HashSet<SVGElementInstance*>::const_iterator it2 = localCopy.begin();
292  const HashSet<SVGElementInstance*>::const_iterator end2 = localCopy.end();
293 
294  for (; it2 != end2; ++it2)
295  (*it2)->updateInstance(nonConstThis);*/
296 }
297 
298 RenderStyle *SVGStyledElement::resolveStyle(RenderStyle *parentStyle)
299 {
300  Q_UNUSED(parentStyle);
301  if (renderer()) {
302  RenderStyle *renderStyle = renderer()->style();
303  renderStyle->ref();
304  return renderStyle;
305  }
306 
307  return document()->styleSelector()->styleForElement(this/*, parentStyle*/);
308 }
309 
310 PassRefPtr<DOM::CSSValueImpl> SVGStyledElement::getPresentationAttribute(const String &name)
311 {
312  Q_UNUSED(name);
313  /*MappedAttribute* cssSVGAttr = mappedAttributes()->getAttributeItem(name);
314  if (!cssSVGAttr || !cssSVGAttr->style())
315  return 0;
316  return cssSVGAttr->style()->getPropertyCSSValue(name);*/
317  Q_ASSERT(false);
318  return new CSSPrimitiveValueImpl(0);
319 }
320 
321 void SVGStyledElement::detach()
322 {
323  /*SVGResource::removeClient(this);*/
324  SVGElement::detach();
325 }
326 
327 void SVGStyledElement::setInstanceUpdatesBlocked(bool blockUpdates)
328 {
329  if (blockUpdates) {
330  if (!gElementsWithInstanceUpdatesBlocked) {
331  gElementsWithInstanceUpdatesBlocked = new HashSet<const SVGStyledElement *>;
332  }
333  gElementsWithInstanceUpdatesBlocked->add(this);
334  } else {
335  ASSERT(gElementsWithInstanceUpdatesBlocked);
336  ASSERT(gElementsWithInstanceUpdatesBlocked->contains(this));
337  gElementsWithInstanceUpdatesBlocked->remove(this);
338  }
339 }
340 
341 }
342 
343 #endif // ENABLE(SVG)
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:278
Node parentNode() const
The parent of this node.
Definition: dom_node.cpp:250
The Document interface represents the entire HTML or XML document.
Definition: dom_doc.h:246
This library provides a full-featured HTML parser and widget.
QByteArray toLatin1() const const
int length() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:10 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.