• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 #ifndef GrAtlasTextOp_DEFINED
9 #define GrAtlasTextOp_DEFINED
10 
11 #include "ops/GrMeshDrawOp.h"
12 #include "text/GrAtlasTextContext.h"
13 #include "text/GrDistanceFieldAdjustTable.h"
14 
15 class GrAtlasTextOp final : public GrMeshDrawOp {
16 public:
17     DEFINE_OP_CLASS_ID
18 
~GrAtlasTextOp()19     ~GrAtlasTextOp() override {
20         for (int i = 0; i < fGeoCount; i++) {
21             fGeoData[i].fBlob->unref();
22         }
23     }
24 
25     static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph;
26     static const int kIndicesPerGlyph = 6;
27 
28     typedef GrAtlasTextBlob Blob;
29     struct Geometry {
30         SkMatrix fViewMatrix;
31         Blob* fBlob;
32         SkScalar fX;
33         SkScalar fY;
34         int fRun;
35         int fSubRun;
36         GrColor fColor;
37     };
38 
MakeBitmap(GrPaint && paint,GrMaskFormat maskFormat,int glyphCount,GrAtlasGlyphCache * fontCache)39     static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrPaint&& paint, GrMaskFormat maskFormat,
40                                                      int glyphCount, GrAtlasGlyphCache* fontCache) {
41         std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
42 
43         op->fFontCache = fontCache;
44         switch (maskFormat) {
45             case kA8_GrMaskFormat:
46                 op->fMaskType = kGrayscaleCoverageMask_MaskType;
47                 break;
48             case kA565_GrMaskFormat:
49                 op->fMaskType = kLCDCoverageMask_MaskType;
50                 break;
51             case kARGB_GrMaskFormat:
52                 op->fMaskType = kColorBitmapMask_MaskType;
53                 break;
54         }
55         op->fNumGlyphs = glyphCount;
56         op->fGeoCount = 1;
57         op->fLuminanceColor = 0;
58         op->fFontCache = fontCache;
59         return op;
60     }
61 
MakeDistanceField(GrPaint && paint,int glyphCount,GrAtlasGlyphCache * fontCache,const GrDistanceFieldAdjustTable * distanceAdjustTable,bool useGammaCorrectDistanceTable,SkColor luminanceColor,bool isLCD,bool useBGR,bool isAntiAliased)62     static std::unique_ptr<GrAtlasTextOp> MakeDistanceField(
63             GrPaint&& paint, int glyphCount, GrAtlasGlyphCache* fontCache,
64             const GrDistanceFieldAdjustTable* distanceAdjustTable,
65             bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR,
66             bool isAntiAliased) {
67         std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint)));
68 
69         op->fFontCache = fontCache;
70         op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType
71                                        : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType
72                                                          : kLCDDistanceField_MaskType)
73                                                : kGrayscaleDistanceField_MaskType;
74         op->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
75         op->fUseGammaCorrectDistanceTable = useGammaCorrectDistanceTable;
76         op->fLuminanceColor = luminanceColor;
77         op->fNumGlyphs = glyphCount;
78         op->fGeoCount = 1;
79         return op;
80     }
81 
82     // To avoid even the initial copy of the struct, we have a getter for the first item which
83     // is used to seed the op with its initial geometry.  After seeding, the client should call
84     // init() so the op can initialize itself
geometry()85     Geometry& geometry() { return fGeoData[0]; }
86 
init()87     void init() {
88         const Geometry& geo = fGeoData[0];
89         fColor = geo.fColor;
90         SkRect bounds;
91         geo.fBlob->computeSubRunBounds(&bounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
92                                        geo.fY);
93         // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
94         // we treat this as a set of non-AA rects rendered with a texture.
95         this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
96     }
97 
name()98     const char* name() const override { return "AtlasTextOp"; }
99 
100     SkString dumpInfo() const override;
101 
102     FixedFunctionFlags fixedFunctionFlags() const override;
103 
104     RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override;
105 
106 private:
GrAtlasTextOp(GrPaint && paint)107     GrAtlasTextOp(GrPaint&& paint)
108             : INHERITED(ClassID())
109             , fColor(paint.getColor())
110             , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
111             , fProcessors(std::move(paint)) {}
112 
113     struct FlushInfo {
114         sk_sp<const GrBuffer> fVertexBuffer;
115         sk_sp<const GrBuffer> fIndexBuffer;
116         sk_sp<GrGeometryProcessor> fGeometryProcessor;
117         const GrPipeline* fPipeline;
118         int fGlyphsToFlush;
119         int fVertexOffset;
120     };
121 
122     void onPrepareDraws(Target* target) const override;
123 
maskFormat()124     GrMaskFormat maskFormat() const {
125         switch (fMaskType) {
126             case kLCDCoverageMask_MaskType:
127                 return kA565_GrMaskFormat;
128             case kColorBitmapMask_MaskType:
129                 return kARGB_GrMaskFormat;
130             case kGrayscaleCoverageMask_MaskType:
131             case kAliasedDistanceField_MaskType:
132             case kGrayscaleDistanceField_MaskType:
133             case kLCDDistanceField_MaskType:
134             case kLCDBGRDistanceField_MaskType:
135                 return kA8_GrMaskFormat;
136         }
137         return kA8_GrMaskFormat;  // suppress warning
138     }
139 
usesDistanceFields()140     bool usesDistanceFields() const {
141         return kAliasedDistanceField_MaskType == fMaskType ||
142                kGrayscaleDistanceField_MaskType == fMaskType ||
143                kLCDDistanceField_MaskType == fMaskType ||
144                kLCDBGRDistanceField_MaskType == fMaskType;
145     }
146 
isLCD()147     bool isLCD() const {
148         return kLCDCoverageMask_MaskType == fMaskType ||
149                kLCDDistanceField_MaskType == fMaskType ||
150                kLCDBGRDistanceField_MaskType == fMaskType;
151     }
152 
153     inline void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const;
154 
color()155     GrColor color() const { return fColor; }
viewMatrix()156     const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
usesLocalCoords()157     bool usesLocalCoords() const { return fUsesLocalCoords; }
numGlyphs()158     int numGlyphs() const { return fNumGlyphs; }
159 
160     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override;
161 
162     // TODO just use class params
163     sk_sp<GrGeometryProcessor> setupDfProcessor(const SkMatrix& viewMatrix, SkColor luminanceColor,
164                                                 GrColor color, sk_sp<GrTextureProxy> proxy) const;
165 
166 
167     // The minimum number of Geometry we will try to allocate.
168     enum { kMinGeometryAllocated = 4 };
169 
170     enum MaskType {
171         kGrayscaleCoverageMask_MaskType,
172         kLCDCoverageMask_MaskType,
173         kColorBitmapMask_MaskType,
174         kAliasedDistanceField_MaskType,
175         kGrayscaleDistanceField_MaskType,
176         kLCDDistanceField_MaskType,
177         kLCDBGRDistanceField_MaskType,
178     };
179 
180     SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
181     GrColor fColor;
182     uint32_t fSRGBFlags;
183     GrProcessorSet fProcessors;
184     bool fUsesLocalCoords;
185     bool fCanCombineOnTouchOrOverlap;
186     int fGeoCount;
187     int fNumGlyphs;
188     MaskType fMaskType;
189     GrAtlasGlyphCache* fFontCache;
190     // Distance field properties
191     sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
192     SkColor fLuminanceColor;
193     bool fUseGammaCorrectDistanceTable;
194 
195     friend class GrBlobRegenHelper;  // Needs to trigger flushes
196 
197     typedef GrMeshDrawOp INHERITED;
198 };
199 
200 /*
201  * A simple helper class to abstract the interface GrAtlasTextBlob needs to regenerate itself.
202  * It'd be nicer if this was nested, but we need to forward declare it in GrAtlasTextBlob.h
203  */
204 class GrBlobRegenHelper {
205 public:
GrBlobRegenHelper(const GrAtlasTextOp * op,GrMeshDrawOp::Target * target,GrAtlasTextOp::FlushInfo * flushInfo)206     GrBlobRegenHelper(const GrAtlasTextOp* op, GrMeshDrawOp::Target* target,
207                       GrAtlasTextOp::FlushInfo* flushInfo)
208             : fOp(op), fTarget(target), fFlushInfo(flushInfo) {}
209 
210     void flush();
211 
212     void incGlyphCount(int glyphCount = 1) { fFlushInfo->fGlyphsToFlush += glyphCount; }
213 
214 private:
215     const GrAtlasTextOp* fOp;
216     GrMeshDrawOp::Target* fTarget;
217     GrAtlasTextOp::FlushInfo* fFlushInfo;
218 };
219 
220 #endif
221