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