• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3   * Copyright (C) 2004, 2005, 2007, 2008 Rob Buis <buis@kde.org>
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 "config.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 "Document.h"
30  #include "HTMLNames.h"
31  #include "PlatformString.h"
32  #include "RenderObject.h"
33  #include "RenderSVGResource.h"
34  #include "RenderSVGResourceClipper.h"
35  #include "RenderSVGResourceFilter.h"
36  #include "RenderSVGResourceMasker.h"
37  #include "SVGElement.h"
38  #include "SVGElementInstance.h"
39  #include "SVGElementRareData.h"
40  #include "SVGNames.h"
41  #include "SVGRenderStyle.h"
42  #include "SVGRenderSupport.h"
43  #include "SVGSVGElement.h"
44  #include "SVGUseElement.h"
45  #include <wtf/Assertions.h>
46  #include <wtf/HashMap.h>
47  
48  namespace WebCore {
49  
50  // Animated property definitions
51  DEFINE_ANIMATED_STRING(SVGStyledElement, HTMLNames::classAttr, ClassName, className)
52  
53  using namespace SVGNames;
54  
mapAttributeToCSSProperty(HashMap<AtomicStringImpl *,int> * propertyNameToIdMap,const QualifiedName & attrName)55  void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, int>* propertyNameToIdMap, const QualifiedName& attrName)
56  {
57      int propertyId = cssPropertyID(attrName.localName());
58      ASSERT(propertyId > 0);
59      propertyNameToIdMap->set(attrName.localName().impl(), propertyId);
60  }
61  
SVGStyledElement(const QualifiedName & tagName,Document * document)62  SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* document)
63      : SVGElement(tagName, document)
64  {
65  }
66  
~SVGStyledElement()67  SVGStyledElement::~SVGStyledElement()
68  {
69  }
70  
title() const71  String SVGStyledElement::title() const
72  {
73      // According to spec, we should not return titles when hovering over root <svg> elements (those
74      // <title> elements are the title of the document, not a tooltip) so we instantly return.
75      if (hasTagName(SVGNames::svgTag)) {
76          const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(this);
77          if (svg->isOutermostSVG())
78              return String();
79      }
80  
81      // Walk up the tree, to find out whether we're inside a <use> shadow tree, to find the right title.
82      Node* parent = const_cast<SVGStyledElement*>(this);
83      while (parent) {
84          if (!parent->isSVGShadowRoot()) {
85              parent = parent->parentNodeGuaranteedHostFree();
86              continue;
87          }
88  
89          // Get the <use> element.
90          Element* shadowParent = parent->svgShadowHost();
91          if (shadowParent && shadowParent->isSVGElement() && shadowParent->hasTagName(SVGNames::useTag)) {
92              SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowParent);
93              // If the <use> title is not empty we found the title to use.
94              String useTitle(useElement->title());
95              if (useTitle.isEmpty())
96                  break;
97              return useTitle;
98          }
99          parent = parent->parentNode();
100      }
101  
102      // If we aren't an instance in a <use> or the <use> title was not found, then find the first
103      // <title> child of this element.
104      Element* titleElement = firstElementChild();
105      for (; titleElement; titleElement = titleElement->nextElementSibling()) {
106          if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGElement())
107              break;
108      }
109  
110      // If a title child was found, return the text contents.
111      if (titleElement)
112          return titleElement->innerText();
113  
114      // Otherwise return a null/empty string.
115      return String();
116  }
117  
rendererIsNeeded(RenderStyle * style)118  bool SVGStyledElement::rendererIsNeeded(RenderStyle* style)
119  {
120      // http://www.w3.org/TR/SVG/extend.html#PrivateData
121      // Prevent anything other than SVG renderers from appearing in our render tree
122      // Spec: SVG allows inclusion of elements from foreign namespaces anywhere
123      // with the SVG content. In general, the SVG user agent will include the unknown
124      // elements in the DOM but will otherwise ignore unknown elements.
125      if (!parentNode() || parentNode()->isSVGElement())
126          return StyledElement::rendererIsNeeded(style);
127  
128      return false;
129  }
130  
cssPropertyIdForSVGAttributeName(const QualifiedName & attrName)131  int SVGStyledElement::cssPropertyIdForSVGAttributeName(const QualifiedName& attrName)
132  {
133      if (!attrName.namespaceURI().isNull())
134          return 0;
135  
136      static HashMap<AtomicStringImpl*, int>* propertyNameToIdMap = 0;
137      if (!propertyNameToIdMap) {
138          propertyNameToIdMap = new HashMap<AtomicStringImpl*, int>;
139          // This is a list of all base CSS and SVG CSS properties which are exposed as SVG XML attributes
140          mapAttributeToCSSProperty(propertyNameToIdMap, alignment_baselineAttr);
141          mapAttributeToCSSProperty(propertyNameToIdMap, baseline_shiftAttr);
142          mapAttributeToCSSProperty(propertyNameToIdMap, clipAttr);
143          mapAttributeToCSSProperty(propertyNameToIdMap, clip_pathAttr);
144          mapAttributeToCSSProperty(propertyNameToIdMap, clip_ruleAttr);
145          mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::colorAttr);
146          mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolationAttr);
147          mapAttributeToCSSProperty(propertyNameToIdMap, color_interpolation_filtersAttr);
148          mapAttributeToCSSProperty(propertyNameToIdMap, color_profileAttr);
149          mapAttributeToCSSProperty(propertyNameToIdMap, color_renderingAttr);
150          mapAttributeToCSSProperty(propertyNameToIdMap, cursorAttr);
151          mapAttributeToCSSProperty(propertyNameToIdMap, SVGNames::directionAttr);
152          mapAttributeToCSSProperty(propertyNameToIdMap, displayAttr);
153          mapAttributeToCSSProperty(propertyNameToIdMap, dominant_baselineAttr);
154          mapAttributeToCSSProperty(propertyNameToIdMap, enable_backgroundAttr);
155          mapAttributeToCSSProperty(propertyNameToIdMap, fillAttr);
156          mapAttributeToCSSProperty(propertyNameToIdMap, fill_opacityAttr);
157          mapAttributeToCSSProperty(propertyNameToIdMap, fill_ruleAttr);
158          mapAttributeToCSSProperty(propertyNameToIdMap, filterAttr);
159          mapAttributeToCSSProperty(propertyNameToIdMap, flood_colorAttr);
160          mapAttributeToCSSProperty(propertyNameToIdMap, flood_opacityAttr);
161          mapAttributeToCSSProperty(propertyNameToIdMap, font_familyAttr);
162          mapAttributeToCSSProperty(propertyNameToIdMap, font_sizeAttr);
163          mapAttributeToCSSProperty(propertyNameToIdMap, font_stretchAttr);
164          mapAttributeToCSSProperty(propertyNameToIdMap, font_styleAttr);
165          mapAttributeToCSSProperty(propertyNameToIdMap, font_variantAttr);
166          mapAttributeToCSSProperty(propertyNameToIdMap, font_weightAttr);
167          mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_horizontalAttr);
168          mapAttributeToCSSProperty(propertyNameToIdMap, glyph_orientation_verticalAttr);
169          mapAttributeToCSSProperty(propertyNameToIdMap, image_renderingAttr);
170          mapAttributeToCSSProperty(propertyNameToIdMap, kerningAttr);
171          mapAttributeToCSSProperty(propertyNameToIdMap, letter_spacingAttr);
172          mapAttributeToCSSProperty(propertyNameToIdMap, lighting_colorAttr);
173          mapAttributeToCSSProperty(propertyNameToIdMap, marker_endAttr);
174          mapAttributeToCSSProperty(propertyNameToIdMap, marker_midAttr);
175          mapAttributeToCSSProperty(propertyNameToIdMap, marker_startAttr);
176          mapAttributeToCSSProperty(propertyNameToIdMap, maskAttr);
177          mapAttributeToCSSProperty(propertyNameToIdMap, opacityAttr);
178          mapAttributeToCSSProperty(propertyNameToIdMap, overflowAttr);
179          mapAttributeToCSSProperty(propertyNameToIdMap, pointer_eventsAttr);
180          mapAttributeToCSSProperty(propertyNameToIdMap, shape_renderingAttr);
181          mapAttributeToCSSProperty(propertyNameToIdMap, stop_colorAttr);
182          mapAttributeToCSSProperty(propertyNameToIdMap, stop_opacityAttr);
183          mapAttributeToCSSProperty(propertyNameToIdMap, strokeAttr);
184          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dasharrayAttr);
185          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_dashoffsetAttr);
186          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linecapAttr);
187          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_linejoinAttr);
188          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_miterlimitAttr);
189          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_opacityAttr);
190          mapAttributeToCSSProperty(propertyNameToIdMap, stroke_widthAttr);
191          mapAttributeToCSSProperty(propertyNameToIdMap, text_anchorAttr);
192          mapAttributeToCSSProperty(propertyNameToIdMap, text_decorationAttr);
193          mapAttributeToCSSProperty(propertyNameToIdMap, text_renderingAttr);
194          mapAttributeToCSSProperty(propertyNameToIdMap, unicode_bidiAttr);
195          mapAttributeToCSSProperty(propertyNameToIdMap, vector_effectAttr);
196          mapAttributeToCSSProperty(propertyNameToIdMap, visibilityAttr);
197          mapAttributeToCSSProperty(propertyNameToIdMap, word_spacingAttr);
198          mapAttributeToCSSProperty(propertyNameToIdMap, writing_modeAttr);
199      }
200  
201      return propertyNameToIdMap->get(attrName.localName().impl());
202  }
203  
cssPropertyToTypeMap()204  static inline AttributeToPropertyTypeMap& cssPropertyToTypeMap()
205  {
206      DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_cssPropertyMap, ());
207  
208      if (!s_cssPropertyMap.isEmpty())
209          return s_cssPropertyMap;
210  
211      // Fill the map for the first use.
212      s_cssPropertyMap.set(alignment_baselineAttr, AnimatedString);
213      s_cssPropertyMap.set(baseline_shiftAttr, AnimatedString);
214      s_cssPropertyMap.set(clipAttr, AnimatedRect);
215      s_cssPropertyMap.set(clip_pathAttr, AnimatedString);
216      s_cssPropertyMap.set(clip_ruleAttr, AnimatedString);
217      s_cssPropertyMap.set(SVGNames::colorAttr, AnimatedColor);
218      s_cssPropertyMap.set(color_interpolationAttr, AnimatedString);
219      s_cssPropertyMap.set(color_interpolation_filtersAttr, AnimatedString);
220      s_cssPropertyMap.set(color_profileAttr, AnimatedString);
221      s_cssPropertyMap.set(color_renderingAttr, AnimatedString);
222      s_cssPropertyMap.set(cursorAttr, AnimatedString);
223      s_cssPropertyMap.set(displayAttr, AnimatedString);
224      s_cssPropertyMap.set(dominant_baselineAttr, AnimatedString);
225      s_cssPropertyMap.set(fillAttr, AnimatedColor);
226      s_cssPropertyMap.set(fill_opacityAttr, AnimatedNumber);
227      s_cssPropertyMap.set(fill_ruleAttr, AnimatedString);
228      s_cssPropertyMap.set(filterAttr, AnimatedString);
229      s_cssPropertyMap.set(flood_colorAttr, AnimatedColor);
230      s_cssPropertyMap.set(flood_opacityAttr, AnimatedNumber);
231      s_cssPropertyMap.set(font_familyAttr, AnimatedString);
232      s_cssPropertyMap.set(font_sizeAttr, AnimatedLength);
233      s_cssPropertyMap.set(font_stretchAttr, AnimatedString);
234      s_cssPropertyMap.set(font_styleAttr, AnimatedString);
235      s_cssPropertyMap.set(font_variantAttr, AnimatedString);
236      s_cssPropertyMap.set(font_weightAttr, AnimatedString);
237      s_cssPropertyMap.set(image_renderingAttr, AnimatedString);
238      s_cssPropertyMap.set(kerningAttr, AnimatedLength);
239      s_cssPropertyMap.set(letter_spacingAttr, AnimatedLength);
240      s_cssPropertyMap.set(lighting_colorAttr, AnimatedColor);
241      s_cssPropertyMap.set(marker_endAttr, AnimatedString);
242      s_cssPropertyMap.set(marker_midAttr, AnimatedString);
243      s_cssPropertyMap.set(marker_startAttr, AnimatedString);
244      s_cssPropertyMap.set(maskAttr, AnimatedString);
245      s_cssPropertyMap.set(opacityAttr, AnimatedNumber);
246      s_cssPropertyMap.set(overflowAttr, AnimatedString);
247      s_cssPropertyMap.set(pointer_eventsAttr, AnimatedString);
248      s_cssPropertyMap.set(shape_renderingAttr, AnimatedString);
249      s_cssPropertyMap.set(stop_colorAttr, AnimatedColor);
250      s_cssPropertyMap.set(stop_opacityAttr, AnimatedNumber);
251      s_cssPropertyMap.set(strokeAttr, AnimatedColor);
252      s_cssPropertyMap.set(stroke_dasharrayAttr, AnimatedLengthList);
253      s_cssPropertyMap.set(stroke_dashoffsetAttr, AnimatedLength);
254      s_cssPropertyMap.set(stroke_linecapAttr, AnimatedString);
255      s_cssPropertyMap.set(stroke_linejoinAttr, AnimatedString);
256      s_cssPropertyMap.set(stroke_miterlimitAttr, AnimatedNumber);
257      s_cssPropertyMap.set(stroke_opacityAttr, AnimatedNumber);
258      s_cssPropertyMap.set(stroke_widthAttr, AnimatedLength);
259      s_cssPropertyMap.set(text_anchorAttr, AnimatedString);
260      s_cssPropertyMap.set(text_decorationAttr, AnimatedString);
261      s_cssPropertyMap.set(text_renderingAttr, AnimatedString);
262      s_cssPropertyMap.set(vector_effectAttr, AnimatedString);
263      s_cssPropertyMap.set(visibilityAttr, AnimatedString);
264      s_cssPropertyMap.set(word_spacingAttr, AnimatedLength);
265      return s_cssPropertyMap;
266  }
267  
animatedPropertyTypeForCSSProperty(const QualifiedName & attrName)268  AnimatedAttributeType SVGStyledElement::animatedPropertyTypeForCSSProperty(const QualifiedName& attrName)
269  {
270      AttributeToPropertyTypeMap& cssPropertyTypeMap = cssPropertyToTypeMap();
271      if (cssPropertyTypeMap.contains(attrName))
272          return cssPropertyTypeMap.get(attrName);
273      return AnimatedUnknown;
274  }
275  
isAnimatableCSSProperty(const QualifiedName & attrName)276  bool SVGStyledElement::isAnimatableCSSProperty(const QualifiedName& attrName)
277  {
278      return cssPropertyToTypeMap().contains(attrName);
279  }
280  
fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap & attributeToPropertyTypeMap)281  void SVGStyledElement::fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap& attributeToPropertyTypeMap)
282  {
283      attributeToPropertyTypeMap.set(HTMLNames::classAttr, AnimatedString);
284  }
285  
mapToEntry(const QualifiedName & attrName,MappedAttributeEntry & result) const286  bool SVGStyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
287  {
288      if (SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName) > 0) {
289          result = eSVG;
290          return false;
291      }
292      return SVGElement::mapToEntry(attrName, result);
293  }
294  
parseMappedAttribute(Attribute * attr)295  void SVGStyledElement::parseMappedAttribute(Attribute* attr)
296  {
297      const QualifiedName& attrName = attr->name();
298      // NOTE: Any subclass which overrides parseMappedAttribute for a property handled by
299      // cssPropertyIdForSVGAttributeName will also have to override mapToEntry to disable the default eSVG mapping
300      int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(attrName);
301      if (propId > 0) {
302          addCSSProperty(attr, propId, attr->value());
303          setNeedsStyleRecalc();
304          return;
305      }
306  
307      // SVG animation has currently requires special storage of values so we set
308      // the className here.  svgAttributeChanged actually causes the resulting
309      // style updates (instead of StyledElement::parseMappedAttribute). We don't
310      // tell StyledElement about the change to avoid parsing the class list twice
311      if (attrName.matches(HTMLNames::classAttr))
312          setClassNameBaseValue(attr->value());
313      else
314          // id is handled by StyledElement which SVGElement inherits from
315          SVGElement::parseMappedAttribute(attr);
316  }
317  
isKnownAttribute(const QualifiedName & attrName)318  bool SVGStyledElement::isKnownAttribute(const QualifiedName& attrName)
319  {
320      return isIdAttributeName(attrName);
321  }
322  
svgAttributeChanged(const QualifiedName & attrName)323  void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName)
324  {
325      SVGElement::svgAttributeChanged(attrName);
326  
327      if (attrName.matches(HTMLNames::classAttr))
328          classAttributeChanged(className());
329  
330      RenderObject* object = renderer();
331  
332      if (isIdAttributeName(attrName)) {
333          // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions
334          if (object && object->isSVGResourceContainer())
335              object->toRenderSVGResourceContainer()->idChanged();
336      }
337  
338      // Invalidate all SVGElementInstances associated with us
339      SVGElementInstance::invalidateAllInstancesOfElement(this);
340  }
341  
synchronizeProperty(const QualifiedName & attrName)342  void SVGStyledElement::synchronizeProperty(const QualifiedName& attrName)
343  {
344      SVGElement::synchronizeProperty(attrName);
345  
346      if (attrName == anyQName() || attrName.matches(HTMLNames::classAttr))
347          synchronizeClassName();
348  }
349  
attach()350  void SVGStyledElement::attach()
351  {
352      SVGElement::attach();
353  
354      if (RenderObject* object = renderer())
355          object->updateFromElement();
356  }
357  
insertedIntoDocument()358  void SVGStyledElement::insertedIntoDocument()
359  {
360      SVGElement::insertedIntoDocument();
361      updateRelativeLengthsInformation();
362  }
363  
removedFromDocument()364  void SVGStyledElement::removedFromDocument()
365  {
366      updateRelativeLengthsInformation(false, this);
367      SVGElement::removedFromDocument();
368  }
369  
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)370  void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
371  {
372      SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
373  
374      // Invalidate all SVGElementInstances associated with us
375      if (!changedByParser)
376          SVGElementInstance::invalidateAllInstancesOfElement(this);
377  }
378  
resolveStyle(RenderStyle * parentStyle)379  PassRefPtr<RenderStyle> SVGStyledElement::resolveStyle(RenderStyle* parentStyle)
380  {
381      if (renderer())
382          return renderer()->style();
383      return document()->styleSelector()->styleForElement(this, parentStyle);
384  }
385  
getPresentationAttribute(const String & name)386  PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& name)
387  {
388      if (!attributeMap())
389          return 0;
390  
391      QualifiedName attributeName(nullAtom, name, nullAtom);
392      Attribute* attr = attributeMap()->getAttributeItem(attributeName);
393      if (!attr || !attr->isMappedAttribute() || !attr->style())
394          return 0;
395  
396      Attribute* cssSVGAttr = attr;
397      // This function returns a pointer to a CSSValue which can be mutated from JavaScript.
398      // If the associated MappedAttribute uses the same CSSMappedAttributeDeclaration
399      // as StyledElement's mappedAttributeDecls cache, create a new CSSMappedAttributeDeclaration
400      // before returning so that any modifications to the CSSValue will not affect other attributes.
401      MappedAttributeEntry entry;
402      mapToEntry(attributeName, entry);
403      if (getMappedAttributeDecl(entry, cssSVGAttr) == cssSVGAttr->decl()) {
404          cssSVGAttr->setDecl(0);
405          int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(cssSVGAttr->name());
406          addCSSProperty(cssSVGAttr, propId, cssSVGAttr->value());
407      }
408      return cssSVGAttr->style()->getPropertyCSSValue(name);
409  }
410  
instanceUpdatesBlocked() const411  bool SVGStyledElement::instanceUpdatesBlocked() const
412  {
413      return hasRareSVGData() && rareSVGData()->instanceUpdatesBlocked();
414  }
415  
setInstanceUpdatesBlocked(bool value)416  void SVGStyledElement::setInstanceUpdatesBlocked(bool value)
417  {
418      if (hasRareSVGData())
419          rareSVGData()->setInstanceUpdatesBlocked(value);
420  }
421  
localCoordinateSpaceTransform(SVGLocatable::CTMScope) const422  AffineTransform SVGStyledElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
423  {
424      // To be overriden by SVGStyledLocatableElement/SVGStyledTransformableElement (or as special case SVGTextElement)
425      ASSERT_NOT_REACHED();
426      return AffineTransform();
427  }
428  
updateRelativeLengthsInformation(bool hasRelativeLengths,SVGStyledElement * element)429  void SVGStyledElement::updateRelativeLengthsInformation(bool hasRelativeLengths, SVGStyledElement* element)
430  {
431      // If we're not yet in a document, this function will be called again from insertedIntoDocument(). Do nothing now.
432      if (!inDocument())
433          return;
434  
435      // An element wants to notify us that its own relative lengths state changed.
436      // Register it in the relative length map, and register us in the parent relative length map.
437      // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
438  
439      if (hasRelativeLengths)
440          m_elementsWithRelativeLengths.add(element);
441      else {
442          if (!m_elementsWithRelativeLengths.contains(element)) {
443              // We were never registered. Do nothing.
444              return;
445          }
446  
447          m_elementsWithRelativeLengths.remove(element);
448      }
449  
450      // Find first styled parent node, and notify it that we've changed our relative length state.
451      ContainerNode* node = parentNode();
452      while (node) {
453          if (!node->isSVGElement())
454              break;
455  
456          SVGElement* element = static_cast<SVGElement*>(node);
457          if (!element->isStyled()) {
458              node = node->parentNode();
459              continue;
460          }
461  
462          // Register us in the parent element map.
463          static_cast<SVGStyledElement*>(element)->updateRelativeLengthsInformation(hasRelativeLengths, this);
464          break;
465      }
466  }
467  
468  }
469  
470  #endif // ENABLE(SVG)
471