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