1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/gpu/GrRecordingContext.h"
9 #include "src/core/SkDrawProcs.h"
10 #include "src/gpu/GrCaps.h"
11 #include "src/gpu/GrPaint.h"
12 #include "src/gpu/GrPathRenderer.h"
13 #include "src/gpu/GrRecordingContextPriv.h"
14 #include "src/gpu/GrSurfaceDrawContext.h"
15 #include "src/gpu/GrUserStencilSettings.h"
16 #include "src/gpu/geometry/GrStyledShape.h"
17
18 #ifdef SK_DEBUG
validate() const19 void GrPathRenderer::StencilPathArgs::validate() const {
20 SkASSERT(fContext);
21 SkASSERT(fRenderTargetContext);
22 SkASSERT(fClipConservativeBounds);
23 SkASSERT(fViewMatrix);
24 SkASSERT(fShape);
25 SkASSERT(fShape->style().isSimpleFill());
26 SkPath path;
27 fShape->asPath(&path);
28 SkASSERT(!path.isInverseFillType());
29 }
30 #endif
31
32 //////////////////////////////////////////////////////////////////////////////
33
GrPathRenderer()34 GrPathRenderer::GrPathRenderer() {}
35
getStencilSupport(const GrStyledShape & shape) const36 GrPathRenderer::StencilSupport GrPathRenderer::getStencilSupport(const GrStyledShape& shape) const {
37 SkDEBUGCODE(SkPath path;)
38 SkDEBUGCODE(shape.asPath(&path);)
39 SkASSERT(shape.style().isSimpleFill());
40 SkASSERT(!path.isInverseFillType());
41 return this->onGetStencilSupport(shape);
42 }
43
drawPath(const DrawPathArgs & args)44 bool GrPathRenderer::drawPath(const DrawPathArgs& args) {
45 #ifdef SK_DEBUG
46 args.validate();
47 CanDrawPathArgs canArgs;
48 canArgs.fCaps = args.fContext->priv().caps();
49 canArgs.fProxy = args.fRenderTargetContext->asRenderTargetProxy();
50 canArgs.fClipConservativeBounds = args.fClipConservativeBounds;
51 canArgs.fViewMatrix = args.fViewMatrix;
52 canArgs.fShape = args.fShape;
53 canArgs.fPaint = &args.fPaint;
54 canArgs.fSurfaceProps = &args.fRenderTargetContext->surfaceProps();
55 canArgs.fAAType = args.fAAType;
56 canArgs.validate();
57
58 canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused();
59 SkASSERT(CanDrawPath::kNo != this->canDrawPath(canArgs));
60 if (!args.fUserStencilSettings->isUnused()) {
61 SkPath path;
62 args.fShape->asPath(&path);
63 SkASSERT(args.fShape->style().isSimpleFill());
64 SkASSERT(kNoRestriction_StencilSupport == this->getStencilSupport(*args.fShape));
65 }
66 #endif
67 return this->onDrawPath(args);
68 }
69
IsStrokeHairlineOrEquivalent(const GrStyle & style,const SkMatrix & matrix,SkScalar * outCoverage)70 bool GrPathRenderer::IsStrokeHairlineOrEquivalent(const GrStyle& style, const SkMatrix& matrix,
71 SkScalar* outCoverage) {
72 if (style.pathEffect()) {
73 return false;
74 }
75 const SkStrokeRec& stroke = style.strokeRec();
76 if (stroke.isHairlineStyle()) {
77 if (outCoverage) {
78 *outCoverage = SK_Scalar1;
79 }
80 return true;
81 }
82 return stroke.getStyle() == SkStrokeRec::kStroke_Style &&
83 SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage);
84 }
85
GetPathDevBounds(const SkPath & path,SkISize devSize,const SkMatrix & matrix,SkRect * bounds)86 void GrPathRenderer::GetPathDevBounds(const SkPath& path,
87 SkISize devSize,
88 const SkMatrix& matrix,
89 SkRect* bounds) {
90 if (path.isInverseFillType()) {
91 *bounds = SkRect::Make(devSize);
92 return;
93 }
94 *bounds = path.getBounds();
95 matrix.mapRect(bounds);
96 }
97
onStencilPath(const StencilPathArgs & args)98 void GrPathRenderer::onStencilPath(const StencilPathArgs& args) {
99 static constexpr GrUserStencilSettings kIncrementStencil(
100 GrUserStencilSettings::StaticInit<
101 0xffff,
102 GrUserStencilTest::kAlways,
103 0xffff,
104 GrUserStencilOp::kReplace,
105 GrUserStencilOp::kReplace,
106 0xffff>()
107 );
108
109 GrPaint paint;
110 DrawPathArgs drawArgs{args.fContext,
111 std::move(paint),
112 &kIncrementStencil,
113 args.fRenderTargetContext,
114 nullptr, // clip
115 args.fClipConservativeBounds,
116 args.fViewMatrix,
117 args.fShape,
118 (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone,
119 false};
120 this->drawPath(drawArgs);
121 }
122