1 /*
2 * Copyright 2014 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 "GrGpu.h"
9 #include "GrPathRendering.h"
10 #include "SkDescriptor.h"
11 #include "SkScalerContext.h"
12 #include "SkGlyph.h"
13 #include "SkMatrix.h"
14 #include "SkTypeface.h"
15 #include "GrPathRange.h"
16
GetStencilPassSettings(FillType fill)17 const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
18 switch (fill) {
19 default:
20 SK_ABORT("Unexpected path fill.");
21 case GrPathRendering::kWinding_FillType: {
22 constexpr static GrUserStencilSettings kWindingStencilPass(
23 GrUserStencilSettings::StaticInit<
24 0xffff,
25 GrUserStencilTest::kAlwaysIfInClip,
26 0xffff,
27 GrUserStencilOp::kIncWrap,
28 GrUserStencilOp::kIncWrap,
29 0xffff>()
30 );
31 return kWindingStencilPass;
32 }
33 case GrPathRendering::kEvenOdd_FillType: {
34 constexpr static GrUserStencilSettings kEvenOddStencilPass(
35 GrUserStencilSettings::StaticInit<
36 0xffff,
37 GrUserStencilTest::kAlwaysIfInClip,
38 0xffff,
39 GrUserStencilOp::kInvert,
40 GrUserStencilOp::kInvert,
41 0xffff>()
42 );
43 return kEvenOddStencilPass;
44 }
45 }
46 }
47
48 class GlyphGenerator : public GrPathRange::PathGenerator {
49 public:
GlyphGenerator(const SkTypeface & typeface,const SkScalerContextEffects & effects,const SkDescriptor & desc)50 GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects,
51 const SkDescriptor& desc)
52 : fScalerContext(typeface.createScalerContext(effects, &desc))
53 #ifdef SK_DEBUG
54 , fDesc(desc.copy())
55 #endif
56 {}
57
getNumPaths()58 int getNumPaths() override {
59 return fScalerContext->getGlyphCount();
60 }
61
generatePath(int glyphID,SkPath * out)62 void generatePath(int glyphID, SkPath* out) override {
63 fScalerContext->getPath(glyphID, out);
64 }
65 #ifdef SK_DEBUG
isEqualTo(const SkDescriptor & desc) const66 bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; }
67 #endif
68 private:
69 const std::unique_ptr<SkScalerContext> fScalerContext;
70 #ifdef SK_DEBUG
71 const std::unique_ptr<SkDescriptor> fDesc;
72 #endif
73 };
74
createGlyphs(const SkTypeface * typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc,const GrStyle & style)75 sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface,
76 const SkScalerContextEffects& effects,
77 const SkDescriptor* desc,
78 const GrStyle& style) {
79 if (nullptr == typeface) {
80 typeface = SkTypeface::GetDefaultTypeface();
81 SkASSERT(nullptr != typeface);
82 }
83
84 if (desc) {
85 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc));
86 return this->createPathRange(generator.get(), style);
87 }
88
89 SkAutoDescriptor ad;
90 SkDescriptor* genericDesc =
91 SkScalerContext::MakeDescriptorForPaths(typeface->uniqueID(), &ad);
92
93 // No effects, so we make a dummy struct
94 SkScalerContextEffects noEffects;
95
96 sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
97 return this->createPathRange(generator.get(), style);
98 }
99
stencilPath(const StencilPathArgs & args,const GrPath * path)100 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
101 fGpu->handleDirtyContext();
102 this->onStencilPath(args, path);
103 }
104
drawPath(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrStencilSettings & stencilPassSettings,const GrPath * path)105 void GrPathRendering::drawPath(const GrPipeline& pipeline,
106 const GrPrimitiveProcessor& primProc,
107 // Cover pass settings in pipeline.
108 const GrStencilSettings& stencilPassSettings,
109 const GrPath* path) {
110 fGpu->handleDirtyContext();
111 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
112 fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
113 }
114 this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
115 }
116
drawPaths(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrStencilSettings & stencilPassSettings,const GrPathRange * pathRange,const void * indices,PathIndexType indexType,const float transformValues[],PathTransformType transformType,int count)117 void GrPathRendering::drawPaths(const GrPipeline& pipeline,
118 const GrPrimitiveProcessor& primProc,
119 // Cover pass settings in pipeline.
120 const GrStencilSettings& stencilPassSettings,
121 const GrPathRange* pathRange,
122 const void* indices,
123 PathIndexType indexType,
124 const float transformValues[],
125 PathTransformType transformType,
126 int count) {
127 fGpu->handleDirtyContext();
128 if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
129 fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
130 }
131 #ifdef SK_DEBUG
132 pathRange->assertPathsLoaded(indices, indexType, count);
133 #endif
134 this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
135 transformValues, transformType, count);
136 }
137