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