| 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 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 93 |
| 94 bool RenderSVGPath::strokeContains(const FloatPoint& point, bool requiresStroke) | 94 bool RenderSVGPath::strokeContains(const FloatPoint& point, bool requiresStroke) |
| 95 { | 95 { |
| 96 if (!m_strokeAndMarkerBoundingBox.contains(point)) | 96 if (!m_strokeAndMarkerBoundingBox.contains(point)) |
| 97 return false; | 97 return false; |
| 98 | 98 |
| 99 Color fallbackColor; | 99 Color fallbackColor; |
| 100 if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style
(), fallbackColor)) | 100 if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style
(), fallbackColor)) |
| 101 return false; | 101 return false; |
| 102 | 102 |
| 103 if (shouldStrokeZeroLengthSubpath()) | |
| 104 return zeroLengthSubpathRect().contains(point); | |
| 105 | |
| 106 BoundingRectStrokeStyleApplier strokeStyle(this, style()); | 103 BoundingRectStrokeStyleApplier strokeStyle(this, style()); |
| 107 return m_path.strokeContains(&strokeStyle, point); | 104 return m_path.strokeContains(&strokeStyle, point); |
| 108 } | 105 } |
| 109 | 106 |
| 110 void RenderSVGPath::layout() | 107 void RenderSVGPath::layout() |
| 111 { | 108 { |
| 112 LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsL
ayout()); | 109 LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsL
ayout()); |
| 113 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableE
lement*>(node()); | 110 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableE
lement*>(node()); |
| 114 | 111 |
| 115 bool updateCachedBoundariesInParents = false; | 112 bool updateCachedBoundariesInParents = false; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 145 } | 142 } |
| 146 | 143 |
| 147 // If our bounds changed, notify the parents. | 144 // If our bounds changed, notify the parents. |
| 148 if (updateCachedBoundariesInParents) | 145 if (updateCachedBoundariesInParents) |
| 149 RenderSVGModelObject::setNeedsBoundariesUpdate(); | 146 RenderSVGModelObject::setNeedsBoundariesUpdate(); |
| 150 | 147 |
| 151 repainter.repaintAfterLayout(); | 148 repainter.repaintAfterLayout(); |
| 152 setNeedsLayout(false); | 149 setNeedsLayout(false); |
| 153 } | 150 } |
| 154 | 151 |
| 155 bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const | |
| 156 { | |
| 157 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-l
inecap’ property has a value of butt | |
| 158 // but shall be stroked if the ‘stroke-linecap’ property has a value of roun
d or square | |
| 159 return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() !
= ButtCap && !m_fillBoundingBox.width() && !m_fillBoundingBox.height(); | |
| 160 } | |
| 161 | |
| 162 FloatRect RenderSVGPath::zeroLengthSubpathRect() const | |
| 163 { | |
| 164 SVGElement* svgElement = static_cast<SVGElement*>(node()); | |
| 165 float strokeWidth = style()->svgStyle()->strokeWidth().value(svgElement); | |
| 166 return FloatRect(m_fillBoundingBox.x() - strokeWidth / 2, m_fillBoundingBox.
y() - strokeWidth / 2, strokeWidth, strokeWidth); | |
| 167 } | |
| 168 | |
| 169 void RenderSVGPath::setupSquareCapPath(Path*& usePath, int& applyMode) | |
| 170 { | |
| 171 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-l
inecap’ property has a value of butt | |
| 172 // but shall be stroked if the ‘stroke-linecap’ property has a value of roun
d or square | |
| 173 DEFINE_STATIC_LOCAL(Path, tempPath, ()); | |
| 174 | |
| 175 applyMode = ApplyToFillMode; | |
| 176 usePath = &tempPath; | |
| 177 usePath->clear(); | |
| 178 if (style()->svgStyle()->capStyle() == SquareCap) | |
| 179 usePath->addRect(zeroLengthSubpathRect()); | |
| 180 else | |
| 181 usePath->addEllipse(zeroLengthSubpathRect()); | |
| 182 } | |
| 183 | |
| 184 bool RenderSVGPath::setupNonScalingStrokePath(Path*& usePath, GraphicsContextSta
teSaver& stateSaver) | |
| 185 { | |
| 186 DEFINE_STATIC_LOCAL(Path, tempPath, ()); | |
| 187 | |
| 188 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableE
lement*>(node()); | |
| 189 AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatab
le::DisallowStyleUpdate); | |
| 190 if (!nonScalingStrokeTransform.isInvertible()) | |
| 191 return false; | |
| 192 | |
| 193 tempPath = m_path; | |
| 194 usePath = &tempPath; | |
| 195 tempPath.transform(nonScalingStrokeTransform); | |
| 196 | |
| 197 stateSaver.save(); | |
| 198 stateSaver.context()->concatCTM(nonScalingStrokeTransform.inverse()); | |
| 199 return true; | |
| 200 } | |
| 201 | |
| 202 void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) | 152 void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) |
| 203 { | 153 { |
| 204 RenderStyle* style = this->style(); | 154 RenderStyle* style = this->style(); |
| 205 | 155 |
| 206 Color fallbackColor; | 156 Color fallbackColor; |
| 207 if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintin
gResource(this, style, fallbackColor)) { | 157 if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintin
gResource(this, style, fallbackColor)) { |
| 208 if (fillPaintingResource->applyResource(this, style, context, ApplyToFil
lMode)) | 158 if (fillPaintingResource->applyResource(this, style, context, ApplyToFil
lMode)) |
| 209 fillPaintingResource->postApplyResource(this, context, ApplyToFillMo
de, &m_path); | 159 fillPaintingResource->postApplyResource(this, context, ApplyToFillMo
de, &m_path); |
| 210 else if (fallbackColor.isValid()) { | 160 else if (fallbackColor.isValid()) { |
| 211 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::s
haredSolidPaintingResource(); | 161 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::s
haredSolidPaintingResource(); |
| 212 fallbackResource->setColor(fallbackColor); | 162 fallbackResource->setColor(fallbackColor); |
| 213 if (fallbackResource->applyResource(this, style, context, ApplyToFil
lMode)) | 163 if (fallbackResource->applyResource(this, style, context, ApplyToFil
lMode)) |
| 214 fallbackResource->postApplyResource(this, context, ApplyToFillMo
de, &m_path); | 164 fallbackResource->postApplyResource(this, context, ApplyToFillMo
de, &m_path); |
| 215 } | 165 } |
| 216 } | 166 } |
| 217 | 167 |
| 218 fallbackColor = Color(); | 168 fallbackColor = Color(); |
| 219 RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintin
gResource(this, style, fallbackColor); | 169 RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintin
gResource(this, style, fallbackColor); |
| 220 if (!strokePaintingResource) | 170 if (!strokePaintingResource) |
| 221 return; | 171 return; |
| 222 | 172 |
| 223 Path* usePath = &m_path; | 173 Path path; |
| 224 int applyMode = ApplyToStrokeMode; | |
| 225 | 174 |
| 226 bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_
STROKE; | 175 bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_
STROKE; |
| 227 | 176 |
| 228 GraphicsContextStateSaver stateSaver(*context, false); | 177 GraphicsContextStateSaver stateSaver(*context, false); |
| 178 if (nonScalingStroke) { |
| 179 SVGStyledTransformableElement* element = static_cast<SVGStyledTransforma
bleElement*>(node()); |
| 180 AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLoc
atable::DisallowStyleUpdate); |
| 181 if (!nonScalingStrokeTransform.isInvertible()) |
| 182 return; |
| 229 | 183 |
| 230 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-l
inecap’ property has a value of butt | 184 path = m_path; |
| 231 // but shall be stroked if the ‘stroke-linecap’ property has a value of roun
d or square | 185 path.transform(nonScalingStrokeTransform); |
| 232 // FIXME: this does not work for zero-length subpaths, only when total path
is zero-length | 186 |
| 233 if (shouldStrokeZeroLengthSubpath()) | 187 stateSaver.save(); |
| 234 setupSquareCapPath(usePath, applyMode); | 188 context->concatCTM(nonScalingStrokeTransform.inverse()); |
| 235 else if (nonScalingStroke) { | |
| 236 if (!setupNonScalingStrokePath(usePath, stateSaver)) | |
| 237 return; | |
| 238 } | 189 } |
| 239 | 190 |
| 240 if (strokePaintingResource->applyResource(this, style, context, applyMode)) | 191 if (strokePaintingResource->applyResource(this, style, context, ApplyToStrok
eMode)) |
| 241 strokePaintingResource->postApplyResource(this, context, applyMode, useP
ath); | 192 strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMo
de, nonScalingStroke ? &path : &m_path); |
| 242 else if (fallbackColor.isValid()) { | 193 else if (fallbackColor.isValid()) { |
| 243 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::share
dSolidPaintingResource(); | 194 RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::share
dSolidPaintingResource(); |
| 244 fallbackResource->setColor(fallbackColor); | 195 fallbackResource->setColor(fallbackColor); |
| 245 if (fallbackResource->applyResource(this, style, context, applyMode)) | 196 if (fallbackResource->applyResource(this, style, context, ApplyToStrokeM
ode)) |
| 246 fallbackResource->postApplyResource(this, context, applyMode, usePat
h); | 197 fallbackResource->postApplyResource(this, context, ApplyToStrokeMode
, nonScalingStroke ? &path : &m_path); |
| 247 } | 198 } |
| 248 } | 199 } |
| 249 | 200 |
| 250 void RenderSVGPath::paint(PaintInfo& paintInfo, const LayoutPoint&) | 201 void RenderSVGPath::paint(PaintInfo& paintInfo, const LayoutPoint&) |
| 251 { | 202 { |
| 252 if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN
|| m_path.isEmpty()) | 203 if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN
|| m_path.isEmpty()) |
| 253 return; | 204 return; |
| 254 | 205 |
| 255 FloatRect boundingBox = repaintRectInLocalCoordinates(); | 206 FloatRect boundingBox = repaintRectInLocalCoordinates(); |
| 256 if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTr
ansform, paintInfo)) | 207 if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTr
ansform, paintInfo)) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 if (m_path.isEmpty()) { | 303 if (m_path.isEmpty()) { |
| 353 m_fillBoundingBox = FloatRect(); | 304 m_fillBoundingBox = FloatRect(); |
| 354 m_strokeAndMarkerBoundingBox = FloatRect(); | 305 m_strokeAndMarkerBoundingBox = FloatRect(); |
| 355 m_repaintBoundingBox = FloatRect(); | 306 m_repaintBoundingBox = FloatRect(); |
| 356 return; | 307 return; |
| 357 } | 308 } |
| 358 | 309 |
| 359 // Cache _unclipped_ fill bounding box, used for calculations in resources | 310 // Cache _unclipped_ fill bounding box, used for calculations in resources |
| 360 m_fillBoundingBox = m_path.boundingRect(); | 311 m_fillBoundingBox = m_path.boundingRect(); |
| 361 | 312 |
| 362 // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-l
inecap’ property has a value of butt | |
| 363 // but shall be stroked if the ‘stroke-linecap’ property has a value of roun
d or square | |
| 364 if (shouldStrokeZeroLengthSubpath()) { | |
| 365 m_strokeAndMarkerBoundingBox = zeroLengthSubpathRect(); | |
| 366 // Cache smallest possible repaint rectangle | |
| 367 m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; | |
| 368 SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBound
ingBox); | |
| 369 return; | |
| 370 } | |
| 371 | |
| 372 // Cache _unclipped_ stroke bounding box, used for calculations in resources
(includes marker boundaries) | 313 // Cache _unclipped_ stroke bounding box, used for calculations in resources
(includes marker boundaries) |
| 373 m_strokeAndMarkerBoundingBox = m_fillBoundingBox; | 314 m_strokeAndMarkerBoundingBox = m_fillBoundingBox; |
| 374 | 315 |
| 375 const SVGRenderStyle* svgStyle = style()->svgStyle(); | 316 const SVGRenderStyle* svgStyle = style()->svgStyle(); |
| 376 if (svgStyle->hasStroke()) { | 317 if (svgStyle->hasStroke()) { |
| 377 BoundingRectStrokeStyleApplier strokeStyle(this, style()); | 318 BoundingRectStrokeStyleApplier strokeStyle(this, style()); |
| 378 m_strokeAndMarkerBoundingBox.unite(m_path.strokeBoundingRect(&strokeStyl
e)); | 319 m_strokeAndMarkerBoundingBox.unite(m_path.strokeBoundingRect(&strokeStyl
e)); |
| 379 } | 320 } |
| 380 | 321 |
| 381 if (svgStyle->hasMarkers()) { | 322 if (svgStyle->hasMarkers()) { |
| 382 FloatRect markerBounds = calculateMarkerBoundsIfNeeded(); | 323 FloatRect markerBounds = calculateMarkerBoundsIfNeeded(); |
| 383 if (!markerBounds.isEmpty()) | 324 if (!markerBounds.isEmpty()) |
| 384 m_strokeAndMarkerBoundingBox.unite(markerBounds); | 325 m_strokeAndMarkerBoundingBox.unite(markerBounds); |
| 385 } | 326 } |
| 386 | 327 |
| 387 // Cache smallest possible repaint rectangle | 328 // Cache smallest possible repaint rectangle |
| 388 m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; | 329 m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; |
| 389 SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingB
ox); | 330 SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingB
ox); |
| 390 } | 331 } |
| 391 | 332 |
| 392 } | 333 } |
| 393 | 334 |
| 394 #endif // ENABLE(SVG) | 335 #endif // ENABLE(SVG) |
| OLD | NEW |