COMMIT_MESSAGE

 1renderer ok
 2

Source/WebCore/CMakeLists.txt

@@IF (ENABLE_SVG)
15801580 rendering/svg/RenderSVGInlineText.cpp
15811581 rendering/svg/RenderSVGModelObject.cpp
15821582 rendering/svg/RenderSVGPath.cpp
 1583 rendering/svg/RenderSVGRect.cpp
15831584 rendering/svg/RenderSVGResource.cpp
15841585 rendering/svg/RenderSVGResourceClipper.cpp
15851586 rendering/svg/RenderSVGResourceContainer.cpp

Source/WebCore/GNUmakefile.list.am

@@webcore_sources += \
31893189 Source/WebCore/rendering/svg/RenderSVGModelObject.h \
31903190 Source/WebCore/rendering/svg/RenderSVGPath.cpp \
31913191 Source/WebCore/rendering/svg/RenderSVGPath.h \
 3192 Source/WebCore/rendering/svg/RenderSVGRect.cpp \
 3193 Source/WebCore/rendering/svg/RenderSVGRect.h \
31923194 Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp \
31933195 Source/WebCore/rendering/svg/RenderSVGResourceClipper.h \
31943196 Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp \

Source/WebCore/WebCore.gypi

58695869 'rendering/svg/RenderSVGModelObject.h',
58705870 'rendering/svg/RenderSVGPath.cpp',
58715871 'rendering/svg/RenderSVGPath.h',
 5872 'rendering/svg/RenderSVGRect.cpp',
 5873 'rendering/svg/RenderSVGRect.h',
58725874 'rendering/svg/RenderSVGResource.cpp',
58735875 'rendering/svg/RenderSVGResource.h',
58745876 'rendering/svg/RenderSVGResourceClipper.cpp',

Source/WebCore/WebCore.pro

@@HEADERS += \
22662266 rendering/svg/RenderSVGInlineText.h \
22672267 rendering/svg/RenderSVGModelObject.h \
22682268 rendering/svg/RenderSVGPath.h \
 2269 rendering/svg/RenderSVGRect.h \
22692270 rendering/svg/RenderSVGResource.h \
22702271 rendering/svg/RenderSVGResourceClipper.h \
22712272 rendering/svg/RenderSVGResourceContainer.h \

@@HEADERS += \
22802281 rendering/svg/RenderSVGResourceSolidColor.h \
22812282 rendering/svg/RenderSVGRoot.h \
22822283 rendering/svg/RenderSVGShadowTreeRootContainer.h \
 2284 rendering/svg/RenderSVGShape.h \
22832285 rendering/svg/RenderSVGTSpan.h \
22842286 rendering/svg/RenderSVGText.h \
22852287 rendering/svg/RenderSVGTextPath.h \

@@contains(DEFINES, ENABLE_SVG=1) {
32993301 rendering/style/SVGRenderStyleDefs.cpp \
33003302 rendering/PointerEventsHitRules.cpp \
33013303 rendering/svg/RenderSVGPath.cpp \
 3304 rendering/svg/RenderSVGRect.cpp \
 3305 rendering/svg/RenderSVGShape.cpp \
33023306 svg/animation/SMILTime.cpp \
33033307 svg/animation/SMILTimeContainer.cpp \
33043308 svg/animation/SVGSMILElement.cpp \

Source/WebCore/WebCore.xcodeproj/project.pbxproj

99039903 9FFE3EA311B5A4390037874E /* JSMemoryInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMemoryInfo.cpp; sourceTree = "<group>"; };
99049904 9FFE3EA411B5A4390037874E /* JSMemoryInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMemoryInfo.h; sourceTree = "<group>"; };
99059905 A00B721911DE6427008AB9FF /* CheckedInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CheckedInt.h; path = canvas/CheckedInt.h; sourceTree = "<group>"; };
 9906 A1309B6413F18D9300C8A065 /* RenderSVGRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RenderSVGRect.cpp; path = rendering/svg/RenderSVGRect.cpp; sourceTree = "<group>"; };
 9907 A1309B6813F18DA100C8A065 /* RenderSVGRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RenderSVGRect.h; path = rendering/svg/RenderSVGRect.h; sourceTree = "<group>"; };
99069908 A136A00A1134DBD200CC8D50 /* XMLHttpRequestProgressEventThrottle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLHttpRequestProgressEventThrottle.cpp; sourceTree = "<group>"; };
99079909 A136A00B1134DBD200CC8D50 /* XMLHttpRequestProgressEventThrottle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLHttpRequestProgressEventThrottle.h; sourceTree = "<group>"; };
99089910 A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLElementFactory.cpp; sourceTree = "<group>"; };

1294512947 0867D691FE84028FC02AAC07 /* WebKit */ = {
1294612948 isa = PBXGroup;
1294712949 children = (
 12950 A1309B6813F18DA100C8A065 /* RenderSVGRect.h */,
 12951 A1309B6413F18D9300C8A065 /* RenderSVGRect.cpp */,
1294812952 65C97AF208EA908800ACD273 /* config.h */,
1294912953 EDEC98020AED7E170059137F /* WebCorePrefix.h */,
1295012954 9307061309E0CA8200B17FE4 /* DerivedSources.make */,

Source/WebCore/rendering/RenderObject.h

@@public:
354354 virtual bool isSVGGradientStop() const { return false; }
355355 virtual bool isSVGHiddenContainer() const { return false; }
356356 virtual bool isSVGPath() const { return false; }
 357 virtual bool isSVGRect() const { return false; }
 358 virtual bool isSVGShape() const { return false; }
357359 virtual bool isSVGText() const { return false; }
358360 virtual bool isSVGTextPath() const { return false; }
359361 virtual bool isSVGInline() const { return false; }

Source/WebCore/rendering/RenderTreeAsText.cpp

@@static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBo
520520void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavior behavior)
521521{
522522#if ENABLE(SVG)
523  if (o.isSVGPath()) {
524  write(ts, *toRenderSVGPath(&o), indent);
 523 if (o.isSVGShape()) {
 524 write(ts, *toRenderSVGShape(&o), indent);
525525 return;
526526 }
527527 if (o.isSVGGradientStop()) {

Source/WebCore/rendering/svg/RenderSVGPath.cpp

66 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
77 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
88 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
 10 * Copyright (C) 2011 University of Szeged
911 *
1012 * This library is free software; you can redistribute it and/or
1113 * modify it under the terms of the GNU Library General Public

2830#if ENABLE(SVG)
2931#include "RenderSVGPath.h"
3032
31 #include "FloatPoint.h"
32 #include "FloatQuad.h"
33 #include "GraphicsContext.h"
34 #include "HitTestRequest.h"
35 #include "PointerEventsHitRules.h"
36 #include "RenderSVGContainer.h"
37 #include "RenderSVGResourceMarker.h"
38 #include "RenderSVGResourceSolidColor.h"
39 #include "SVGRenderSupport.h"
40 #include "SVGResources.h"
 33#include "SVGPathElement.h"
4134#include "SVGStyledTransformableElement.h"
42 #include "SVGTransformList.h"
43 #include "SVGURIReference.h"
44 #include "StrokeStyleApplier.h"
45 #include <wtf/MathExtras.h>
4635
4736namespace WebCore {
4837
49 class BoundingRectStrokeStyleApplier : public StrokeStyleApplier {
50 public:
51  BoundingRectStrokeStyleApplier(const RenderObject* object, RenderStyle* style)
52  : m_object(object)
53  , m_style(style)
54  {
55  ASSERT(style);
56  ASSERT(object);
57  }
58 
59  void strokeStyle(GraphicsContext* gc)
60  {
61  SVGRenderSupport::applyStrokeStyleToContext(gc, m_style, m_object);
62  }
63 
64 private:
65  const RenderObject* m_object;
66  RenderStyle* m_style;
67 };
68 
6938RenderSVGPath::RenderSVGPath(SVGStyledTransformableElement* node)
70  : RenderSVGModelObject(node)
71  , m_needsBoundariesUpdate(false) // default is false, the cached rects are empty from the beginning
72  , m_needsPathUpdate(true) // default is true, so we grab a Path object once from SVGStyledTransformableElement
73  , m_needsTransformUpdate(true) // default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement
 39 : RenderSVGShape(node)
7440{
7541}
7642

@@RenderSVGPath::~RenderSVGPath()
7844{
7945}
8046
81 bool RenderSVGPath::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule)
82 {
83  if (!m_fillBoundingBox.contains(point))
84  return false;
85 
86  Color fallbackColor;
87  if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), fallbackColor))
88  return false;
89 
90  return m_path.contains(point, fillRule);
91 }
92 
93 bool RenderSVGPath::strokeContains(const FloatPoint& point, bool requiresStroke)
94 {
95  if (!m_strokeAndMarkerBoundingBox.contains(point))
96  return false;
97 
98  Color fallbackColor;
99  if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
100  return false;
101 
102  if (shouldStrokeZeroLengthSubpath())
103  return zeroLengthSubpathRect().contains(point);
104 
105  BoundingRectStrokeStyleApplier strokeStyle(this, style());
106  return m_path.strokeContains(&strokeStyle, point);
107 }
108 
109 void RenderSVGPath::layout()
110 {
111  LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
112  SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
113 
114  bool updateCachedBoundariesInParents = false;
115 
116  bool needsPathUpdate = m_needsPathUpdate;
117  if (needsPathUpdate) {
118  m_path.clear();
119  element->toPathData(m_path);
120  m_needsPathUpdate = false;
121  updateCachedBoundariesInParents = true;
122  }
123 
124  if (m_needsTransformUpdate) {
125  m_localTransform = element->animatedLocalTransform();
126  m_needsTransformUpdate = false;
127  updateCachedBoundariesInParents = true;
128  }
129 
130  if (m_needsBoundariesUpdate)
131  updateCachedBoundariesInParents = true;
132 
133  // Invalidate all resources of this client if our layout changed.
134  if (m_everHadLayout && selfNeedsLayout()) {
135  SVGResourcesCache::clientLayoutChanged(this);
136  m_markerLayoutInfo.clear();
137  }
138 
139  // At this point LayoutRepainter already grabbed the old bounds,
140  // recalculate them now so repaintAfterLayout() uses the new bounds.
141  if (needsPathUpdate || m_needsBoundariesUpdate) {
142  updateCachedBoundaries();
143  m_needsBoundariesUpdate = false;
144  }
145 
146  // If our bounds changed, notify the parents.
147  if (updateCachedBoundariesInParents)
148  RenderSVGModelObject::setNeedsBoundariesUpdate();
149 
150  repainter.repaintAfterLayout();
151  setNeedsLayout(false);
152 }
153 
154 bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
155 {
156  // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
157  // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
158  return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap && !m_fillBoundingBox.width() && !m_fillBoundingBox.height();
159 }
160 
161 FloatRect RenderSVGPath::zeroLengthSubpathRect() const
162 {
163  SVGElement* svgElement = static_cast<SVGElement*>(node());
164  float strokeWidth = style()->svgStyle()->strokeWidth().value(svgElement);
165  return FloatRect(m_fillBoundingBox.x() - strokeWidth / 2, m_fillBoundingBox.y() - strokeWidth / 2, strokeWidth, strokeWidth);
166 }
167 
168 void RenderSVGPath::setupSquareCapPath(Path*& usePath, int& applyMode)
169 {
170  // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
171  // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
172  DEFINE_STATIC_LOCAL(Path, tempPath, ());
173 
174  applyMode = ApplyToFillMode;
175  usePath = &tempPath;
176  usePath->clear();
177  if (style()->svgStyle()->capStyle() == SquareCap)
178  usePath->addRect(zeroLengthSubpathRect());
179  else
180  usePath->addEllipse(zeroLengthSubpathRect());
181 }
182 
183 bool RenderSVGPath::setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver& stateSaver)
184 {
185  DEFINE_STATIC_LOCAL(Path, tempPath, ());
186 
187  SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
188  AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
189  if (!nonScalingStrokeTransform.isInvertible())
190  return false;
191 
192  tempPath = m_path;
193  usePath = &tempPath;
194  tempPath.transform(nonScalingStrokeTransform);
195 
196  stateSaver.save();
197  stateSaver.context()->concatCTM(nonScalingStrokeTransform.inverse());
198  return true;
199 }
200 
201 void RenderSVGPath::fillAndStrokePath(GraphicsContext* context)
202 {
203  RenderStyle* style = this->style();
204 
205  Color fallbackColor;
206  if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
207  if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode))
208  fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, &m_path);
209  else if (fallbackColor.isValid()) {
210  RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
211  fallbackResource->setColor(fallbackColor);
212  if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
213  fallbackResource->postApplyResource(this, context, ApplyToFillMode, &m_path);
214  }
215  }
216 
217  fallbackColor = Color();
218  RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor);
219  if (!strokePaintingResource)
220  return;
221 
222  Path* usePath = &m_path;
223  int applyMode = ApplyToStrokeMode;
224 
225  bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
226 
227  GraphicsContextStateSaver stateSaver(*context, false);
228 
229  // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
230  // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
231  // FIXME: this does not work for zero-length subpaths, only when total path is zero-length
232  if (shouldStrokeZeroLengthSubpath())
233  setupSquareCapPath(usePath, applyMode);
234  else if (nonScalingStroke) {
235  if (!setupNonScalingStrokePath(usePath, stateSaver))
236  return;
237  }
238 
239  if (strokePaintingResource->applyResource(this, style, context, applyMode))
240  strokePaintingResource->postApplyResource(this, context, applyMode, usePath);
241  else if (fallbackColor.isValid()) {
242  RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
243  fallbackResource->setColor(fallbackColor);
244  if (fallbackResource->applyResource(this, style, context, applyMode))
245  fallbackResource->postApplyResource(this, context, applyMode, usePath);
246  }
247 }
248 
249 void RenderSVGPath::paint(PaintInfo& paintInfo, const LayoutPoint&)
250 {
251  if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty())
252  return;
253 
254  FloatRect boundingBox = repaintRectInLocalCoordinates();
255  if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
256  return;
257 
258  PaintInfo childPaintInfo(paintInfo);
259  bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
260  if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
261  GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
262  childPaintInfo.applyTransform(m_localTransform);
263 
264  if (childPaintInfo.phase == PaintPhaseForeground) {
265  PaintInfo savedInfo(childPaintInfo);
266 
267  if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) {
268  const SVGRenderStyle* svgStyle = style()->svgStyle();
269  if (svgStyle->shapeRendering() == SR_CRISPEDGES)
270  childPaintInfo.context->setShouldAntialias(false);
271 
272  fillAndStrokePath(childPaintInfo.context);
273 
274  if (svgStyle->hasMarkers())
275  m_markerLayoutInfo.drawMarkers(childPaintInfo);
276  }
277 
278  SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context);
279  }
280 
281  if (drawsOutline)
282  paintOutline(childPaintInfo.context, IntRect(boundingBox));
283  }
284 }
285 
286 // This method is called from inside paintOutline() since we call paintOutline()
287 // while transformed to our coord system, return local coords
288 void RenderSVGPath::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&)
289 {
290  LayoutRect rect = enclosingLayoutRect(repaintRectInLocalCoordinates());
291  if (!rect.isEmpty())
292  rects.append(rect);
293 }
294 
295 bool RenderSVGPath::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
296 {
297  // We only draw in the forground phase, so we only hit-test then.
298  if (hitTestAction != HitTestForeground)
299  return false;
300 
301  FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent);
302 
303  if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
304  return false;
305 
306  PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style()->pointerEvents());
307  bool isVisible = (style()->visibility() == VISIBLE);
308  if (isVisible || !hitRules.requireVisible) {
309  const SVGRenderStyle* svgStyle = style()->svgStyle();
310  WindRule fillRule = svgStyle->fillRule();
311  if (request.svgClipContent())
312  fillRule = svgStyle->clipRule();
313  if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke))
314  || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) {
315  updateHitTestResult(result, roundedLayoutPoint(localPoint));
316  return true;
317  }
318  }
319  return false;
320 }
321 
322 FloatRect RenderSVGPath::calculateMarkerBoundsIfNeeded()
323 {
324  SVGElement* svgElement = static_cast<SVGElement*>(node());
325  ASSERT(svgElement && svgElement->document());
326  if (!svgElement->isStyled())
327  return FloatRect();
328 
329  SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
330  if (!styledElement->supportsMarkers())
331  return FloatRect();
332 
333  const SVGRenderStyle* svgStyle = style()->svgStyle();
334  ASSERT(svgStyle->hasMarkers());
335 
336  SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
337  if (!resources)
338  return FloatRect();
339 
340  RenderSVGResourceMarker* markerStart = resources->markerStart();
341  RenderSVGResourceMarker* markerMid = resources->markerMid();
342  RenderSVGResourceMarker* markerEnd = resources->markerEnd();
343  if (!markerStart && !markerMid && !markerEnd)
344  return FloatRect();
345 
346  return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, svgStyle->strokeWidth().value(svgElement), m_path);
347 }
348 
349 void RenderSVGPath::updateCachedBoundaries()
350 {
351  if (m_path.isEmpty()) {
352  m_fillBoundingBox = FloatRect();
353  m_strokeAndMarkerBoundingBox = FloatRect();
354  m_repaintBoundingBox = FloatRect();
355  return;
356  }
357 
358  // Cache _unclipped_ fill bounding box, used for calculations in resources
359  m_fillBoundingBox = m_path.boundingRect();
360 
361  // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
362  // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
363  if (shouldStrokeZeroLengthSubpath()) {
364  m_strokeAndMarkerBoundingBox = zeroLengthSubpathRect();
365  // Cache smallest possible repaint rectangle
366  m_repaintBoundingBox = m_strokeAndMarkerBoundingBox;
367  SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
368  return;
369  }
370 
371  // Cache _unclipped_ stroke bounding box, used for calculations in resources (includes marker boundaries)
372  m_strokeAndMarkerBoundingBox = m_fillBoundingBox;
373 
374  const SVGRenderStyle* svgStyle = style()->svgStyle();
375  if (svgStyle->hasStroke()) {
376  BoundingRectStrokeStyleApplier strokeStyle(this, style());
377  m_strokeAndMarkerBoundingBox.unite(m_path.strokeBoundingRect(&strokeStyle));
378  }
379 
380  if (svgStyle->hasMarkers()) {
381  FloatRect markerBounds = calculateMarkerBoundsIfNeeded();
382  if (!markerBounds.isEmpty())
383  m_strokeAndMarkerBoundingBox.unite(markerBounds);
384  }
385 
386  // Cache smallest possible repaint rectangle
387  m_repaintBoundingBox = m_strokeAndMarkerBoundingBox;
388  SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
389 }
390 
39147}
39248
39349#endif // ENABLE(SVG)

Source/WebCore/rendering/svg/RenderSVGPath.h

44 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
55 * Copyright (C) 2006 Apple Computer, Inc
66 * Copyright (C) 2009 Google, Inc.
 7 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
 8 * Copyright (C) 2011 University of Szeged
79 *
810 * This library is free software; you can redistribute it and/or
911 * modify it under the terms of the GNU Library General Public

2527#define RenderSVGPath_h
2628
2729#if ENABLE(SVG)
28 #include "AffineTransform.h"
29 #include "FloatRect.h"
30 #include "RenderSVGModelObject.h"
31 #include "SVGMarkerLayoutInfo.h"
 30#include "RenderSVGShape.h"
3231
3332namespace WebCore {
3433
35 class FloatPoint;
36 class GraphicsContextStateSaver;
37 class RenderSVGContainer;
38 class SVGStyledTransformableElement;
39 
40 class RenderSVGPath : public RenderSVGModelObject {
 34class RenderSVGPath : public RenderSVGShape {
4135public:
42  explicit RenderSVGPath(SVGStyledTransformableElement*);
 36 RenderSVGPath(SVGStyledTransformableElement*);
4337 virtual ~RenderSVGPath();
4438
45  const Path& path() const { return m_path; }
46  void setNeedsPathUpdate() { m_needsPathUpdate = true; }
47  virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
48  virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
49 
5039private:
51  // Hit-detection seperated for the fill and the stroke
52  bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO);
53  bool strokeContains(const FloatPoint&, bool requiresStroke = true);
54 
55  virtual FloatRect objectBoundingBox() const { return m_fillBoundingBox; }
56  virtual FloatRect strokeBoundingBox() const { return m_strokeAndMarkerBoundingBox; }
57  virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
58  virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
59 
6040 virtual bool isSVGPath() const { return true; }
6141 virtual const char* renderName() const { return "RenderSVGPath"; }
62 
63  virtual void layout();
64  virtual void paint(PaintInfo&, const LayoutPoint&);
65  virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint&);
66 
67  virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
68 
69  FloatRect calculateMarkerBoundsIfNeeded();
70  void updateCachedBoundaries();
71 
72  void setupSquareCapPath(Path*& usePath, int& applyMode);
73  bool setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver&);
74  bool shouldStrokeZeroLengthSubpath() const;
75  FloatRect zeroLengthSubpathRect() const;
76 
77 private:
78  virtual AffineTransform localTransform() const { return m_localTransform; }
79  void fillAndStrokePath(GraphicsContext*);
80 
81  bool m_needsBoundariesUpdate : 1;
82  bool m_needsPathUpdate : 1;
83  bool m_needsTransformUpdate : 1;
84 
85  mutable Path m_path;
86  FloatRect m_fillBoundingBox;
87  FloatRect m_strokeAndMarkerBoundingBox;
88  FloatRect m_repaintBoundingBox;
89  SVGMarkerLayoutInfo m_markerLayoutInfo;
90  AffineTransform m_localTransform;
9142};
9243
93 inline RenderSVGPath* toRenderSVGPath(RenderObject* object)
94 {
95  ASSERT(!object || object->isSVGPath());
96  return static_cast<RenderSVGPath*>(object);
97 }
98 
99 inline const RenderSVGPath* toRenderSVGPath(const RenderObject* object)
100 {
101  ASSERT(!object || object->isSVGPath());
102  return static_cast<const RenderSVGPath*>(object);
103 }
104 
105 // This will catch anyone doing an unnecessary cast.
106 void toRenderSVGPath(const RenderSVGPath*);
107 
10844}
10945
11046#endif // ENABLE(SVG)

Source/WebCore/rendering/svg/RenderSVGRect.cpp

 1/*
 2 * Copyright (C) 2011 University of Szeged
 3 * Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
 4 * All rights reserved.
 5 *
 6 * Redistribution and use in source and binary forms, with or without
 7 * modification, are permitted provided that the following conditions
 8 * are met:
 9 * 1. Redistributions of source code must retain the above copyright
 10 * notice, this list of conditions and the following disclaimer.
 11 * 2. Redistributions in binary form must reproduce the above copyright
 12 * notice, this list of conditions and the following disclaimer in the
 13 * documentation and/or other materials provided with the distribution.
 14 *
 15 * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28#include "config.h"
 29
 30#if ENABLE(SVG)
 31#include "RenderSVGRect.h"
 32
 33#include "SVGNames.h"
 34#include "SVGRectElement.h"
 35
 36namespace WebCore {
 37
 38RenderSVGRect::RenderSVGRect(SVGStyledTransformableElement* node)
 39 : RenderSVGShape(node)
 40{
 41}
 42
 43RenderSVGRect::~RenderSVGRect()
 44{
 45}
 46
 47void RenderSVGRect::createShape()
 48{
 49 // Clear m_rect.
 50 m_rect = FloatRect();
 51 SVGRectElement* rect = static_cast<SVGRectElement*>(node());
 52 bool m_hasRx = rect->hasAttribute(SVGNames::rxAttr);
 53 bool m_hasRy = rect->hasAttribute(SVGNames::ryAttr);
 54 // Fallback to the parent if rect has special features.
 55 if (m_hasRx || m_hasRy || !style()->svgStyle()->strokeDashArray().isEmpty()) {
 56 RenderSVGShape::createShape();
 57 return;
 58 }
 59 float widthValue = rect->width().value(rect);
 60 if (widthValue <= 0)
 61 return;
 62
 63 float heightValue = rect->height().value(rect);
 64 if (heightValue <= 0)
 65 return;
 66
 67 float xValue = rect->x().value(rect);
 68 float yValue = rect->y().value(rect);
 69 m_rect = FloatRect(xValue, yValue, widthValue, heightValue);
 70}
 71
 72
 73FloatRect RenderSVGRect::objectBoundingBox() const
 74{
 75 if (hasPath())
 76 return RenderSVGShape::objectBoundingBox();
 77 return m_rect;
 78}
 79
 80FloatRect RenderSVGRect::strokeBoundingBox()
 81{
 82 if (hasPath())
 83 return RenderSVGShape::strokeBoundingBox();
 84 // If we inflate the m_rect with the half size strokeWidth, we get the strokeBoundingBox in non-fallback path mode.
 85 BoundingRectStrokeStyleApplier strokeStyle(this, style());
 86 FloatRect strokeRect = m_rect;
 87 strokeRect.inflate(this->strokeWidth() / 2);
 88 return strokeRect;
 89}
 90
 91void RenderSVGRect::fillShape(GraphicsContext* context)
 92{
 93 if (hasPath())
 94 RenderSVGShape::fillShape(context);
 95 else
 96 context->fillRect(m_rect);
 97}
 98
 99void RenderSVGRect::strokeShape(GraphicsContext* context)
 100{
 101 if (hasPath()) {
 102 RenderSVGShape::strokeShape(context);
 103 return;
 104 }
 105 context->strokeRect(m_rect, this->strokeWidth());
 106}
 107
 108bool RenderSVGRect::strokeContainsSlowCase(const FloatPoint& point)
 109{
 110 if (hasPath())
 111 return RenderSVGShape::strokeContainsSlowCase(point);
 112
 113 // To deceide the stroke containing we create two rects which represent the inner and
 114 // the outer stroke borders. The containing exists, if the point is between them.
 115 float strokeWidth = this->strokeWidth();
 116 FloatRect innerStrokeRect = m_rect;
 117 FloatRect outerStrokeRect = m_rect;
 118 innerStrokeRect.inflate(-strokeWidth / 2);
 119 outerStrokeRect.inflate(strokeWidth / 2);
 120 return (determinePointLocation(point, innerStrokeRect) != InsideShape
 121 && determinePointLocation(point, outerStrokeRect) != OutsideShape) ? true : false;
 122}
 123
 124bool RenderSVGRect::fillContainsSlowCase(const FloatPoint& point, const WindRule&) const
 125{
 126 return (determinePointLocation(point, m_rect) != OutsideShape) ? true : false;
 127}
 128
 129PointLocation RenderSVGRect::determinePointLocation(const FloatPoint& point, const FloatRect& rect) const
 130{
 131 // Test whether the rect contains the certain point or not
 132 if (!rect.contains(point))
 133 return OutsideShape;
 134 return (rect.x() < point.x() && rect.maxX() > point.x() && rect.y() < point.y() && rect.maxY() > point.y()) ? InsideShape : OnStroke;
 135}
 136
 137}
 138
 139#endif // ENABLE(SVG)

Source/WebCore/rendering/svg/RenderSVGRect.h

 1/*
 2 * Copyright (C) 2011 University of Szeged
 3 * Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
 4 * All rights reserved.
 5 *
 6 * Redistribution and use in source and binary forms, with or without
 7 * modification, are permitted provided that the following conditions
 8 * are met:
 9 * 1. Redistributions of source code must retain the above copyright
 10 * notice, this list of conditions and the following disclaimer.
 11 * 2. Redistributions in binary form must reproduce the above copyright
 12 * notice, this list of conditions and the following disclaimer in the
 13 * documentation and/or other materials provided with the distribution.
 14 *
 15 * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 26 */
 27
 28#ifndef RenderSVGRect_h
 29#define RenderSVGRect_h
 30
 31#if ENABLE(SVG)
 32#include "RenderSVGPath.h"
 33
 34namespace WebCore {
 35
 36class RenderSVGRect : public RenderSVGShape {
 37public:
 38 explicit RenderSVGRect(SVGStyledTransformableElement*);
 39 virtual ~RenderSVGRect();
 40
 41private:
 42 virtual bool isSVGRect() const { return true; }
 43 virtual const char* renderName() const { return "RenderSVGRect"; }
 44
 45 void createShape();
 46 bool isEmpty() const { return hasPath() ? RenderSVGShape::isEmpty() : m_rect.isEmpty(); };
 47 void fillShape(GraphicsContext*);
 48 FloatRect objectBoundingBox() const;
 49 FloatRect strokeBoundingBox();
 50 void strokeShape(GraphicsContext*);
 51 bool strokeContainsSlowCase(const FloatPoint&);
 52 bool fillContainsSlowCase(const FloatPoint&, const WindRule&) const;
 53 PointLocation determinePointLocation(const FloatPoint&, const FloatRect&) const;
 54
 55private:
 56 FloatRect m_rect;
 57};
 58
 59}
 60
 61#endif // ENABLE(SVG)
 62#endif

Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp

@@bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData
242242 }
243243
244244 // Only shapes, paths and texts are allowed for clipping.
245  if (!renderer->isSVGPath() && !renderer->isSVGText())
 245 if (!renderer->isSVGShape() && !renderer->isSVGText())
246246 continue;
247247
248248 // Save the old RenderStyle of the current object for restoring after drawing

@@void RenderSVGResourceClipper::calculateClipContentRepaintRect()
284284 RenderObject* renderer = childNode->renderer();
285285 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer)
286286 continue;
287  if (!renderer->isSVGPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer())
 287 if (!renderer->isSVGShape() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer())
288288 continue;
289289 RenderStyle* style = renderer->style();
290290 if (!style || style->display() == NONE || style->visibility() != VISIBLE)

@@bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
310310 RenderObject* renderer = childNode->renderer();
311311 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer)
312312 continue;
313  if (!renderer->isSVGPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer())
 313 if (!renderer->isSVGShape() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer())
314314 continue;
315315 IntPoint hitPoint;
316316 HitTestResult result(hitPoint);

Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp

@@void RenderSVGResourceContainer::registerResource()
180180// FIXME: This does not belong here.
181181AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
182182{
183  if (!object->isSVGPath())
 183 if (!object->isSVGShape())
184184 return resourceTransform;
185185
186186 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node());

Source/WebCore/rendering/svg/RenderSVGShape.cpp

 1/*
 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
 3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org>
 4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org>
 5 * Copyright (C) 2009 Google, Inc.
 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
 7 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
 10 * Copyright (C) 2011 University of Szeged
 11 *
 12 * This library is free software; you can redistribute it and/or
 13 * modify it under the terms of the GNU Library General Public
 14 * License as published by the Free Software Foundation; either
 15 * version 2 of the License, or (at your option) any later version.
 16 *
 17 * This library is distributed in the hope that it will be useful,
 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 20 * Library General Public License for more details.
 21 *
 22 * You should have received a copy of the GNU Library General Public License
 23 * along with this library; see the file COPYING.LIB. If not, write to
 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 25 * Boston, MA 02110-1301, USA.
 26 */
 27
 28#include "config.h"
 29
 30#if ENABLE(SVG)
 31#include "RenderSVGShape.h"
 32
 33#include "FloatPoint.h"
 34#include "FloatQuad.h"
 35#include "GraphicsContext.h"
 36#include "HitTestRequest.h"
 37#include "PointerEventsHitRules.h"
 38#include "RenderSVGContainer.h"
 39#include "RenderSVGResourceMarker.h"
 40#include "RenderSVGResourceSolidColor.h"
 41#include "SVGPathElement.h"
 42#include "SVGRenderSupport.h"
 43#include "SVGResources.h"
 44#include "SVGStyledTransformableElement.h"
 45#include "SVGTransformList.h"
 46#include "SVGURIReference.h"
 47#include "StrokeStyleApplier.h"
 48#include <wtf/MathExtras.h>
 49
 50namespace WebCore {
 51
 52RenderSVGShape::RenderSVGShape(SVGStyledTransformableElement* node)
 53 : RenderSVGModelObject(node)
 54 , m_needsBoundariesUpdate(false) // default is false, the cached rects are empty from the beginning
 55 , m_needsShapeUpdate(true) // default is true, so we grab a Path object once from SVGStyledTransformableElement
 56 , m_needsTransformUpdate(true) // default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement
 57{
 58}
 59
 60RenderSVGShape::~RenderSVGShape()
 61{
 62}
 63
 64void RenderSVGShape::createShape()
 65{
 66 m_path = adoptPtr(new Path);
 67 ASSERT(isEmpty());
 68
 69 SVGPathElement* element = static_cast<SVGPathElement*>(node());
 70 element->toPathData(path());
 71}
 72
 73bool RenderSVGShape::isEmpty() const
 74{
 75 return path().isEmpty();
 76}
 77
 78void RenderSVGShape::fillShape(GraphicsContext* context)
 79{
 80 context->fillPath(path());
 81}
 82
 83FloatRect RenderSVGShape::objectBoundingBox() const
 84{
 85 return m_path->boundingRect();
 86}
 87
 88FloatRect RenderSVGShape::strokeBoundingBox()
 89{
 90 BoundingRectStrokeStyleApplier strokeStyle(this, style());
 91 return path().strokeBoundingRect(&strokeStyle);
 92}
 93
 94void RenderSVGShape::strokeShape(GraphicsContext* context)
 95{
 96 context->strokePath(path());
 97}
 98
 99bool RenderSVGShape::strokeContainsSlowCase(const FloatPoint& point)
 100{
 101 BoundingRectStrokeStyleApplier applier(this, style());
 102 return path().strokeContains(&applier, point);
 103}
 104
 105bool RenderSVGShape::fillContainsSlowCase(const FloatPoint& point, const WindRule& fillRule) const
 106{
 107 return path().contains(point, fillRule);
 108}
 109
 110bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule)
 111{
 112 if (!m_fillBoundingBox.contains(point))
 113 return false;
 114
 115 Color fallbackColor;
 116 if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), fallbackColor))
 117 return false;
 118
 119 return fillContainsSlowCase(point, fillRule);
 120}
 121
 122bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke)
 123{
 124 if (!m_strokeAndMarkerBoundingBox.contains(point))
 125 return false;
 126
 127 Color fallbackColor;
 128 if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
 129 return false;
 130
 131 if (shouldStrokeZeroLengthSubpath())
 132 return zeroLengthSubpathRect().contains(point);
 133
 134 return strokeContainsSlowCase(point);
 135}
 136
 137void RenderSVGShape::layout()
 138{
 139 LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
 140 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
 141
 142 bool updateCachedBoundariesInParents = false;
 143
 144 bool needsShapeUpdate = m_needsShapeUpdate;
 145 if (needsShapeUpdate) {;
 146 createShape();
 147 m_needsShapeUpdate = false;
 148 updateCachedBoundariesInParents = true;
 149 }
 150
 151 if (m_needsTransformUpdate) {
 152 m_localTransform = element->animatedLocalTransform();
 153 m_needsTransformUpdate = false;
 154 updateCachedBoundariesInParents = true;
 155 }
 156
 157 if (m_needsBoundariesUpdate)
 158 updateCachedBoundariesInParents = true;
 159
 160 // Invalidate all resources of this client if our layout changed.
 161 if (m_everHadLayout && selfNeedsLayout()) {
 162 SVGResourcesCache::clientLayoutChanged(this);
 163 m_markerLayoutInfo.clear();
 164 }
 165
 166 // At this point LayoutRepainter already grabbed the old bounds,
 167 // recalculate them now so repaintAfterLayout() uses the new bounds.
 168 if (needsShapeUpdate || m_needsBoundariesUpdate) {
 169 updateCachedBoundaries();
 170 m_needsBoundariesUpdate = false;
 171 }
 172
 173 // If our bounds changed, notify the parents.
 174 if (updateCachedBoundariesInParents)
 175 RenderSVGModelObject::setNeedsBoundariesUpdate();
 176
 177 repainter.repaintAfterLayout();
 178 setNeedsLayout(false);
 179}
 180
 181bool RenderSVGShape::shouldStrokeZeroLengthSubpath() const
 182{
 183 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
 184 // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
 185 return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap && !m_fillBoundingBox.width() && !m_fillBoundingBox.height();
 186}
 187
 188FloatRect RenderSVGShape::zeroLengthSubpathRect() const
 189{
 190 float strokeWidth = this->strokeWidth();
 191 return FloatRect(m_fillBoundingBox.x() - strokeWidth / 2, m_fillBoundingBox.y() - strokeWidth / 2, strokeWidth, strokeWidth);
 192}
 193
 194void RenderSVGShape::setupSquareCapPath(Path*& usePath, int& applyMode)
 195{
 196 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
 197 // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
 198 DEFINE_STATIC_LOCAL(Path, tempPath, ());
 199
 200 applyMode = ApplyToFillMode;
 201 usePath = &tempPath;
 202 usePath->clear();
 203 if (style()->svgStyle()->capStyle() == SquareCap)
 204 usePath->addRect(zeroLengthSubpathRect());
 205 else
 206 usePath->addEllipse(zeroLengthSubpathRect());
 207}
 208
 209bool RenderSVGShape::setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver& stateSaver)
 210{
 211 DEFINE_STATIC_LOCAL(Path, tempPath, ());
 212
 213 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
 214 AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
 215 if (!nonScalingStrokeTransform.isInvertible())
 216 return false;
 217
 218 tempPath = *m_path;
 219 usePath = &tempPath;
 220 tempPath.transform(nonScalingStrokeTransform);
 221
 222 stateSaver.save();
 223 stateSaver.context()->concatCTM(nonScalingStrokeTransform.inverse());
 224 return true;
 225}
 226
 227void RenderSVGShape::fillAndStrokePath(GraphicsContext* context)
 228{
 229 RenderStyle* style = this->style();
 230
 231 Color fallbackColor;
 232 if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
 233 if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) {
 234 fillShape(context);
 235 } else if (fallbackColor.isValid()) {
 236 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
 237 fallbackResource->setColor(fallbackColor);
 238 if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
 239 fillShape(context);
 240 }
 241 }
 242
 243 fallbackColor = Color();
 244 RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor);
 245 if (!strokePaintingResource)
 246 return;
 247
 248 Path* usePath;
 249 int applyMode = ApplyToStrokeMode;
 250
 251 bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
 252
 253 GraphicsContextStateSaver stateSaver(*context, false);
 254
 255 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
 256 // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
 257 // FIXME: this does not work for zero-length subpaths, only when total path is zero-length
 258 if (shouldStrokeZeroLengthSubpath()) {
 259 RenderSVGShape::createShape();
 260 usePath = m_path.get();
 261 setupSquareCapPath(usePath, applyMode);
 262 } else if (nonScalingStroke) {
 263 RenderSVGShape::createShape();
 264 usePath = m_path.get();
 265 if (!setupNonScalingStrokePath(usePath, stateSaver))
 266 return;
 267 }
 268 if (strokePaintingResource->applyResource(this, style, context, applyMode)) {
 269 strokeShape(context);
 270 return;
 271 }
 272 if (!fallbackColor.isValid())
 273 return;
 274 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
 275 fallbackResource->setColor(fallbackColor);
 276 if (fallbackResource->applyResource(this, style, context, applyMode))
 277 strokeShape(context);
 278}
 279
 280void RenderSVGShape::paint(PaintInfo& paintInfo, const IntPoint&)
 281{
 282 if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || isEmpty())
 283 return;
 284 FloatRect boundingBox = repaintRectInLocalCoordinates();
 285 if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
 286 return;
 287 PaintInfo childPaintInfo(paintInfo);
 288 bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
 289 if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
 290 GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
 291 childPaintInfo.applyTransform(m_localTransform);
 292
 293 if (childPaintInfo.phase == PaintPhaseForeground) {
 294 PaintInfo savedInfo(childPaintInfo);
 295
 296 if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) {
 297 const SVGRenderStyle* svgStyle = style()->svgStyle();
 298 if (svgStyle->shapeRendering() == SR_CRISPEDGES)
 299 childPaintInfo.context->setShouldAntialias(false);
 300
 301 fillAndStrokePath(childPaintInfo.context);
 302
 303 if (svgStyle->hasMarkers())
 304 m_markerLayoutInfo.drawMarkers(childPaintInfo);
 305 }
 306
 307 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context);
 308 }
 309
 310 if (drawsOutline)
 311 paintOutline(childPaintInfo.context, IntRect(boundingBox));
 312 }
 313}
 314
 315// This method is called from inside paintOutline() since we call paintOutline()
 316// while transformed to our coord system, return local coords
 317void RenderSVGShape::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint&)
 318{
 319 LayoutRect rect = enclosingLayoutRect(repaintRectInLocalCoordinates());
 320 if (!rect.isEmpty())
 321 rects.append(rect);
 322}
 323
 324bool RenderSVGShape::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
 325{
 326 // We only draw in the forground phase, so we only hit-test then.
 327 if (hitTestAction != HitTestForeground)
 328 return false;
 329
 330 FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent);
 331
 332 if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
 333 return false;
 334
 335 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style()->pointerEvents());
 336 bool isVisible = (style()->visibility() == VISIBLE);
 337 if (isVisible || !hitRules.requireVisible) {
 338 const SVGRenderStyle* svgStyle = style()->svgStyle();
 339 WindRule fillRule = svgStyle->fillRule();
 340 if (request.svgClipContent())
 341 fillRule = svgStyle->clipRule();
 342 if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke))
 343 || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) {
 344 updateHitTestResult(result, roundedLayoutPoint(localPoint));
 345 return true;
 346 }
 347 }
 348 return false;
 349}
 350
 351FloatRect RenderSVGShape::calculateMarkerBoundsIfNeeded()
 352{
 353 SVGElement* svgElement = static_cast<SVGElement*>(node());
 354 ASSERT(svgElement && svgElement->document());
 355 if (!svgElement->isStyled())
 356 return FloatRect();
 357
 358 SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
 359 if (!styledElement->supportsMarkers())
 360 return FloatRect();
 361
 362 ASSERT(style()->svgStyle()->hasMarkers());
 363
 364 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
 365 if (!resources)
 366 return FloatRect();
 367
 368 RenderSVGResourceMarker* markerStart = resources->markerStart();
 369 RenderSVGResourceMarker* markerMid = resources->markerMid();
 370 RenderSVGResourceMarker* markerEnd = resources->markerEnd();
 371 if (!markerStart && !markerMid && !markerEnd)
 372 return FloatRect();
 373
 374 return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, markerEnd, strokeWidth(), path());
 375}
 376
 377void RenderSVGShape::updateCachedBoundaries()
 378{
 379 if (isEmpty()) {
 380 m_fillBoundingBox = FloatRect();
 381 m_strokeAndMarkerBoundingBox = FloatRect();
 382 m_repaintBoundingBox = FloatRect();
 383 return;
 384 }
 385
 386 // Cache _unclipped_ fill bounding box, used for calculations in resources
 387 m_fillBoundingBox = objectBoundingBox();
 388
 389 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
 390 // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
 391 if (shouldStrokeZeroLengthSubpath()) {
 392 m_strokeAndMarkerBoundingBox = zeroLengthSubpathRect();
 393 // Cache smallest possible repaint rectangle
 394 m_repaintBoundingBox = m_strokeAndMarkerBoundingBox;
 395 SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
 396 return;
 397 }
 398
 399 // Cache _unclipped_ stroke bounding box, used for calculations in resources (includes marker boundaries)
 400 m_strokeAndMarkerBoundingBox = m_fillBoundingBox;
 401
 402 const SVGRenderStyle* svgStyle = style()->svgStyle();
 403 if (svgStyle->hasStroke())
 404 m_strokeAndMarkerBoundingBox.unite(strokeBoundingBox());
 405
 406 if (isSVGPath()) {
 407 if (svgStyle->hasMarkers()) {
 408 FloatRect markerBounds = calculateMarkerBoundsIfNeeded();
 409 if (!markerBounds.isEmpty())
 410 m_strokeAndMarkerBoundingBox.unite(markerBounds);
 411 }
 412 }
 413 // Cache smallest possible repaint rectangle
 414 m_repaintBoundingBox = m_strokeAndMarkerBoundingBox;
 415 SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
 416}
 417
 418float RenderSVGShape::strokeWidth() const
 419{
 420 SVGElement* svgElement = static_cast<SVGElement*>(node());
 421 return style()->svgStyle()->strokeWidth().value(svgElement);
 422}
 423
 424}

Source/WebCore/rendering/svg/RenderSVGShape.h

 1/*
 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
 5 * Copyright (C) 2006 Apple Computer, Inc
 6 * Copyright (C) 2009 Google, Inc.
 7 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
 8 * Copyright (C) 2011 University of Szeged
 9 *
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Library General Public
 12 * License as published by the Free Software Foundation; either
 13 * version 2 of the License, or (at your option) any later version.
 14 *
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 18 * Library General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU Library General Public License
 21 * along with this library; see the file COPYING.LIB. If not, write to
 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 23 * Boston, MA 02110-1301, USA.
 24 */
 25
 26#ifndef RenderSVGShape_h
 27#define RenderSVGShape_h
 28
 29#if ENABLE(SVG)
 30#include "AffineTransform.h"
 31#include "FloatRect.h"
 32#include "RenderSVGModelObject.h"
 33#include "SVGMarkerLayoutInfo.h"
 34#include "StrokeStyleApplier.h"
 35#include <wtf/OwnPtr.h>
 36
 37namespace WebCore {
 38
 39class FloatPoint;
 40class GraphicsContextStateSaver;
 41class RenderSVGContainer;
 42class RenderSVGPath;
 43class SVGStyledTransformableElement;
 44
 45enum PointLocation {
 46 InsideShape,
 47 OutsideShape,
 48 OnStroke
 49};
 50
 51class BoundingRectStrokeStyleApplier : public StrokeStyleApplier {
 52public:
 53 BoundingRectStrokeStyleApplier(const RenderObject* object, RenderStyle* style)
 54 : m_object(object)
 55 , m_style(style)
 56 {
 57 ASSERT(style);
 58 ASSERT(object);
 59 }
 60
 61 void strokeStyle(GraphicsContext* gc)
 62 {
 63 SVGRenderSupport::applyStrokeStyleToContext(gc, m_style, m_object);
 64 }
 65
 66private:
 67 const RenderObject* m_object;
 68 RenderStyle* m_style;
 69};
 70
 71class RenderSVGShape : public RenderSVGModelObject {
 72public:
 73 explicit RenderSVGShape(SVGStyledTransformableElement*);
 74 virtual ~RenderSVGShape();
 75
 76 void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
 77 virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
 78 virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
 79
 80private:
 81 // Hit-detection seperated for the fill and the stroke
 82 bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO);
 83 bool strokeContains(const FloatPoint&, bool requiresStroke = true);
 84
 85 virtual FloatRect strokeBoundingBox() const { return m_strokeAndMarkerBoundingBox; }
 86 virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
 87 virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
 88
 89 virtual bool isSVGShape() const { return true; }
 90 virtual const char* renderName() const { return "RenderSVGShape"; }
 91
 92 virtual void layout();
 93 virtual void paint(PaintInfo&, const LayoutPoint&);
 94 virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint&);
 95
 96 virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
 97
 98 FloatRect calculateMarkerBoundsIfNeeded();
 99 void updateCachedBoundaries();
 100
 101 void setupSquareCapPath(Path*& usePath, int& applyMode);
 102 bool setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver&);
 103 bool shouldStrokeZeroLengthSubpath() const;
 104 FloatRect zeroLengthSubpathRect() const;
 105
 106protected:
 107 virtual void createShape();
 108 virtual bool isEmpty() const;
 109 virtual void fillShape(GraphicsContext*);
 110 virtual FloatRect objectBoundingBox() const;
 111 virtual FloatRect strokeBoundingBox();
 112 virtual void strokeShape(GraphicsContext*);
 113 virtual bool strokeContainsSlowCase(const FloatPoint&);
 114 virtual bool fillContainsSlowCase(const FloatPoint&, const WindRule&) const;
 115 float strokeWidth() const;
 116
 117 Path& path() const
 118 {
 119 ASSERT(m_path.get());
 120 return *m_path;
 121 }
 122
 123 Path* pathPtr() const
 124 {
 125 ASSERT(m_path.get());
 126 return m_path.get();
 127 };
 128
 129 bool hasPath() const { return m_path.get(); }
 130
 131private:
 132 virtual AffineTransform localTransform() const { return m_localTransform; }
 133 void fillAndStrokePath(GraphicsContext*);
 134
 135 bool m_needsBoundariesUpdate : 1;
 136 bool m_needsShapeUpdate : 1;
 137 bool m_needsTransformUpdate : 1;
 138
 139 FloatRect m_fillBoundingBox;
 140 FloatRect m_strokeAndMarkerBoundingBox;
 141 FloatRect m_repaintBoundingBox;
 142 SVGMarkerLayoutInfo m_markerLayoutInfo;
 143 AffineTransform m_localTransform;
 144 OwnPtr<Path> m_path;
 145};
 146
 147inline RenderSVGShape* toRenderSVGShape(RenderObject* object)
 148{
 149 ASSERT(!object || object->isSVGShape());
 150 return static_cast<RenderSVGShape*>(object);
 151}
 152
 153inline const RenderSVGShape* toRenderSVGShape(const RenderObject* object)
 154{
 155 ASSERT(!object || object->isSVGShape());
 156 return static_cast<const RenderSVGShape*>(object);
 157}
 158
 159// This will catch anyone doing an unnecessary cast.
 160void toRenderSVGShape(const RenderSVGShape*);
 161
 162}
 163

Source/WebCore/rendering/svg/SVGRenderSupport.cpp

@@void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
225225 // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
226226 if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) {
227227 if (element->isStyled() && static_cast<SVGStyledElement*>(element)->hasRelativeLengths()) {
228  // When the layout size changed and when using relative values tell the RenderSVGPath to update its Path object
229  if (child->isSVGPath())
230  toRenderSVGPath(child)->setNeedsPathUpdate();
 228 // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
 229 if (child->isSVGShape())
 230 toRenderSVGShape(child)->setNeedsShapeUpdate();
231231
232232 needsLayout = true;
233233 }

Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp

5555#include "RenderSVGResourceRadialGradient.h"
5656#include "RenderSVGResourceSolidColor.h"
5757#include "RenderSVGRoot.h"
 58#include "RenderSVGShape.h"
5859#include "RenderSVGText.h"
5960#include "RenderTreeAsText.h"
6061#include "SVGCircleElement.h"

@@static void writeStyle(TextStream& ts, const RenderObject& object)
289290 writeNameValuePair(ts, "transform", object.localTransform());
290291 writeIfNotDefault(ts, "image rendering", style->imageRendering(), RenderStyle::initialImageRendering());
291292 writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity());
292  if (object.isSVGPath()) {
293  const RenderSVGPath& path = static_cast<const RenderSVGPath&>(object);
294  ASSERT(path.node());
295  ASSERT(path.node()->isSVGElement());
 293 if (object.isSVGShape()) {
 294 const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object);
 295 ASSERT(shape.node());
 296 ASSERT(shape.node()->isSVGElement());
296297
297298 Color fallbackColor;
298  if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGPath*>(&path), path.style(), fallbackColor)) {
 299 if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
299300 TextStreamSeparator s(" ");
300301 ts << " [stroke={" << s;
301302 writeSVGPaintingResource(ts, strokePaintingResource);
302303
303  SVGElement* element = static_cast<SVGElement*>(path.node());
 304 SVGElement* element = static_cast<SVGElement*>(shape.node());
304305 double dashOffset = svgStyle->strokeDashOffset().value(element);
305306 double strokeWidth = svgStyle->strokeWidth().value(element);
306307 const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();

@@static void writeStyle(TextStream& ts, const RenderObject& object)
322323 ts << "}]";
323324 }
324325
325  if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGPath*>(&path), path.style(), fallbackColor)) {
 326 if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
326327 TextStreamSeparator s(" ");
327328 ts << " [fill={" << s;
328329 writeSVGPaintingResource(ts, fillPaintingResource);

@@static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& obj
346347 return ts;
347348}
348349
349 static TextStream& operator<<(TextStream& ts, const RenderSVGPath& path)
 350static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
350351{
351  writePositionAndStyle(ts, path);
 352 writePositionAndStyle(ts, shape);
352353
353  ASSERT(path.node()->isSVGElement());
354  SVGElement* svgElement = static_cast<SVGElement*>(path.node());
 354 ASSERT(shape.node()->isSVGElement());
 355 SVGElement* svgElement = static_cast<SVGElement*>(shape.node());
355356
356357 if (svgElement->hasTagName(SVGNames::rectTag)) {
357358 SVGRectElement* element = static_cast<SVGRectElement*>(svgElement);

@@void writeSVGImage(TextStream& ts, const RenderSVGImage& image, int indent)
653654 writeResources(ts, image, indent);
654655}
655656
656 void write(TextStream& ts, const RenderSVGPath& path, int indent)
 657void write(TextStream& ts, const RenderSVGShape& shape, int indent)
657658{
658  writeStandardPrefix(ts, path, indent);
659  ts << path << "\n";
660  writeResources(ts, path, indent);
 659 writeStandardPrefix(ts, shape, indent);
 660 ts << shape << "\n";
 661 writeResources(ts, shape, indent);
661662}
662663
663664void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int indent)

Source/WebCore/rendering/svg/SVGRenderTreeAsText.h

@@class RenderImage;
4141class RenderObject;
4242class RenderSVGGradientStop;
4343class RenderSVGImage;
44 class RenderSVGPath;
 44class RenderSVGShape;
4545class RenderSVGRoot;
4646class RenderText;
4747class AffineTransform;
4848class SVGUnitTypes;
4949
5050// functions used by the main RenderTreeAsText code
51 void write(TextStream&, const RenderSVGPath&, int indent);
 51void write(TextStream&, const RenderSVGShape&, int indent);
5252void write(TextStream&, const RenderSVGRoot&, int indent);
5353void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent);
5454void writeSVGResourceContainer(TextStream&, const RenderObject&, int indent);

Source/WebCore/svg/SVGCircleElement.cpp

@@void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName)
124124 return;
125125
126126 if (isLengthAttribute) {
127  renderer->setNeedsPathUpdate();
 127 renderer->setNeedsShapeUpdate();
128128 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
129129 return;
130130 }

Source/WebCore/svg/SVGEllipseElement.cpp

@@void SVGEllipseElement::svgAttributeChanged(const QualifiedName& attrName)
129129 return;
130130
131131 if (isLengthAttribute) {
132  renderer->setNeedsPathUpdate();
 132 renderer->setNeedsShapeUpdate();
133133 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
134134 return;
135135 }

Source/WebCore/svg/SVGLineElement.cpp

@@void SVGLineElement::svgAttributeChanged(const QualifiedName& attrName)
129129 return;
130130
131131 if (isLengthAttribute) {
132  renderer->setNeedsPathUpdate();
 132 renderer->setNeedsShapeUpdate();
133133 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
134134 return;
135135 }

Source/WebCore/svg/SVGPathElement.cpp

@@void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName)
269269 }
270270
271271 if (renderer)
272  renderer->setNeedsPathUpdate();
 272 renderer->setNeedsShapeUpdate();
273273 }
274274
275275 if (renderer)

@@void SVGPathElement::pathSegListChanged(SVGPathSegRole role)
355355 if (!renderer)
356356 return;
357357
358  renderer->setNeedsPathUpdate();
 358 renderer->setNeedsShapeUpdate();
359359 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
360360}
361361
 362RenderObject* SVGPathElement::createRenderer(RenderArena* arena, RenderStyle*)
 363{
 364 // By default, any subclass is expected to do path-based drawing
 365 return new (arena) RenderSVGPath(this);
 366}
 367
362368}
363369
364370#endif // ENABLE(SVG)

Source/WebCore/svg/SVGPathElement.h

@@private:
122122 virtual void synchronizeRequiredExtensions() { SVGTests::synchronizeRequiredExtensions(this); }
123123 virtual void synchronizeSystemLanguage() { SVGTests::synchronizeSystemLanguage(this); }
124124
 125 RenderObject* createRenderer(RenderArena*, RenderStyle*);
 126
125127private:
126128 OwnPtr<SVGPathByteStream> m_pathByteStream;
127129 mutable SVGSynchronizableAnimatedProperty<SVGPathSegList> m_pathSegList;

Source/WebCore/svg/SVGPolyElement.cpp

@@void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName)
124124 return;
125125
126126 if (attrName == SVGNames::pointsAttr) {
127  renderer->setNeedsPathUpdate();
 127 renderer->setNeedsShapeUpdate();
128128 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
129129 return;
130130 }

Source/WebCore/svg/SVGRectElement.cpp

2525
2626#include "Attribute.h"
2727#include "RenderSVGPath.h"
 28#include "RenderSVGRect.h"
2829#include "RenderSVGResource.h"
2930#include "SVGElementInstance.h"
3031#include "SVGLength.h"

3233
3334namespace WebCore {
3435
 36class RenderSVGRect;
 37
3538// Animated property definitions
3639DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::xAttr, X, x)
3740DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::yAttr, Y, y)

@@void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName)
137140 if (SVGTests::handleAttributeChange(this, attrName))
138141 return;
139142
140  RenderSVGPath* renderer = static_cast<RenderSVGPath*>(this->renderer());
 143 RenderSVGRect* renderer = static_cast<RenderSVGRect*>(this->renderer());
141144 if (!renderer)
142145 return;
143146
144147 if (isLengthAttribute) {
145  renderer->setNeedsPathUpdate();
 148 renderer->setNeedsShapeUpdate();
146149 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
147150 return;
148151 }

@@bool SVGRectElement::selfHasRelativeLengths() const
198201 || ry().isRelative();
199202}
200203
 204RenderObject* SVGRectElement::createRenderer(RenderArena* arena, RenderStyle*)
 205{
 206 return new (arena) RenderSVGRect(this);
 207}
 208
201209}
202210
203211#endif // ENABLE(SVG)

Source/WebCore/svg/SVGRectElement.h

@@private:
5252
5353 virtual bool selfHasRelativeLengths() const;
5454
 55 RenderObject* createRenderer(RenderArena*, RenderStyle*);
 56
5557 BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGRectElement)
5658 DECLARE_ANIMATED_LENGTH(X, x)
5759 DECLARE_ANIMATED_LENGTH(Y, y)