blob: 47bb7aeec304171094f0c11135f49e6734fc7d21 [file] [log] [blame]
joshualitt1d89e8d2015-04-01 12:40:54 -07001/*
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 GrAtlasTextContext_DEFINED
9#define GrAtlasTextContext_DEFINED
10
11#include "GrTextContext.h"
12
joshualittb4c507e2015-04-08 08:07:59 -070013#include "GrBatchAtlas.h"
joshualittae32c102015-04-21 09:37:57 -070014#include "GrBatchFontCache.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070015#include "GrGeometryProcessor.h"
16#include "SkDescriptor.h"
joshualittb7133be2015-04-08 09:08:31 -070017#include "GrMemoryPool.h"
joshualitt53b5f442015-04-13 06:33:59 -070018#include "SkMaskFilter.h"
joshualitt9a27e632015-04-06 10:53:36 -070019#include "SkTextBlob.h"
joshualittb7133be2015-04-08 09:08:31 -070020#include "SkTInternalLList.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070021
joshualitt79dfb2b2015-05-11 08:58:08 -070022#ifdef GR_TEST_UTILS
23#include "GrBatchTest.h"
24#endif
25
26class BitmapTextBatch;
robertphillipsea461502015-05-26 11:38:03 -070027class GrDrawContext;
robertphillips2334fb62015-06-17 05:43:33 -070028class GrDrawTarget;
joshualitt1d89e8d2015-04-01 12:40:54 -070029class GrPipelineBuilder;
joshualittb7133be2015-04-08 09:08:31 -070030class GrTextBlobCache;
joshualitt1d89e8d2015-04-01 12:40:54 -070031
32/*
33 * This class implements GrTextContext using standard bitmap fonts, and can also process textblobs.
34 * TODO replace GrBitmapTextContext
35 */
joshualittdbd35932015-04-02 09:19:04 -070036class GrAtlasTextContext : public GrTextContext {
joshualitt1d89e8d2015-04-01 12:40:54 -070037public:
robertphillips2334fb62015-06-17 05:43:33 -070038 static GrAtlasTextContext* Create(GrContext*, GrDrawContext*,
39 const SkDeviceProperties&, bool enableDistanceFields);
joshualitt1d89e8d2015-04-01 12:40:54 -070040
joshualitt1d89e8d2015-04-01 12:40:54 -070041private:
robertphillips2334fb62015-06-17 05:43:33 -070042 GrAtlasTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&, bool useDFT);
joshualitt9bd2daf2015-04-17 09:30:06 -070043 ~GrAtlasTextContext() override {}
joshualitt1d89e8d2015-04-01 12:40:54 -070044
45 bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
46 const SkPaint&, const SkMatrix& viewMatrix) override;
47
robertphillips2334fb62015-06-17 05:43:33 -070048 void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
joshualitt1d89e8d2015-04-01 12:40:54 -070049 const SkMatrix& viewMatrix, const char text[], size_t byteLength,
50 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
robertphillips2334fb62015-06-17 05:43:33 -070051 void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&,
robertphillipsccb1b572015-05-27 11:02:55 -070052 const SkPaint&, const SkMatrix& viewMatrix,
joshualitt1d89e8d2015-04-01 12:40:54 -070053 const char text[], size_t byteLength,
54 const SkScalar pos[], int scalarsPerPosition,
55 const SkPoint& offset, const SkIRect& regionClipBounds) override;
robertphillips9c240a12015-05-28 07:45:59 -070056 void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
joshualitt1d89e8d2015-04-01 12:40:54 -070057 const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
58 SkDrawFilter*, const SkIRect& clipBounds) override;
59
joshualitt1d89e8d2015-04-01 12:40:54 -070060 /*
61 * A BitmapTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
62 * on the GPU. These are initially created with valid positions and colors, but invalid
63 * texture coordinates. The BitmapTextBlob itself has a few Blob-wide properties, and also
64 * consists of a number of runs. Runs inside a blob are flushed individually so they can be
65 * reordered.
66 *
67 * The only thing(aside from a memcopy) required to flush a BitmapTextBlob is to ensure that
68 * the GrAtlas will not evict anything the Blob needs.
joshualitt1d89e8d2015-04-01 12:40:54 -070069 */
70 struct BitmapTextBlob : public SkRefCnt {
joshualittb7133be2015-04-08 09:08:31 -070071 SK_DECLARE_INTERNAL_LLIST_INTERFACE(BitmapTextBlob);
72
joshualitt9a27e632015-04-06 10:53:36 -070073 /*
74 * Each Run inside of the blob can have its texture coordinates regenerated if required.
75 * To determine if regeneration is necessary, fAtlasGeneration is used. If there have been
76 * any evictions inside of the atlas, then we will simply regenerate Runs. We could track
77 * this at a more fine grained level, but its not clear if this is worth it, as evictions
78 * should be fairly rare.
79 *
80 * One additional point, each run can contain glyphs with any of the three mask formats.
81 * We call these SubRuns. Because a subrun must be a contiguous range, we have to create
82 * a new subrun each time the mask format changes in a run. In theory, a run can have as
83 * many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8. In
84 * practice, the vast majority of runs have only a single subrun.
85 *
86 * Finally, for runs where the entire thing is too large for the GrAtlasTextContext to
87 * handle, we have a bit to mark the run as flusahable via rendering as paths. It is worth
88 * pointing. It would be a bit expensive to figure out ahead of time whether or not a run
89 * can flush in this manner, so we always allocate vertices for the run, regardless of
90 * whether or not it is too large. The benefit of this strategy is that we can always reuse
91 * a blob allocation regardless of viewmatrix changes. We could store positions for these
92 * glyphs. However, its not clear if this is a win because we'd still have to either go the
93 * glyph cache to get the path at flush time, or hold onto the path in the cache, which
94 * would greatly increase the memory of these cached items.
95 */
joshualitt1d89e8d2015-04-01 12:40:54 -070096 struct Run {
joshualittc3c59902015-04-14 14:33:37 -070097 Run()
98 : fColor(GrColor_ILLEGAL)
99 , fInitialized(false)
100 , fDrawAsPaths(false) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700101 fVertexBounds.setLargestInverted();
joshualitt97202d22015-04-22 13:47:02 -0700102 // To ensure we always have one subrun, we push back a fresh run here
103 fSubRunInfo.push_back();
joshualitt1d89e8d2015-04-01 12:40:54 -0700104 }
105 struct SubRunInfo {
106 SubRunInfo()
107 : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration)
joshualitt1d89e8d2015-04-01 12:40:54 -0700108 , fVertexStartIndex(0)
joshualitt9bd2daf2015-04-17 09:30:06 -0700109 , fVertexEndIndex(0)
joshualitt8672f4d2015-04-21 08:03:04 -0700110 , fGlyphStartIndex(0)
111 , fGlyphEndIndex(0)
joshualitt9bd2daf2015-04-17 09:30:06 -0700112 , fDrawAsDistanceFields(false) {}
joshualittfec19e12015-04-17 10:32:32 -0700113 // Distance field text cannot draw coloremoji, and so has to fall back. However,
114 // though the distance field text and the coloremoji may share the same run, they
115 // will have different descriptors. If fOverrideDescriptor is non-NULL, then it
116 // will be used in place of the run's descriptor to regen texture coords
117 // TODO we could have a descriptor cache, it would reduce the size of these blobs
118 // significantly, and then the subrun could just have a refed pointer to the
119 // correct descriptor.
joshualitt8672f4d2015-04-21 08:03:04 -0700120 GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken;
121 uint64_t fAtlasGeneration;
122 size_t fVertexStartIndex;
123 size_t fVertexEndIndex;
124 uint32_t fGlyphStartIndex;
125 uint32_t fGlyphEndIndex;
126 SkScalar fTextRatio; // df property
127 GrMaskFormat fMaskFormat;
128 bool fDrawAsDistanceFields; // df property
129 bool fUseLCDText; // df property
joshualitt1d89e8d2015-04-01 12:40:54 -0700130 };
joshualittc3c59902015-04-14 14:33:37 -0700131
joshualitt97202d22015-04-22 13:47:02 -0700132 SubRunInfo& push_back() {
133 // Forward glyph / vertex information to seed the new sub run
134 SubRunInfo& prevSubRun = fSubRunInfo.back();
135 SubRunInfo& newSubRun = fSubRunInfo.push_back();
136 newSubRun.fGlyphStartIndex = prevSubRun.fGlyphEndIndex;
137 newSubRun.fGlyphEndIndex = prevSubRun.fGlyphEndIndex;
joshualittc3c59902015-04-14 14:33:37 -0700138
joshualitt97202d22015-04-22 13:47:02 -0700139 newSubRun.fVertexStartIndex = prevSubRun.fVertexEndIndex;
140 newSubRun.fVertexEndIndex = prevSubRun.fVertexEndIndex;
141 return newSubRun;
142 }
143 static const int kMinSubRuns = 1;
joshualittae32c102015-04-21 09:37:57 -0700144 SkAutoTUnref<GrBatchTextStrike> fStrike;
joshualitt1d89e8d2015-04-01 12:40:54 -0700145 SkAutoTUnref<SkTypeface> fTypeface;
146 SkRect fVertexBounds;
joshualitt97202d22015-04-22 13:47:02 -0700147 SkSTArray<kMinSubRuns, SubRunInfo> fSubRunInfo;
joshualitt8672f4d2015-04-21 08:03:04 -0700148 SkAutoDescriptor fDescriptor;
joshualitt97202d22015-04-22 13:47:02 -0700149 SkAutoTDelete<SkAutoDescriptor> fOverrideDescriptor; // df properties
joshualitt1d89e8d2015-04-01 12:40:54 -0700150 GrColor fColor;
151 bool fInitialized;
joshualitt9a27e632015-04-06 10:53:36 -0700152 bool fDrawAsPaths;
joshualitt1d89e8d2015-04-01 12:40:54 -0700153 };
154
155 struct BigGlyph {
joshualitt19e4c022015-05-13 11:23:03 -0700156 BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy)
157 : fPath(path)
158 , fVx(vx)
159 , fVy(vy) {}
joshualitt1d89e8d2015-04-01 12:40:54 -0700160 SkPath fPath;
joshualitt19e4c022015-05-13 11:23:03 -0700161 SkScalar fVx;
162 SkScalar fVy;
joshualitt1d89e8d2015-04-01 12:40:54 -0700163 };
joshualitt1d89e8d2015-04-01 12:40:54 -0700164
joshualitt53b5f442015-04-13 06:33:59 -0700165 struct Key {
166 Key() {
joshualitt9e36c1a2015-04-14 12:17:27 -0700167 sk_bzero(this, sizeof(Key));
joshualitt53b5f442015-04-13 06:33:59 -0700168 }
169 uint32_t fUniqueID;
joshualitt9e36c1a2015-04-14 12:17:27 -0700170 // Color may affect the gamma of the mask we generate, but in a fairly limited way.
171 // Each color is assigned to on of a fixed number of buckets based on its
172 // luminance. For each luminance bucket there is a "canonical color" that
173 // represents the bucket. This functionality is currently only supported for A8
174 SkColor fCanonicalColor;
joshualitte4cee1f2015-05-11 13:04:28 -0700175 SkPaint::Style fStyle;
176 SkPixelGeometry fPixelGeometry;
joshualitt53b5f442015-04-13 06:33:59 -0700177 bool fHasBlur;
178
179 bool operator==(const Key& other) const {
180 return 0 == memcmp(this, &other, sizeof(Key));
181 }
182 };
joshualitt8672f4d2015-04-21 08:03:04 -0700183
184 struct StrokeInfo {
185 SkScalar fFrameWidth;
186 SkScalar fMiterLimit;
187 SkPaint::Join fJoin;
188 };
189
190 enum TextType {
191 kHasDistanceField_TextType = 0x1,
192 kHasBitmap_TextType = 0x2,
193 };
194
195 // all glyph / vertex offsets are into these pools.
196 unsigned char* fVertices;
joshualittae32c102015-04-21 09:37:57 -0700197 GrGlyph** fGlyphs;
joshualitt8672f4d2015-04-21 08:03:04 -0700198 Run* fRuns;
199 GrMemoryPool* fPool;
200 SkMaskFilter::BlurRec fBlurRec;
201 StrokeInfo fStrokeInfo;
202 SkTArray<BigGlyph> fBigGlyphs;
joshualitt53b5f442015-04-13 06:33:59 -0700203 Key fKey;
joshualitt8672f4d2015-04-21 08:03:04 -0700204 SkMatrix fViewMatrix;
joshualitt64c99cc2015-04-21 09:43:03 -0700205 SkColor fPaintColor;
joshualitt8672f4d2015-04-21 08:03:04 -0700206 SkScalar fX;
207 SkScalar fY;
joshualitt64c99cc2015-04-21 09:43:03 -0700208
209 // We can reuse distance field text, but only if the new viewmatrix would not result in
210 // a mip change. Because there can be multiple runs in a blob, we track the overall
211 // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
212 SkScalar fMaxMinScale;
213 SkScalar fMinMaxScale;
joshualitt8672f4d2015-04-21 08:03:04 -0700214 int fRunCount;
215 uint8_t fTextType;
216
joshualitt64c99cc2015-04-21 09:43:03 -0700217 BitmapTextBlob()
joshualitta7c63892015-04-21 13:24:37 -0700218 : fMaxMinScale(-SK_ScalarMax)
joshualitt64c99cc2015-04-21 09:43:03 -0700219 , fMinMaxScale(SK_ScalarMax)
220 , fTextType(0) {}
joshualitt53b5f442015-04-13 06:33:59 -0700221
joshualitt12c20e42015-04-22 11:24:20 -0700222 ~BitmapTextBlob() override {
223 for (int i = 0; i < fRunCount; i++) {
224 fRuns[i].~Run();
225 }
226 }
227
joshualitt53b5f442015-04-13 06:33:59 -0700228 static const Key& GetKey(const BitmapTextBlob& blob) {
229 return blob.fKey;
joshualittb7133be2015-04-08 09:08:31 -0700230 }
231
joshualitt53b5f442015-04-13 06:33:59 -0700232 static uint32_t Hash(const Key& key) {
233 return SkChecksum::Murmur3(&key, sizeof(Key));
joshualitt1d89e8d2015-04-01 12:40:54 -0700234 }
235
joshualittb7133be2015-04-08 09:08:31 -0700236 void operator delete(void* p) {
237 BitmapTextBlob* blob = reinterpret_cast<BitmapTextBlob*>(p);
238 blob->fPool->release(p);
239 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700240 void* operator new(size_t) {
241 SkFAIL("All blobs are created by placement new.");
242 return sk_malloc_throw(0);
243 }
244
245 void* operator new(size_t, void* p) { return p; }
246 void operator delete(void* target, void* placement) {
247 ::operator delete(target, placement);
248 }
joshualittfcfb9fc2015-04-21 07:35:10 -0700249
250 bool hasDistanceField() const { return SkToBool(fTextType & kHasDistanceField_TextType); }
251 bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
252 void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
253 void setHasBitmap() { fTextType |= kHasBitmap_TextType; }
joshualitt1d89e8d2015-04-01 12:40:54 -0700254 };
255
256 typedef BitmapTextBlob::Run Run;
257 typedef Run::SubRunInfo PerSubRunInfo;
258
joshualitt9bd2daf2015-04-17 09:30:06 -0700259 inline bool canDrawAsDistanceFields(const SkPaint&, const SkMatrix& viewMatrix);
260 BitmapTextBlob* setupDFBlob(int glyphCount, const SkPaint& origPaint,
261 const SkMatrix& viewMatrix, SkGlyphCache** cache,
262 SkPaint* dfPaint, SkScalar* textRatio);
263 void bmpAppendGlyph(BitmapTextBlob*, int runIndex, GrGlyph::PackedID, int left, int top,
264 GrColor color, GrFontScaler*, const SkIRect& clipRect);
265 bool dfAppendGlyph(BitmapTextBlob*, int runIndex, GrGlyph::PackedID, SkScalar sx, SkScalar sy,
266 GrColor color, GrFontScaler*, const SkIRect& clipRect, SkScalar textRatio,
267 const SkMatrix& viewMatrix);
268 inline void appendGlyphPath(BitmapTextBlob* blob, GrGlyph* glyph,
joshualitt19e4c022015-05-13 11:23:03 -0700269 GrFontScaler* scaler, SkScalar x, SkScalar y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700270 inline void appendGlyphCommon(BitmapTextBlob*, Run*, Run::SubRunInfo*,
271 const SkRect& positions, GrColor color,
272 size_t vertexStride, bool useVertexColor,
joshualittae32c102015-04-21 09:37:57 -0700273 GrGlyph*);
joshualitt9a27e632015-04-06 10:53:36 -0700274
robertphillips2334fb62015-06-17 05:43:33 -0700275 inline void flushRunAsPaths(GrRenderTarget*,
robertphillipsccb1b572015-05-27 11:02:55 -0700276 const SkTextBlob::RunIterator&, const GrClip& clip,
277 const SkPaint&, SkDrawFilter*,
joshualitt9a27e632015-04-06 10:53:36 -0700278 const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
279 SkScalar y);
joshualitt79dfb2b2015-05-11 08:58:08 -0700280 inline BitmapTextBatch* createBatch(BitmapTextBlob*, const PerSubRunInfo&,
281 int glyphCount, int run, int subRun,
282 GrColor, SkScalar transX, SkScalar transY,
283 const SkPaint&);
robertphillips2334fb62015-06-17 05:43:33 -0700284 inline void flushRun(GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
joshualitt9bd2daf2015-04-17 09:30:06 -0700285 SkScalar transX, SkScalar transY, const SkPaint&);
robertphillips2334fb62015-06-17 05:43:33 -0700286 inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget*,
robertphillipsccb1b572015-05-27 11:02:55 -0700287 const GrClip& clip, const SkPaint& skPaint,
joshualitt1107e902015-05-11 14:52:11 -0700288 SkScalar transX, SkScalar transY, const SkIRect& clipBounds);
joshualitt9a27e632015-04-06 10:53:36 -0700289
290 // We have to flush SkTextBlobs differently from drawText / drawPosText
robertphillips2334fb62015-06-17 05:43:33 -0700291 void flush(const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
robertphillipsccb1b572015-05-27 11:02:55 -0700292 const SkPaint&, const GrPaint&, SkDrawFilter*, const GrClip&,
293 const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y,
294 SkScalar transX, SkScalar transY);
robertphillips2334fb62015-06-17 05:43:33 -0700295 void flush(BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
joshualitt1107e902015-05-11 14:52:11 -0700296 const GrPaint&, const GrClip&, const SkIRect& clipBounds);
joshualitt1d89e8d2015-04-01 12:40:54 -0700297
joshualitt9bd2daf2015-04-17 09:30:06 -0700298 // A helper for drawing BitmapText in a run of distance fields
joshualittfcfb9fc2015-04-21 07:35:10 -0700299 inline void fallbackDrawPosText(BitmapTextBlob*, int runIndex,
300 GrRenderTarget*, const GrClip&,
joshualitt9bd2daf2015-04-17 09:30:06 -0700301 const GrPaint&,
302 const SkPaint&, const SkMatrix& viewMatrix,
303 const SkTDArray<char>& fallbackTxt,
304 const SkTDArray<SkScalar>& fallbackPos,
305 int scalarsPerPosition,
306 const SkPoint& offset,
307 const SkIRect& clipRect);
308
309 void internalDrawBMPText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
joshualitt9e36c1a2015-04-14 12:17:27 -0700310 GrColor color, const SkMatrix& viewMatrix,
joshualitt1d89e8d2015-04-01 12:40:54 -0700311 const char text[], size_t byteLength,
joshualitt9bd2daf2015-04-17 09:30:06 -0700312 SkScalar x, SkScalar y, const SkIRect& clipRect);
313 void internalDrawBMPPosText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
314 GrColor color, const SkMatrix& viewMatrix,
315 const char text[], size_t byteLength,
316 const SkScalar pos[], int scalarsPerPosition,
317 const SkPoint& offset, const SkIRect& clipRect);
318
319 void internalDrawDFText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
320 GrColor color, const SkMatrix& viewMatrix,
321 const char text[], size_t byteLength,
322 SkScalar x, SkScalar y, const SkIRect& clipRect,
323 SkScalar textRatio,
324 SkTDArray<char>* fallbackTxt,
325 SkTDArray<SkScalar>* fallbackPos,
326 SkPoint* offset, const SkPaint& origPaint);
327 void internalDrawDFPosText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
328 GrColor color, const SkMatrix& viewMatrix,
329 const char text[], size_t byteLength,
330 const SkScalar pos[], int scalarsPerPosition,
331 const SkPoint& offset, const SkIRect& clipRect,
332 SkScalar textRatio,
333 SkTDArray<char>* fallbackTxt,
334 SkTDArray<SkScalar>* fallbackPos);
joshualitt1d89e8d2015-04-01 12:40:54 -0700335
336 // sets up the descriptor on the blob and returns a detached cache. Client must attach
joshualitt9e36c1a2015-04-14 12:17:27 -0700337 inline static GrColor ComputeCanonicalColor(const SkPaint&, bool lcd);
joshualitt9bd2daf2015-04-17 09:30:06 -0700338 inline SkGlyphCache* setupCache(Run*, const SkPaint&, const SkMatrix* viewMatrix, bool noGamma);
joshualitt2a0e9f32015-04-13 06:12:21 -0700339 static inline bool MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTransY,
340 const BitmapTextBlob&, const SkPaint&,
joshualitt53b5f442015-04-13 06:33:59 -0700341 const SkMaskFilter::BlurRec&,
joshualitt1d89e8d2015-04-01 12:40:54 -0700342 const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
robertphillips9c240a12015-05-28 07:45:59 -0700343 void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, GrColor,
joshualitt9e36c1a2015-04-14 12:17:27 -0700344 const SkMatrix& viewMatrix,
joshualitt1d89e8d2015-04-01 12:40:54 -0700345 const SkTextBlob* blob, SkScalar x, SkScalar y,
joshualittfcfb9fc2015-04-21 07:35:10 -0700346 SkDrawFilter* drawFilter, const SkIRect& clipRect, GrRenderTarget*,
347 const GrClip&, const GrPaint&);
joshualitt9e36c1a2015-04-14 12:17:27 -0700348 inline static bool HasLCD(const SkTextBlob*);
joshualitt64c99cc2015-04-21 09:43:03 -0700349 inline void initDistanceFieldPaint(BitmapTextBlob*, SkPaint*, SkScalar* textRatio,
350 const SkMatrix&);
joshualitt9bd2daf2015-04-17 09:30:06 -0700351
joshualitt79dfb2b2015-05-11 08:58:08 -0700352 // Test methods
353 // TODO this is really ugly. It'd be much nicer if positioning could be moved to batch
354 inline BitmapTextBlob* createDrawTextBlob(GrRenderTarget*, const GrClip&, const GrPaint&,
355 const SkPaint&, const SkMatrix& viewMatrix,
356 const char text[], size_t byteLength,
357 SkScalar x, SkScalar y,
358 const SkIRect& regionClipBounds);
359 inline BitmapTextBlob* createDrawPosTextBlob(GrRenderTarget*, const GrClip&, const GrPaint&,
360 const SkPaint&, const SkMatrix& viewMatrix,
361 const char text[], size_t byteLength,
362 const SkScalar pos[], int scalarsPerPosition,
363 const SkPoint& offset,
364 const SkIRect& regionClipBounds);
365
joshualitt9bd2daf2015-04-17 09:30:06 -0700366 // Distance field text needs this table to compute a value for use in the fragment shader.
367 // Because the GrAtlasTextContext can go out of scope before the final flush, this needs to be
368 // refcnted and malloced
369 struct DistanceAdjustTable : public SkNVRefCnt<DistanceAdjustTable> {
370 DistanceAdjustTable(float gamma) { this->buildDistanceAdjustTable(gamma); }
371 ~DistanceAdjustTable() { SkDELETE_ARRAY(fTable); }
372
373 void buildDistanceAdjustTable(float gamma);
374
375 SkScalar& operator[] (int i) {
376 return fTable[i];
377 }
378
379 const SkScalar& operator[] (int i) const {
380 return fTable[i];
381 }
382
383 SkScalar* fTable;
384 };
joshualitt1d89e8d2015-04-01 12:40:54 -0700385
joshualitt1d89e8d2015-04-01 12:40:54 -0700386 GrBatchTextStrike* fCurrStrike;
joshualittb7133be2015-04-08 09:08:31 -0700387 GrTextBlobCache* fCache;
joshualitt9bd2daf2015-04-17 09:30:06 -0700388 bool fEnableDFRendering;
389 SkAutoTUnref<DistanceAdjustTable> fDistanceAdjustTable;
joshualitt1d89e8d2015-04-01 12:40:54 -0700390
joshualittb7133be2015-04-08 09:08:31 -0700391 friend class GrTextBlobCache;
joshualitt1d89e8d2015-04-01 12:40:54 -0700392 friend class BitmapTextBatch;
393
joshualitt79dfb2b2015-05-11 08:58:08 -0700394#ifdef GR_TEST_UTILS
joshualitt6c891102015-05-13 08:51:49 -0700395 BATCH_TEST_FRIEND(TextBlobBatch);
joshualitt79dfb2b2015-05-11 08:58:08 -0700396#endif
397
joshualitt1d89e8d2015-04-01 12:40:54 -0700398 typedef GrTextContext INHERITED;
399};
400
401#endif