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 "GrPathRendering.h"
9 #include "SkDescriptor.h"
10 #include "SkGlyph.h"
11 #include "SkMatrix.h"
12 #include "SkTypeface.h"
13 #include "GrPathRange.h"
14 
GetStencilPassSettings(FillType fill)15 const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
16     switch (fill) {
17         default:
18             SkFAIL("Unexpected path fill.");
19         case GrPathRendering::kWinding_FillType: {
20             constexpr static GrUserStencilSettings kWindingStencilPass(
21                 GrUserStencilSettings::StaticInit<
22                     0xffff,
23                     GrUserStencilTest::kAlwaysIfInClip,
24                     0xffff,
25                     GrUserStencilOp::kIncWrap,
26                     GrUserStencilOp::kIncWrap,
27                     0xffff>()
28             );
29             return kWindingStencilPass;
30         }
31         case GrPathRendering::kEvenOdd_FillType: {
32             constexpr static GrUserStencilSettings kEvenOddStencilPass(
33                 GrUserStencilSettings::StaticInit<
34                     0xffff,
35                     GrUserStencilTest::kAlwaysIfInClip,
36                     0xffff,
37                     GrUserStencilOp::kInvert,
38                     GrUserStencilOp::kInvert,
39                     0xffff>()
40             );
41             return kEvenOddStencilPass;
42         }
43     }
44 }
45 
46 class GlyphGenerator : public GrPathRange::PathGenerator {
47 public:
GlyphGenerator(const SkTypeface & typeface,const SkScalerContextEffects & effects,const SkDescriptor & desc)48     GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects,
49                    const SkDescriptor& desc)
50         : fScalerContext(typeface.createScalerContext(effects, &desc))
51 #ifdef SK_DEBUG
52         , fDesc(desc.copy())
53 #endif
54     {}
55 
getNumPaths()56     int getNumPaths() override {
57         return fScalerContext->getGlyphCount();
58     }
59 
generatePath(int glyphID,SkPath * out)60     void generatePath(int glyphID, SkPath* out) override {
61         fScalerContext->getPath(glyphID, out);
62     }
63 #ifdef SK_DEBUG
isEqualTo(const SkDescriptor & desc) const64     bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; }
65 #endif
66 private:
67     const std::unique_ptr<SkScalerContext> fScalerContext;
68 #ifdef SK_DEBUG
69     const std::unique_ptr<SkDescriptor> fDesc;
70 #endif
71 };
72 
createGlyphs(const SkTypeface * typeface,const SkScalerContextEffects & effects,const SkDescriptor * desc,const GrStyle & style)73 GrPathRange* GrPathRendering::createGlyphs(const SkTypeface* typeface,
74                                            const SkScalerContextEffects& effects,
75                                            const SkDescriptor* desc,
76                                            const GrStyle& style) {
77     if (nullptr == typeface) {
78         typeface = SkTypeface::GetDefaultTypeface();
79         SkASSERT(nullptr != typeface);
80     }
81 
82     if (desc) {
83         sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc));
84         return this->createPathRange(generator.get(), style);
85     }
86 
87     SkScalerContextRec rec;
88     memset(&rec, 0, sizeof(rec));
89     rec.fFontID = typeface->uniqueID();
90     rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths;
91     rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1;
92     // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking.
93 
94     SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
95     SkDescriptor*    genericDesc = ad.getDesc();
96 
97     genericDesc->init();
98     genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
99     genericDesc->computeChecksum();
100 
101     // No effects, so we make a dummy struct
102     SkScalerContextEffects noEffects;
103 
104     sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
105     return this->createPathRange(generator.get(), style);
106 }
107