• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     SkScalerContextRec rec;
90     memset(&rec, 0, sizeof(rec));
91     rec.fFontID = typeface->uniqueID();
92     rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths;
93     rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1;
94     // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking.
95 
96     SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
97     SkDescriptor*    genericDesc = ad.getDesc();
98 
99     genericDesc->init();
100     genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
101     genericDesc->computeChecksum();
102 
103     // No effects, so we make a dummy struct
104     SkScalerContextEffects noEffects;
105 
106     sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
107     return this->createPathRange(generator.get(), style);
108 }
109 
stencilPath(const StencilPathArgs & args,const GrPath * path)110 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
111     fGpu->handleDirtyContext();
112     this->onStencilPath(args, path);
113 }
114 
drawPath(const GrPipeline & pipeline,const GrPrimitiveProcessor & primProc,const GrStencilSettings & stencilPassSettings,const GrPath * path)115 void GrPathRendering::drawPath(const GrPipeline& pipeline,
116                                const GrPrimitiveProcessor& primProc,
117                                // Cover pass settings in pipeline.
118                                const GrStencilSettings& stencilPassSettings,
119                                const GrPath* path) {
120     fGpu->handleDirtyContext();
121     if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
122         fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
123     }
124     this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
125 }
126 
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)127 void GrPathRendering::drawPaths(const GrPipeline& pipeline,
128                                 const GrPrimitiveProcessor& primProc,
129                                 // Cover pass settings in pipeline.
130                                 const GrStencilSettings& stencilPassSettings,
131                                 const GrPathRange* pathRange,
132                                 const void* indices,
133                                 PathIndexType indexType,
134                                 const float transformValues[],
135                                 PathTransformType transformType,
136                                 int count) {
137     fGpu->handleDirtyContext();
138     if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
139         fGpu->xferBarrier(pipeline.renderTarget(), barrierType);
140     }
141 #ifdef SK_DEBUG
142     pathRange->assertPathsLoaded(indices, indexType, count);
143 #endif
144     this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
145                       transformValues, transformType, count);
146 }
147