| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> |
| 3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org> |
| 4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org> |
| 5 * Copyright (C) 2009 Google, Inc. | 5 * Copyright (C) 2009 Google, Inc. |
| 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
| 7 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 7 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
| 8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com> | 8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com> |
| 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> | 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> |
| 10 * Copyright (C) 2011 University of Szeged | 10 * Copyright (C) 2011 University of Szeged |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * | 21 * |
| 22 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 25 * Boston, MA 02110-1301, USA. | 25 * Boston, MA 02110-1301, USA. |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 #include "config.h" | 28 #include "config.h" |
| 29 #include "core/rendering/svg/RenderSVGShape.h" | 29 #include "core/rendering/svg/RenderSVGShape.h" |
| 30 | 30 |
| 31 #include "core/paint/SVGMarkerPainter.h" | 31 #include "core/paint/SVGShapePainter.h" |
| 32 #include "core/rendering/GraphicsContextAnnotator.h" | |
| 33 #include "core/rendering/HitTestRequest.h" | 32 #include "core/rendering/HitTestRequest.h" |
| 34 #include "core/rendering/PointerEventsHitRules.h" | 33 #include "core/rendering/PointerEventsHitRules.h" |
| 35 #include "core/rendering/svg/RenderSVGResourceMarker.h" | |
| 36 #include "core/rendering/svg/SVGPathData.h" | 34 #include "core/rendering/svg/SVGPathData.h" |
| 37 #include "core/rendering/svg/SVGRenderSupport.h" | 35 #include "core/rendering/svg/SVGRenderSupport.h" |
| 38 #include "core/rendering/svg/SVGRenderingContext.h" | 36 #include "core/rendering/svg/SVGRenderingContext.h" |
| 39 #include "core/rendering/svg/SVGResources.h" | 37 #include "core/rendering/svg/SVGResources.h" |
| 40 #include "core/rendering/svg/SVGResourcesCache.h" | 38 #include "core/rendering/svg/SVGResourcesCache.h" |
| 41 #include "core/svg/SVGGraphicsElement.h" | 39 #include "core/svg/SVGGraphicsElement.h" |
| 42 #include "platform/geometry/FloatPoint.h" | 40 #include "platform/geometry/FloatPoint.h" |
| 43 #include "platform/graphics/GraphicsContextStateSaver.h" | |
| 44 #include "wtf/MathExtras.h" | 41 #include "wtf/MathExtras.h" |
| 45 | 42 |
| 46 namespace blink { | 43 namespace blink { |
| 47 | 44 |
| 48 RenderSVGShape::RenderSVGShape(SVGGraphicsElement* node) | 45 RenderSVGShape::RenderSVGShape(SVGGraphicsElement* node) |
| 49 : RenderSVGModelObject(node) | 46 : RenderSVGModelObject(node) |
| 50 , m_needsBoundariesUpdate(false) // Default is false, the cached rects are e
mpty from the beginning. | 47 , m_needsBoundariesUpdate(false) // Default is false, the cached rects are e
mpty from the beginning. |
| 51 , m_needsShapeUpdate(true) // Default is true, so we grab a Path object once
from SVGGraphicsElement. | 48 , m_needsShapeUpdate(true) // Default is true, so we grab a Path object once
from SVGGraphicsElement. |
| 52 , m_needsTransformUpdate(true) // Default is true, so we grab a AffineTransf
orm object once from SVGGraphicsElement. | 49 , m_needsTransformUpdate(true) // Default is true, so we grab a AffineTransf
orm object once from SVGGraphicsElement. |
| 53 { | 50 { |
| 54 } | 51 } |
| 55 | 52 |
| 56 RenderSVGShape::~RenderSVGShape() | 53 RenderSVGShape::~RenderSVGShape() |
| 57 { | 54 { |
| 58 } | 55 } |
| 59 | 56 |
| 60 void RenderSVGShape::updateShapeFromElement() | 57 void RenderSVGShape::updateShapeFromElement() |
| 61 { | 58 { |
| 62 m_path.clear(); | 59 m_path.clear(); |
| 63 m_path = adoptPtr(new Path); | 60 m_path = adoptPtr(new Path); |
| 64 ASSERT(RenderSVGShape::isShapeEmpty()); | 61 ASSERT(RenderSVGShape::isShapeEmpty()); |
| 65 | 62 |
| 66 updatePathFromGraphicsElement(toSVGGraphicsElement(element()), path()); | 63 updatePathFromGraphicsElement(toSVGGraphicsElement(element()), path()); |
| 67 processMarkerPositions(); | 64 processMarkerPositions(); |
| 68 | 65 |
| 69 m_fillBoundingBox = calculateObjectBoundingBox(); | 66 m_fillBoundingBox = calculateObjectBoundingBox(); |
| 70 m_strokeBoundingBox = calculateStrokeBoundingBox(); | 67 m_strokeBoundingBox = calculateStrokeBoundingBox(); |
| 71 } | 68 } |
| 72 | 69 |
| 73 void RenderSVGShape::fillShape(GraphicsContext* context) const | |
| 74 { | |
| 75 context->fillPath(path()); | |
| 76 } | |
| 77 | |
| 78 void RenderSVGShape::strokeShape(GraphicsContext* context) const | |
| 79 { | |
| 80 ASSERT(m_path); | |
| 81 Path* usePath = m_path.get(); | |
| 82 | |
| 83 if (hasNonScalingStroke()) | |
| 84 usePath = nonScalingStrokePath(usePath, nonScalingStrokeTransform()); | |
| 85 | |
| 86 context->strokePath(*usePath); | |
| 87 } | |
| 88 | |
| 89 bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) | 70 bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) |
| 90 { | 71 { |
| 91 ASSERT(m_path); | 72 ASSERT(m_path); |
| 92 StrokeData strokeData; | 73 StrokeData strokeData; |
| 93 SVGRenderSupport::applyStrokeStyleToStrokeData(&strokeData, style(), this); | 74 SVGRenderSupport::applyStrokeStyleToStrokeData(&strokeData, style(), this); |
| 94 | 75 |
| 95 if (hasNonScalingStroke()) { | 76 if (hasNonScalingStroke()) { |
| 96 AffineTransform nonScalingTransform = nonScalingStrokeTransform(); | 77 AffineTransform nonScalingTransform = nonScalingStrokeTransform(); |
| 97 Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform); | 78 Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform); |
| 98 | 79 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransfo
rm& strokeTransform) const | 142 Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransfo
rm& strokeTransform) const |
| 162 { | 143 { |
| 163 DEFINE_STATIC_LOCAL(Path, tempPath, ()); | 144 DEFINE_STATIC_LOCAL(Path, tempPath, ()); |
| 164 | 145 |
| 165 tempPath = *path; | 146 tempPath = *path; |
| 166 tempPath.transform(strokeTransform); | 147 tempPath.transform(strokeTransform); |
| 167 | 148 |
| 168 return &tempPath; | 149 return &tempPath; |
| 169 } | 150 } |
| 170 | 151 |
| 171 bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransfo
rm, GraphicsContextStateSaver& stateSaver) | |
| 172 { | |
| 173 if (!strokeTransform.isInvertible()) | |
| 174 return false; | |
| 175 | |
| 176 stateSaver.save(); | |
| 177 stateSaver.context()->concatCTM(strokeTransform.inverse()); | |
| 178 return true; | |
| 179 } | |
| 180 | |
| 181 AffineTransform RenderSVGShape::nonScalingStrokeTransform() const | 152 AffineTransform RenderSVGShape::nonScalingStrokeTransform() const |
| 182 { | 153 { |
| 183 return toSVGGraphicsElement(element())->getScreenCTM(SVGGraphicsElement::Dis
allowStyleUpdate); | 154 return toSVGGraphicsElement(element())->getScreenCTM(SVGGraphicsElement::Dis
allowStyleUpdate); |
| 184 } | 155 } |
| 185 | 156 |
| 186 bool RenderSVGShape::shouldGenerateMarkerPositions() const | |
| 187 { | |
| 188 if (!style()->svgStyle().hasMarkers()) | |
| 189 return false; | |
| 190 | |
| 191 if (!SVGResources::supportsMarkers(*toSVGGraphicsElement(element()))) | |
| 192 return false; | |
| 193 | |
| 194 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
this); | |
| 195 if (!resources) | |
| 196 return false; | |
| 197 | |
| 198 return resources->markerStart() || resources->markerMid() || resources->mark
erEnd(); | |
| 199 } | |
| 200 | |
| 201 void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&) | 157 void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&) |
| 202 { | 158 { |
| 203 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this); | 159 SVGShapePainter(*this).paint(paintInfo); |
| 204 if (paintInfo.phase != PaintPhaseForeground | |
| 205 || style()->visibility() == HIDDEN | |
| 206 || isShapeEmpty()) | |
| 207 return; | |
| 208 | |
| 209 FloatRect boundingBox = paintInvalidationRectInLocalCoordinates(); | |
| 210 if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(boundingBox,
m_localTransform, paintInfo)) | |
| 211 return; | |
| 212 | |
| 213 PaintInfo childPaintInfo(paintInfo); | |
| 214 | |
| 215 GraphicsContextStateSaver stateSaver(*childPaintInfo.context); | |
| 216 childPaintInfo.applyTransform(m_localTransform); | |
| 217 | |
| 218 SVGRenderingContext renderingContext(this, childPaintInfo); | |
| 219 | |
| 220 if (renderingContext.isRenderingPrepared()) { | |
| 221 const SVGRenderStyle& svgStyle = style()->svgStyle(); | |
| 222 if (svgStyle.shapeRendering() == SR_CRISPEDGES) | |
| 223 childPaintInfo.context->setShouldAntialias(false); | |
| 224 | |
| 225 for (int i = 0; i < 3; i++) { | |
| 226 switch (svgStyle.paintOrderType(i)) { | |
| 227 case PT_FILL: { | |
| 228 GraphicsContextStateSaver stateSaver(*childPaintInfo.context, fa
lse); | |
| 229 if (!SVGRenderSupport::updateGraphicsContext(stateSaver, style()
, *this, ApplyToFillMode)) | |
| 230 break; | |
| 231 fillShape(childPaintInfo.context); | |
| 232 break; | |
| 233 } | |
| 234 case PT_STROKE: | |
| 235 if (svgStyle.hasVisibleStroke()) { | |
| 236 GraphicsContextStateSaver stateSaver(*childPaintInfo.context
, false); | |
| 237 AffineTransform nonScalingTransform; | |
| 238 const AffineTransform* additionalPaintServerTransform = 0; | |
| 239 | |
| 240 if (hasNonScalingStroke()) { | |
| 241 nonScalingTransform = nonScalingStrokeTransform(); | |
| 242 if (!setupNonScalingStrokeContext(nonScalingTransform, s
tateSaver)) | |
| 243 return; | |
| 244 | |
| 245 // Non-scaling stroke needs to reset the transform back
to the host transform. | |
| 246 additionalPaintServerTransform = &nonScalingTransform; | |
| 247 } | |
| 248 | |
| 249 if (!SVGRenderSupport::updateGraphicsContext(stateSaver, sty
le(), *this, ApplyToStrokeMode, additionalPaintServerTransform)) | |
| 250 break; | |
| 251 strokeShape(childPaintInfo.context); | |
| 252 } | |
| 253 break; | |
| 254 case PT_MARKERS: | |
| 255 if (!m_markerPositions.isEmpty()) | |
| 256 paintMarkers(childPaintInfo); | |
| 257 break; | |
| 258 default: | |
| 259 ASSERT_NOT_REACHED(); | |
| 260 break; | |
| 261 } | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 if (style()->outlineWidth()) | |
| 266 paintOutline(childPaintInfo, IntRect(boundingBox)); | |
| 267 } | 160 } |
| 268 | 161 |
| 269 // This method is called from inside paintOutline() since we call paintOutline() | 162 // This method is called from inside paintOutline() since we call paintOutline() |
| 270 // while transformed to our coord system, return local coords | 163 // while transformed to our coord system, return local coords |
| 271 void RenderSVGShape::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPo
int&, const RenderLayerModelObject*) const | 164 void RenderSVGShape::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPo
int&, const RenderLayerModelObject*) const |
| 272 { | 165 { |
| 273 LayoutRect rect = LayoutRect(paintInvalidationRectInLocalCoordinates()); | 166 LayoutRect rect = LayoutRect(paintInvalidationRectInLocalCoordinates()); |
| 274 if (!rect.isEmpty()) | 167 if (!rect.isEmpty()) |
| 275 rects.append(rect); | 168 rects.append(rect); |
| 276 } | 169 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 303 if (request.svgClipContent()) | 196 if (request.svgClipContent()) |
| 304 fillRule = svgStyle.clipRule(); | 197 fillRule = svgStyle.clipRule(); |
| 305 if ((hitRules.canHitBoundingBox && objectBoundingBox().contains(localPoi
nt)) | 198 if ((hitRules.canHitBoundingBox && objectBoundingBox().contains(localPoi
nt)) |
| 306 || (hitRules.canHitStroke && (svgStyle.hasStroke() || !hitRules.requ
ireStroke) && strokeContains(localPoint, hitRules.requireStroke)) | 199 || (hitRules.canHitStroke && (svgStyle.hasStroke() || !hitRules.requ
ireStroke) && strokeContains(localPoint, hitRules.requireStroke)) |
| 307 || (hitRules.canHitFill && (svgStyle.hasFill() || !hitRules.requireF
ill) && fillContains(localPoint, hitRules.requireFill, fillRule))) | 200 || (hitRules.canHitFill && (svgStyle.hasFill() || !hitRules.requireF
ill) && fillContains(localPoint, hitRules.requireFill, fillRule))) |
| 308 return true; | 201 return true; |
| 309 } | 202 } |
| 310 return false; | 203 return false; |
| 311 } | 204 } |
| 312 | 205 |
| 313 static inline RenderSVGResourceMarker* markerForType(SVGMarkerType type, RenderS
VGResourceMarker* markerStart, RenderSVGResourceMarker* markerMid, RenderSVGReso
urceMarker* markerEnd) | |
| 314 { | |
| 315 switch (type) { | |
| 316 case StartMarker: | |
| 317 return markerStart; | |
| 318 case MidMarker: | |
| 319 return markerMid; | |
| 320 case EndMarker: | |
| 321 return markerEnd; | |
| 322 } | |
| 323 | |
| 324 ASSERT_NOT_REACHED(); | |
| 325 return 0; | |
| 326 } | |
| 327 | |
| 328 FloatRect RenderSVGShape::markerRect(float strokeWidth) const | |
| 329 { | |
| 330 ASSERT(!m_markerPositions.isEmpty()); | |
| 331 | |
| 332 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
this); | |
| 333 ASSERT(resources); | |
| 334 | |
| 335 RenderSVGResourceMarker* markerStart = resources->markerStart(); | |
| 336 RenderSVGResourceMarker* markerMid = resources->markerMid(); | |
| 337 RenderSVGResourceMarker* markerEnd = resources->markerEnd(); | |
| 338 ASSERT(markerStart || markerMid || markerEnd); | |
| 339 | |
| 340 FloatRect boundaries; | |
| 341 unsigned size = m_markerPositions.size(); | |
| 342 for (unsigned i = 0; i < size; ++i) { | |
| 343 if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i]
.type, markerStart, markerMid, markerEnd)) | |
| 344 boundaries.unite(marker->markerBoundaries(marker->markerTransformati
on(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth))); | |
| 345 } | |
| 346 return boundaries; | |
| 347 } | |
| 348 | |
| 349 FloatRect RenderSVGShape::calculateObjectBoundingBox() const | 206 FloatRect RenderSVGShape::calculateObjectBoundingBox() const |
| 350 { | 207 { |
| 351 return path().boundingRect(); | 208 return path().boundingRect(); |
| 352 } | 209 } |
| 353 | 210 |
| 354 FloatRect RenderSVGShape::calculateStrokeBoundingBox() const | 211 FloatRect RenderSVGShape::calculateStrokeBoundingBox() const |
| 355 { | 212 { |
| 356 ASSERT(m_path); | 213 ASSERT(m_path); |
| 357 FloatRect strokeBoundingBox = m_fillBoundingBox; | 214 FloatRect strokeBoundingBox = m_fillBoundingBox; |
| 358 | 215 |
| 359 if (style()->svgStyle().hasStroke()) { | 216 if (style()->svgStyle().hasStroke()) { |
| 360 StrokeData strokeData; | 217 StrokeData strokeData; |
| 361 SVGRenderSupport::applyStrokeStyleToStrokeData(&strokeData, style(), thi
s); | 218 SVGRenderSupport::applyStrokeStyleToStrokeData(&strokeData, style(), thi
s); |
| 362 if (hasNonScalingStroke()) { | 219 if (hasNonScalingStroke()) { |
| 363 AffineTransform nonScalingTransform = nonScalingStrokeTransform(); | 220 AffineTransform nonScalingTransform = nonScalingStrokeTransform(); |
| 364 if (nonScalingTransform.isInvertible()) { | 221 if (nonScalingTransform.isInvertible()) { |
| 365 Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTra
nsform); | 222 Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTra
nsform); |
| 366 FloatRect strokeBoundingRect = usePath->strokeBoundingRect(strok
eData); | 223 FloatRect strokeBoundingRect = usePath->strokeBoundingRect(strok
eData); |
| 367 strokeBoundingRect = nonScalingTransform.inverse().mapRect(strok
eBoundingRect); | 224 strokeBoundingRect = nonScalingTransform.inverse().mapRect(strok
eBoundingRect); |
| 368 strokeBoundingBox.unite(strokeBoundingRect); | 225 strokeBoundingBox.unite(strokeBoundingRect); |
| 369 } | 226 } |
| 370 } else { | 227 } else { |
| 371 strokeBoundingBox.unite(path().strokeBoundingRect(strokeData)); | 228 strokeBoundingBox.unite(path().strokeBoundingRect(strokeData)); |
| 372 } | 229 } |
| 373 } | 230 } |
| 374 | 231 |
| 375 if (!m_markerPositions.isEmpty()) | |
| 376 strokeBoundingBox.unite(markerRect(strokeWidth())); | |
| 377 | |
| 378 return strokeBoundingBox; | 232 return strokeBoundingBox; |
| 379 } | 233 } |
| 380 | 234 |
| 381 void RenderSVGShape::updatePaintInvalidationBoundingBox() | 235 void RenderSVGShape::updatePaintInvalidationBoundingBox() |
| 382 { | 236 { |
| 383 m_paintInvalidationBoundingBox = strokeBoundingBox(); | 237 m_paintInvalidationBoundingBox = strokeBoundingBox(); |
| 384 if (strokeWidth() < 1.0f && !m_paintInvalidationBoundingBox.isEmpty()) | 238 if (strokeWidth() < 1.0f && !m_paintInvalidationBoundingBox.isEmpty()) |
| 385 m_paintInvalidationBoundingBox.inflate(1); | 239 m_paintInvalidationBoundingBox.inflate(1); |
| 386 SVGRenderSupport::intersectPaintInvalidationRectWithResources(this, m_paintI
nvalidationBoundingBox); | 240 SVGRenderSupport::intersectPaintInvalidationRectWithResources(this, m_paintI
nvalidationBoundingBox); |
| 387 } | 241 } |
| 388 | 242 |
| 389 float RenderSVGShape::strokeWidth() const | 243 float RenderSVGShape::strokeWidth() const |
| 390 { | 244 { |
| 391 SVGLengthContext lengthContext(element()); | 245 SVGLengthContext lengthContext(element()); |
| 392 return style()->svgStyle().strokeWidth()->value(lengthContext); | 246 return style()->svgStyle().strokeWidth()->value(lengthContext); |
| 393 } | 247 } |
| 394 | 248 |
| 395 bool RenderSVGShape::hasSmoothStroke() const | 249 bool RenderSVGShape::hasSmoothStroke() const |
| 396 { | 250 { |
| 397 const SVGRenderStyle& svgStyle = style()->svgStyle(); | 251 const SVGRenderStyle& svgStyle = style()->svgStyle(); |
| 398 return svgStyle.strokeDashArray()->isEmpty() | 252 return svgStyle.strokeDashArray()->isEmpty() |
| 399 && svgStyle.strokeMiterLimit() == SVGRenderStyle::initialStrokeMiterLimi
t() | 253 && svgStyle.strokeMiterLimit() == SVGRenderStyle::initialStrokeMiterLimi
t() |
| 400 && svgStyle.joinStyle() == SVGRenderStyle::initialJoinStyle() | 254 && svgStyle.joinStyle() == SVGRenderStyle::initialJoinStyle() |
| 401 && svgStyle.capStyle() == SVGRenderStyle::initialCapStyle(); | 255 && svgStyle.capStyle() == SVGRenderStyle::initialCapStyle(); |
| 402 } | 256 } |
| 403 | 257 |
| 404 void RenderSVGShape::paintMarkers(PaintInfo& paintInfo) | |
| 405 { | |
| 406 ASSERT(!m_markerPositions.isEmpty()); | |
| 407 | |
| 408 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
this); | |
| 409 if (!resources) | |
| 410 return; | |
| 411 | |
| 412 RenderSVGResourceMarker* markerStart = resources->markerStart(); | |
| 413 RenderSVGResourceMarker* markerMid = resources->markerMid(); | |
| 414 RenderSVGResourceMarker* markerEnd = resources->markerEnd(); | |
| 415 if (!markerStart && !markerMid && !markerEnd) | |
| 416 return; | |
| 417 | |
| 418 float strokeWidth = this->strokeWidth(); | |
| 419 unsigned size = m_markerPositions.size(); | |
| 420 for (unsigned i = 0; i < size; ++i) { | |
| 421 if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i]
.type, markerStart, markerMid, markerEnd)) | |
| 422 SVGMarkerPainter(*marker).paint(paintInfo, m_markerPositions[i], str
okeWidth); | |
| 423 } | |
| 424 } | 258 } |
| 425 | |
| 426 void RenderSVGShape::processMarkerPositions() | |
| 427 { | |
| 428 m_markerPositions.clear(); | |
| 429 | |
| 430 if (!shouldGenerateMarkerPositions()) | |
| 431 return; | |
| 432 | |
| 433 ASSERT(m_path); | |
| 434 | |
| 435 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(
this); | |
| 436 ASSERT(resources); | |
| 437 | |
| 438 RenderSVGResourceMarker* markerStart = resources->markerStart(); | |
| 439 | |
| 440 SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orien
tType() == SVGMarkerOrientAutoStartReverse : false); | |
| 441 m_path->apply(&markerData, SVGMarkerData::updateFromPathElement); | |
| 442 markerData.pathIsDone(); | |
| 443 } | |
| 444 | |
| 445 } | |
| OLD | NEW |