| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/paint/SVGShapePainter.h" | 6 #include "core/paint/SVGShapePainter.h" |
| 7 | 7 |
| 8 #include "core/layout/svg/LayoutSVGPath.h" | 8 #include "core/layout/svg/LayoutSVGPath.h" |
| 9 #include "core/layout/svg/LayoutSVGResourceMarker.h" | 9 #include "core/layout/svg/LayoutSVGResourceMarker.h" |
| 10 #include "core/layout/svg/LayoutSVGShape.h" | 10 #include "core/layout/svg/LayoutSVGShape.h" |
| 11 #include "core/layout/svg/SVGLayoutSupport.h" | 11 #include "core/layout/svg/SVGLayoutSupport.h" |
| 12 #include "core/layout/svg/SVGMarkerData.h" | 12 #include "core/layout/svg/SVGMarkerData.h" |
| 13 #include "core/layout/svg/SVGResources.h" | 13 #include "core/layout/svg/SVGResources.h" |
| 14 #include "core/layout/svg/SVGResourcesCache.h" | 14 #include "core/layout/svg/SVGResourcesCache.h" |
| 15 #include "core/paint/LayoutObjectDrawingRecorder.h" | 15 #include "core/paint/LayoutObjectDrawingRecorder.h" |
| 16 #include "core/paint/ObjectPainter.h" | 16 #include "core/paint/ObjectPainter.h" |
| 17 #include "core/paint/PaintInfo.h" | 17 #include "core/paint/PaintInfo.h" |
| 18 #include "core/paint/SVGContainerPainter.h" | 18 #include "core/paint/SVGContainerPainter.h" |
| 19 #include "core/paint/SVGPaintContext.h" | 19 #include "core/paint/SVGPaintContext.h" |
| 20 #include "core/paint/ScopeRecorder.h" |
| 20 #include "core/paint/TransformRecorder.h" | 21 #include "core/paint/TransformRecorder.h" |
| 21 #include "platform/graphics/paint/DisplayItemListContextRecorder.h" | 22 #include "platform/graphics/paint/SkPictureBuilder.h" |
| 22 #include "third_party/skia/include/core/SkPaint.h" | 23 #include "third_party/skia/include/core/SkPaint.h" |
| 23 #include "third_party/skia/include/core/SkPicture.h" | 24 #include "third_party/skia/include/core/SkPicture.h" |
| 24 #include "wtf/Optional.h" | 25 #include "wtf/Optional.h" |
| 25 | 26 |
| 26 namespace blink { | 27 namespace blink { |
| 27 | 28 |
| 28 static bool setupNonScalingStrokeContext(AffineTransform& strokeTransform, Graph
icsContextStateSaver& stateSaver) | 29 static bool setupNonScalingStrokeContext(AffineTransform& strokeTransform, Graph
icsContextStateSaver& stateSaver) |
| 29 { | 30 { |
| 30 if (!strokeTransform.isInvertible()) | 31 if (!strokeTransform.isInvertible()) |
| 31 return false; | 32 return false; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 strokePaint.setAntiAlias(shouldAntiAlias); | 95 strokePaint.setAntiAlias(shouldAntiAlias); |
| 95 | 96 |
| 96 StrokeData strokeData; | 97 StrokeData strokeData; |
| 97 SVGLayoutSupport::applyStrokeStyleToStrokeData(strok
eData, m_layoutSVGShape.styleRef(), m_layoutSVGShape); | 98 SVGLayoutSupport::applyStrokeStyleToStrokeData(strok
eData, m_layoutSVGShape.styleRef(), m_layoutSVGShape); |
| 98 strokeData.setupPaint(&strokePaint); | 99 strokeData.setupPaint(&strokePaint); |
| 99 | 100 |
| 100 strokeShape(paintContext.paintInfo().context, stroke
Paint); | 101 strokeShape(paintContext.paintInfo().context, stroke
Paint); |
| 101 } | 102 } |
| 102 break; | 103 break; |
| 103 case PT_MARKERS: | 104 case PT_MARKERS: |
| 104 paintMarkers(paintContext.paintInfo()); | 105 paintMarkers(paintContext.paintInfo(), boundingBox); |
| 105 break; | 106 break; |
| 106 default: | 107 default: |
| 107 ASSERT_NOT_REACHED(); | 108 ASSERT_NOT_REACHED(); |
| 108 break; | 109 break; |
| 109 } | 110 } |
| 110 } | 111 } |
| 111 } | 112 } |
| 112 } | 113 } |
| 113 } | 114 } |
| 114 | 115 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 default: | 173 default: |
| 173 ASSERT(m_layoutSVGShape.hasPath()); | 174 ASSERT(m_layoutSVGShape.hasPath()); |
| 174 Path* usePath = &m_layoutSVGShape.path(); | 175 Path* usePath = &m_layoutSVGShape.path(); |
| 175 if (m_layoutSVGShape.hasNonScalingStroke()) | 176 if (m_layoutSVGShape.hasNonScalingStroke()) |
| 176 usePath = m_layoutSVGShape.nonScalingStrokePath(usePath, m_layoutSVG
Shape.nonScalingStrokeTransform()); | 177 usePath = m_layoutSVGShape.nonScalingStrokePath(usePath, m_layoutSVG
Shape.nonScalingStrokeTransform()); |
| 177 context->drawPath(usePath->skPath(), paint); | 178 context->drawPath(usePath->skPath(), paint); |
| 178 strokeZeroLengthLineCaps(context, paint); | 179 strokeZeroLengthLineCaps(context, paint); |
| 179 } | 180 } |
| 180 } | 181 } |
| 181 | 182 |
| 182 void SVGShapePainter::paintMarkers(const PaintInfo& paintInfo) | 183 void SVGShapePainter::paintMarkers(const PaintInfo& paintInfo, const FloatRect&
boundingBox) |
| 183 { | 184 { |
| 184 const Vector<MarkerPosition>* markerPositions = m_layoutSVGShape.markerPosit
ions(); | 185 const Vector<MarkerPosition>* markerPositions = m_layoutSVGShape.markerPosit
ions(); |
| 185 if (!markerPositions || markerPositions->isEmpty()) | 186 if (!markerPositions || markerPositions->isEmpty()) |
| 186 return; | 187 return; |
| 187 | 188 |
| 188 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
&m_layoutSVGShape); | 189 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
&m_layoutSVGShape); |
| 189 if (!resources) | 190 if (!resources) |
| 190 return; | 191 return; |
| 191 | 192 |
| 192 LayoutSVGResourceMarker* markerStart = resources->markerStart(); | 193 LayoutSVGResourceMarker* markerStart = resources->markerStart(); |
| 193 LayoutSVGResourceMarker* markerMid = resources->markerMid(); | 194 LayoutSVGResourceMarker* markerMid = resources->markerMid(); |
| 194 LayoutSVGResourceMarker* markerEnd = resources->markerEnd(); | 195 LayoutSVGResourceMarker* markerEnd = resources->markerEnd(); |
| 195 if (!markerStart && !markerMid && !markerEnd) | 196 if (!markerStart && !markerMid && !markerEnd) |
| 196 return; | 197 return; |
| 197 | 198 |
| 198 float strokeWidth = m_layoutSVGShape.strokeWidth(); | 199 float strokeWidth = m_layoutSVGShape.strokeWidth(); |
| 199 unsigned size = markerPositions->size(); | 200 unsigned size = markerPositions->size(); |
| 201 SkPictureBuilder pictureBuilder(boundingBox, nullptr, paintInfo.context); |
| 202 PaintInfo markersPaintInfo(paintInfo); |
| 203 markersPaintInfo.context = &pictureBuilder.context(); |
| 204 |
| 205 // It's expensive to track the transformed paint cull rect for each |
| 206 // marker so just disable culling. The shape paint call will already be |
| 207 // culled if it is outside the paint info cull rect. |
| 208 markersPaintInfo.rect = LayoutRect::infiniteIntRect(); |
| 209 |
| 200 for (unsigned i = 0; i < size; ++i) { | 210 for (unsigned i = 0; i < size; ++i) { |
| 211 ScopeRecorder scopeRecorder(*markersPaintInfo.context, m_layoutSVGShape)
; |
| 201 if (LayoutSVGResourceMarker* marker = SVGMarkerData::markerForType((*mar
kerPositions)[i].type, markerStart, markerMid, markerEnd)) | 212 if (LayoutSVGResourceMarker* marker = SVGMarkerData::markerForType((*mar
kerPositions)[i].type, markerStart, markerMid, markerEnd)) |
| 202 paintMarker(paintInfo, *marker, (*markerPositions)[i], strokeWidth); | 213 paintMarker(markersPaintInfo, *marker, (*markerPositions)[i], stroke
Width); |
| 203 } | 214 } |
| 215 |
| 216 pictureBuilder.endRecording()->playback(paintInfo.context->canvas()); |
| 204 } | 217 } |
| 205 | 218 |
| 206 void SVGShapePainter::paintMarker(const PaintInfo& paintInfo, LayoutSVGResourceM
arker& marker, const MarkerPosition& position, float strokeWidth) | 219 void SVGShapePainter::paintMarker(const PaintInfo& paintInfo, LayoutSVGResourceM
arker& marker, const MarkerPosition& position, float strokeWidth) |
| 207 { | 220 { |
| 208 // An empty viewBox disables rendering. | 221 // An empty viewBox disables rendering. |
| 209 SVGMarkerElement* markerElement = toSVGMarkerElement(marker.element()); | 222 SVGMarkerElement* markerElement = toSVGMarkerElement(marker.element()); |
| 210 ASSERT(markerElement); | 223 ASSERT(markerElement); |
| 211 if (markerElement->hasAttribute(SVGNames::viewBoxAttr) && markerElement->vie
wBox()->currentValue()->isValid() && markerElement->viewBox()->currentValue()->v
alue().isEmpty()) | 224 if (markerElement->hasAttribute(SVGNames::viewBoxAttr) && markerElement->vie
wBox()->currentValue()->isValid() && markerElement->viewBox()->currentValue()->v
alue().isEmpty()) |
| 212 return; | 225 return; |
| 213 | 226 |
| 214 { | 227 TransformRecorder transformRecorder(*paintInfo.context, marker, marker.marke
rTransformation(position.origin, position.angle, strokeWidth)); |
| 215 DisplayItemListContextRecorder contextRecorder(*paintInfo.context); | 228 Optional<FloatClipRecorder> clipRecorder; |
| 216 PaintInfo markerPaintInfo(paintInfo); | 229 if (SVGLayoutSupport::isOverflowHidden(&marker)) |
| 217 markerPaintInfo.context = &contextRecorder.context(); | 230 clipRecorder.emplace(*paintInfo.context, marker, paintInfo.phase, marker
.viewport()); |
| 218 | 231 |
| 219 // It's expensive to track the transformed paint cull rect for each | 232 SVGContainerPainter(marker).paint(paintInfo); |
| 220 // marker so just disable culling. The shape paint call will already be | |
| 221 // culled if it is outside the paint info cull rect. | |
| 222 markerPaintInfo.rect = LayoutRect::infiniteIntRect(); | |
| 223 | |
| 224 TransformRecorder transformRecorder(*markerPaintInfo.context, marker, ma
rker.markerTransformation(position.origin, position.angle, strokeWidth)); | |
| 225 Optional<FloatClipRecorder> clipRecorder; | |
| 226 if (SVGLayoutSupport::isOverflowHidden(&marker)) | |
| 227 clipRecorder.emplace(*markerPaintInfo.context, marker, markerPaintIn
fo.phase, marker.viewport()); | |
| 228 | |
| 229 SVGContainerPainter(marker).paint(markerPaintInfo); | |
| 230 } | |
| 231 } | 233 } |
| 232 | 234 |
| 233 void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context, const S
kPaint& strokePaint) | 235 void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context, const S
kPaint& strokePaint) |
| 234 { | 236 { |
| 235 const Vector<FloatPoint>* zeroLengthLineCaps = m_layoutSVGShape.zeroLengthLi
neCaps(); | 237 const Vector<FloatPoint>* zeroLengthLineCaps = m_layoutSVGShape.zeroLengthLi
neCaps(); |
| 236 if (!zeroLengthLineCaps || zeroLengthLineCaps->isEmpty()) | 238 if (!zeroLengthLineCaps || zeroLengthLineCaps->isEmpty()) |
| 237 return; | 239 return; |
| 238 | 240 |
| 239 // We need a paint for filling. | 241 // We need a paint for filling. |
| 240 SkPaint fillPaint = strokePaint; | 242 SkPaint fillPaint = strokePaint; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 255 position = nonScalingTransform.mapPoint(position); | 257 position = nonScalingTransform.mapPoint(position); |
| 256 FloatRect subpathRect = LayoutSVGPath::zeroLengthSubpathRect(position, m
_layoutSVGShape.strokeWidth()); | 258 FloatRect subpathRect = LayoutSVGPath::zeroLengthSubpathRect(position, m
_layoutSVGShape.strokeWidth()); |
| 257 if (m_layoutSVGShape.style()->svgStyle().capStyle() == SquareCap) | 259 if (m_layoutSVGShape.style()->svgStyle().capStyle() == SquareCap) |
| 258 context->drawRect(subpathRect, fillPaint); | 260 context->drawRect(subpathRect, fillPaint); |
| 259 else | 261 else |
| 260 context->drawOval(subpathRect, fillPaint); | 262 context->drawOval(subpathRect, fillPaint); |
| 261 } | 263 } |
| 262 } | 264 } |
| 263 | 265 |
| 264 } // namespace blink | 266 } // namespace blink |
| OLD | NEW |