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