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 "src/core/SkDrawProcs.h"
9 #include "src/gpu/GrCaps.h"
10 #include "src/gpu/GrPaint.h"
11 #include "src/gpu/GrPathRenderer.h"
12 #include "src/gpu/GrRecordingContextPriv.h"
13 #include "src/gpu/GrRenderTargetContext.h"
14 #include "src/gpu/GrUserStencilSettings.h"
15 #include "src/gpu/geometry/GrShape.h"
16
17 #ifdef SK_DEBUG
validate() const18 void GrPathRenderer::StencilPathArgs::validate() const {
19 SkASSERT(fContext);
20 SkASSERT(fRenderTargetContext);
21 SkASSERT(fClipConservativeBounds);
22 SkASSERT(fViewMatrix);
23 SkASSERT(fShape);
24 SkASSERT(fShape->style().isSimpleFill());
25 SkPath path;
26 fShape->asPath(&path);
27 SkASSERT(!path.isInverseFillType());
28 }
29 #endif
30
31 //////////////////////////////////////////////////////////////////////////////
32
GrPathRenderer()33 GrPathRenderer::GrPathRenderer() {}
34
getStencilSupport(const GrShape & shape) const35 GrPathRenderer::StencilSupport GrPathRenderer::getStencilSupport(const GrShape& shape) const {
36 SkDEBUGCODE(SkPath path;)
37 SkDEBUGCODE(shape.asPath(&path);)
38 SkASSERT(shape.style().isSimpleFill());
39 SkASSERT(!path.isInverseFillType());
40 return this->onGetStencilSupport(shape);
41 }
42
drawPath(const DrawPathArgs & args)43 bool GrPathRenderer::drawPath(const DrawPathArgs& args) {
44 #ifdef SK_DEBUG
45 args.validate();
46 CanDrawPathArgs canArgs;
47 canArgs.fCaps = args.fContext->priv().caps();
48 canArgs.fProxy = args.fRenderTargetContext->proxy();
49 canArgs.fClipConservativeBounds = args.fClipConservativeBounds;
50 canArgs.fViewMatrix = args.fViewMatrix;
51 canArgs.fShape = args.fShape;
52 canArgs.fAAType = args.fAAType;
53 canArgs.fTargetIsWrappedVkSecondaryCB = args.fRenderTargetContext->wrapsVkSecondaryCB();
54 canArgs.validate();
55
56 canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused();
57 SkASSERT(CanDrawPath::kNo != this->canDrawPath(canArgs));
58 if (!args.fUserStencilSettings->isUnused()) {
59 SkPath path;
60 args.fShape->asPath(&path);
61 SkASSERT(args.fShape->style().isSimpleFill());
62 SkASSERT(kNoRestriction_StencilSupport == this->getStencilSupport(*args.fShape));
63 }
64 #endif
65 return this->onDrawPath(args);
66 }
67
IsStrokeHairlineOrEquivalent(const GrStyle & style,const SkMatrix & matrix,SkScalar * outCoverage)68 bool GrPathRenderer::IsStrokeHairlineOrEquivalent(const GrStyle& style, const SkMatrix& matrix,
69 SkScalar* outCoverage) {
70 if (style.pathEffect()) {
71 return false;
72 }
73 const SkStrokeRec& stroke = style.strokeRec();
74 if (stroke.isHairlineStyle()) {
75 if (outCoverage) {
76 *outCoverage = SK_Scalar1;
77 }
78 return true;
79 }
80 return stroke.getStyle() == SkStrokeRec::kStroke_Style &&
81 SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage);
82 }
83
84
GetPathDevBounds(const SkPath & path,int devW,int devH,const SkMatrix & matrix,SkRect * bounds)85 void GrPathRenderer::GetPathDevBounds(const SkPath& path,
86 int devW, int devH,
87 const SkMatrix& matrix,
88 SkRect* bounds) {
89 if (path.isInverseFillType()) {
90 *bounds = SkRect::MakeWH(SkIntToScalar(devW), SkIntToScalar(devH));
91 return;
92 }
93 *bounds = path.getBounds();
94 matrix.mapRect(bounds);
95 }
96
onStencilPath(const StencilPathArgs & args)97 void GrPathRenderer::onStencilPath(const StencilPathArgs& args) {
98 static constexpr GrUserStencilSettings kIncrementStencil(
99 GrUserStencilSettings::StaticInit<
100 0xffff,
101 GrUserStencilTest::kAlways,
102 0xffff,
103 GrUserStencilOp::kReplace,
104 GrUserStencilOp::kReplace,
105 0xffff>()
106 );
107
108 GrPaint paint;
109 DrawPathArgs drawArgs{args.fContext,
110 std::move(paint),
111 &kIncrementStencil,
112 args.fRenderTargetContext,
113 nullptr, // clip
114 args.fClipConservativeBounds,
115 args.fViewMatrix,
116 args.fShape,
117 (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone,
118 false};
119 this->drawPath(drawArgs);
120 }
121