blob: 85030686cc9d5baf50fa2406713065d195e7b379 [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#include "GrAtlasTextContext.h"
8
robertphillipsea461502015-05-26 11:38:03 -07009#include "GrDrawContext.h"
robertphillips2334fb62015-06-17 05:43:33 -070010#include "GrDrawTarget.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070011#include "GrFontScaler.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070012#include "GrStrokeInfo.h"
joshualittb7133be2015-04-08 09:08:31 -070013#include "GrTextBlobCache.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070014#include "GrTexturePriv.h"
joshualitt29677982015-12-11 06:08:59 -080015#include "GrTextUtils.h"
bsalomon72e3ae42015-04-28 08:08:46 -070016#include "GrVertexBuffer.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070017
18#include "SkAutoKern.h"
19#include "SkColorPriv.h"
joshualitt9bd2daf2015-04-17 09:30:06 -070020#include "SkColorFilter.h"
21#include "SkDistanceFieldGen.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070022#include "SkDraw.h"
23#include "SkDrawFilter.h"
24#include "SkDrawProcs.h"
herb9be5ff62015-11-11 11:30:11 -080025#include "SkFindAndPlaceGlyph.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070026#include "SkGlyphCache.h"
27#include "SkGpuDevice.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070028#include "SkGrPriv.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070029#include "SkPath.h"
30#include "SkRTConf.h"
31#include "SkStrokeRec.h"
32#include "SkTextBlob.h"
33#include "SkTextMapStateProc.h"
34
joshualitta751c972015-11-20 13:37:32 -080035#include "batches/GrAtlasTextBatch.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070036
robertphillipsf6703fa2015-09-01 05:36:47 -070037GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps& surfaceProps)
38 : INHERITED(context, surfaceProps)
joshualitt1acabf32015-12-10 09:10:10 -080039 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) {
joshualittb7133be2015-04-08 09:08:31 -070040 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
41 // vertexStride
joshualittf528e0d2015-12-09 06:42:52 -080042 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTextVASize &&
43 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextVASize,
bungeman99fe8222015-08-20 07:57:51 -070044 "vertex_attribute_changed");
halcanary96fcdcc2015-08-27 07:41:13 -070045 fCurrStrike = nullptr;
joshualittb7133be2015-04-08 09:08:31 -070046 fCache = context->getTextBlobCache();
joshualitt9bd2daf2015-04-17 09:30:06 -070047}
48
joshualitt1d89e8d2015-04-01 12:40:54 -070049
joshualittdbd35932015-04-02 09:19:04 -070050GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
robertphillipsfcf78292015-06-19 11:49:52 -070051 const SkSurfaceProps& surfaceProps) {
robertphillipsf6703fa2015-09-01 05:36:47 -070052 return new GrAtlasTextContext(context, surfaceProps);
joshualitt1d89e8d2015-04-01 12:40:54 -070053}
54
robertphillips6ee690e2015-12-02 08:57:50 -080055bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, const SkMatrix& viewMatrix) {
joshualitt0d2199b2016-01-20 06:36:09 -080056 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps,
57 *fContext->caps()->shaderCaps()) ||
joshualitt9bd2daf2015-04-17 09:30:06 -070058 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
joshualitt1d89e8d2015-04-01 12:40:54 -070059}
60
joshualitt9e36c1a2015-04-14 12:17:27 -070061GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) {
62 GrColor canonicalColor = paint.computeLuminanceColor();
63 if (lcd) {
64 // This is the correct computation, but there are tons of cases where LCD can be overridden.
65 // For now we just regenerate if any run in a textblob has LCD.
66 // TODO figure out where all of these overrides are and see if we can incorporate that logic
67 // at a higher level *OR* use sRGB
68 SkASSERT(false);
69 //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
70 } else {
71 // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
72 // gamma corrected masks anyways, nor color
73 U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
74 SkColorGetG(canonicalColor),
75 SkColorGetB(canonicalColor));
76 // reduce to our finite number of bits
77 canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
78 }
79 return canonicalColor;
80}
81
82// TODO if this function ever shows up in profiling, then we can compute this value when the
83// textblob is being built and cache it. However, for the time being textblobs mostly only have 1
84// run so this is not a big deal to compute here.
85bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) {
halcanary33779752015-10-27 14:01:05 -070086 SkTextBlobRunIterator it(blob);
joshualitt9e36c1a2015-04-14 12:17:27 -070087 for (; !it.done(); it.next()) {
88 if (it.isLCD()) {
89 return true;
90 }
91 }
92 return false;
93}
94
robertphillips433625e2015-12-04 06:58:16 -080095void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc,
robertphillipsccb1b572015-05-27 11:02:55 -070096 const GrClip& clip, const SkPaint& skPaint,
97 const SkMatrix& viewMatrix, const SkTextBlob* blob,
98 SkScalar x, SkScalar y,
joshualittdbd35932015-04-02 09:19:04 -070099 SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
joshualitt9b8e79e2015-04-24 09:57:12 -0700100 // If we have been abandoned, then don't draw
robertphillipsea461502015-05-26 11:38:03 -0700101 if (fContext->abandoned()) {
102 return;
103 }
104
joshualitt374b2f72015-07-21 08:05:03 -0700105 SkAutoTUnref<GrAtlasTextBlob> cacheBlob;
joshualitt53b5f442015-04-13 06:33:59 -0700106 SkMaskFilter::BlurRec blurRec;
joshualitt374b2f72015-07-21 08:05:03 -0700107 GrAtlasTextBlob::Key key;
joshualitt53b5f442015-04-13 06:33:59 -0700108 // It might be worth caching these things, but its not clear at this time
109 // TODO for animated mask filters, this will fill up our cache. We need a safeguard here
110 const SkMaskFilter* mf = skPaint.getMaskFilter();
joshualitt2a0e9f32015-04-13 06:12:21 -0700111 bool canCache = !(skPaint.getPathEffect() ||
joshualitt53b5f442015-04-13 06:33:59 -0700112 (mf && !mf->asABlur(&blurRec)) ||
joshualitt2a0e9f32015-04-13 06:12:21 -0700113 drawFilter);
114
115 if (canCache) {
joshualitt9e36c1a2015-04-14 12:17:27 -0700116 bool hasLCD = HasLCD(blob);
joshualitte4cee1f2015-05-11 13:04:28 -0700117
118 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
robertphillipsfcf78292015-06-19 11:49:52 -0700119 SkPixelGeometry pixelGeometry = hasLCD ? fSurfaceProps.pixelGeometry() :
joshualitte4cee1f2015-05-11 13:04:28 -0700120 kUnknown_SkPixelGeometry;
121
joshualitt9e36c1a2015-04-14 12:17:27 -0700122 // TODO we want to figure out a way to be able to use the canonical color on LCD text,
123 // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
124 // ensure we always match the same key
125 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
126 ComputeCanonicalColor(skPaint, hasLCD);
127
joshualitte4cee1f2015-05-11 13:04:28 -0700128 key.fPixelGeometry = pixelGeometry;
joshualitt53b5f442015-04-13 06:33:59 -0700129 key.fUniqueID = blob->uniqueID();
130 key.fStyle = skPaint.getStyle();
131 key.fHasBlur = SkToBool(mf);
joshualitt9e36c1a2015-04-14 12:17:27 -0700132 key.fCanonicalColor = canonicalColor;
joshualitt53b5f442015-04-13 06:33:59 -0700133 cacheBlob.reset(SkSafeRef(fCache->find(key)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700134 }
135
joshualitt2a0e9f32015-04-13 06:12:21 -0700136 SkScalar transX = 0.f;
137 SkScalar transY = 0.f;
138
joshualitt9e36c1a2015-04-14 12:17:27 -0700139 // Though for the time being runs in the textblob can override the paint, they only touch font
140 // info.
141 GrPaint grPaint;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700142 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700143 return;
144 }
joshualitt9e36c1a2015-04-14 12:17:27 -0700145
joshualittb7133be2015-04-08 09:08:31 -0700146 if (cacheBlob) {
joshualittfd5f6c12015-12-10 07:44:50 -0800147 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColor(), blurRec,
148 viewMatrix, x, y)) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700149 // We have to remake the blob because changes may invalidate our masks.
150 // TODO we could probably get away reuse most of the time if the pointer is unique,
151 // but we'd have to clear the subrun information
joshualittb7133be2015-04-08 09:08:31 -0700152 fCache->remove(cacheBlob);
joshualitt53b5f442015-04-13 06:33:59 -0700153 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint,
joshualittf528e0d2015-12-09 06:42:52 -0800154 GrAtlasTextBlob::kGrayTextVASize)));
robertphillips9c240a12015-05-28 07:45:59 -0700155 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix,
joshualitta6bf4c52016-01-19 06:59:29 -0800156 blob, x, y, drawFilter);
joshualittb7133be2015-04-08 09:08:31 -0700157 } else {
158 fCache->makeMRU(cacheBlob);
joshualitt259fbf12015-07-21 11:39:34 -0700159#ifdef CACHE_SANITY_CHECK
160 {
161 int glyphCount = 0;
162 int runCount = 0;
163 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
164 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyphCount, runCount,
165 kGrayTextVASize));
166 GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skPaint);
167 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor(), viewMatrix,
joshualitta6bf4c52016-01-19 06:59:29 -0800168 blob, x, y, drawFilter);
joshualitt259fbf12015-07-21 11:39:34 -0700169 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
170 }
171
172#endif
joshualitt1d89e8d2015-04-01 12:40:54 -0700173 }
174 } else {
joshualitt2a0e9f32015-04-13 06:12:21 -0700175 if (canCache) {
joshualitt53b5f442015-04-13 06:33:59 -0700176 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint,
joshualittf528e0d2015-12-09 06:42:52 -0800177 GrAtlasTextBlob::kGrayTextVASize)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700178 } else {
joshualittf528e0d2015-12-09 06:42:52 -0800179 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBlob::kGrayTextVASize));
joshualitt2a0e9f32015-04-13 06:12:21 -0700180 }
robertphillips9c240a12015-05-28 07:45:59 -0700181 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix,
joshualitta6bf4c52016-01-19 06:59:29 -0800182 blob, x, y, drawFilter);
joshualitt1d89e8d2015-04-01 12:40:54 -0700183 }
184
joshualitt0a42e682015-12-10 13:20:58 -0800185 cacheBlob->flushCached(fContext, dc, blob, fSurfaceProps, fDistanceAdjustTable, skPaint,
joshualitt2e2202e2015-12-10 11:22:08 -0800186 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY);
joshualitt1d89e8d2015-04-01 12:40:54 -0700187}
188
joshualitt374b2f72015-07-21 08:05:03 -0700189void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
joshualitt9e36c1a2015-04-14 12:17:27 -0700190 const SkPaint& skPaint, GrColor color,
191 const SkMatrix& viewMatrix,
joshualittdbd35932015-04-02 09:19:04 -0700192 const SkTextBlob* blob, SkScalar x, SkScalar y,
joshualitta6bf4c52016-01-19 06:59:29 -0800193 SkDrawFilter* drawFilter) {
herbe59124e2015-11-18 10:54:39 -0800194 // The color here is the GrPaint color, and it is used to determine whether we
jvanverth0628a522015-08-18 07:44:22 -0700195 // have to regenerate LCD text blobs.
196 // We use this color vs the SkPaint color because it has the colorfilter applied.
197 cacheBlob->fPaintColor = color;
joshualitt1d89e8d2015-04-01 12:40:54 -0700198 cacheBlob->fViewMatrix = viewMatrix;
199 cacheBlob->fX = x;
200 cacheBlob->fY = y;
joshualitt1d89e8d2015-04-01 12:40:54 -0700201
202 // Regenerate textblob
203 SkPaint runPaint = skPaint;
halcanary33779752015-10-27 14:01:05 -0700204 SkTextBlobRunIterator it(blob);
joshualitt1d89e8d2015-04-01 12:40:54 -0700205 for (int run = 0; !it.done(); it.next(), run++) {
206 int glyphCount = it.glyphCount();
207 size_t textLen = glyphCount * sizeof(uint16_t);
208 const SkPoint& offset = it.offset();
209 // applyFontToPaint() always overwrites the exact same attributes,
210 // so it is safe to not re-seed the paint for this reason.
211 it.applyFontToPaint(&runPaint);
212
213 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
214 // A false return from filter() means we should abort the current draw.
215 runPaint = skPaint;
216 continue;
217 }
218
robertphillipsfcf78292015-06-19 11:49:52 -0700219 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint));
joshualitt1d89e8d2015-04-01 12:40:54 -0700220
joshualitt18b072d2015-12-07 12:26:12 -0800221 cacheBlob->push_back_run(run);
joshualitt1d89e8d2015-04-01 12:40:54 -0700222
joshualitt0d2199b2016-01-20 06:36:09 -0800223 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, fSurfaceProps,
224 *fContext->caps()->shaderCaps())) {
joshualittfcfb9fc2015-04-21 07:35:10 -0700225 switch (it.positioning()) {
226 case SkTextBlob::kDefault_Positioning: {
joshualitt0d2199b2016-01-20 06:36:09 -0800227 GrTextUtils::DrawDFText(cacheBlob, run, fContext->getBatchFontCache(),
228 fSurfaceProps, runPaint, color, viewMatrix,
229 (const char *)it.glyphs(), textLen,
230 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700231 break;
232 }
233 case SkTextBlob::kHorizontal_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800234 SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
joshualitt0d2199b2016-01-20 06:36:09 -0800235 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatchFontCache(),
236 fSurfaceProps, runPaint, color, viewMatrix,
237 (const char*)it.glyphs(), textLen, it.pos(),
238 1, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700239 break;
240 }
241 case SkTextBlob::kFull_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800242 SkPoint dfOffset = SkPoint::Make(x, y);
joshualitt0d2199b2016-01-20 06:36:09 -0800243 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatchFontCache(),
244 fSurfaceProps, runPaint, color, viewMatrix,
245 (const char*)it.glyphs(), textLen, it.pos(),
246 2, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700247 break;
248 }
249 }
joshualittfcfb9fc2015-04-21 07:35:10 -0700250 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
251 cacheBlob->fRuns[run].fDrawAsPaths = true;
252 } else {
joshualittfcfb9fc2015-04-21 07:35:10 -0700253 switch (it.positioning()) {
254 case SkTextBlob::kDefault_Positioning:
joshualitt29677982015-12-11 06:08:59 -0800255 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchFontCache(),
joshualitte76b4bb32015-12-28 07:23:58 -0800256 fSurfaceProps, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800257 (const char *)it.glyphs(), textLen,
258 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700259 break;
260 case SkTextBlob::kHorizontal_Positioning:
joshualitt29677982015-12-11 06:08:59 -0800261 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBatchFontCache(),
joshualitte76b4bb32015-12-28 07:23:58 -0800262 fSurfaceProps, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800263 (const char*)it.glyphs(), textLen, it.pos(), 1,
264 SkPoint::Make(x, y + offset.y()));
joshualittfcfb9fc2015-04-21 07:35:10 -0700265 break;
266 case SkTextBlob::kFull_Positioning:
joshualitt29677982015-12-11 06:08:59 -0800267 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBatchFontCache(),
joshualitte76b4bb32015-12-28 07:23:58 -0800268 fSurfaceProps, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800269 (const char*)it.glyphs(), textLen, it.pos(), 2,
270 SkPoint::Make(x, y));
joshualittfcfb9fc2015-04-21 07:35:10 -0700271 break;
272 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700273 }
274
275 if (drawFilter) {
276 // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
277 runPaint = skPaint;
278 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700279 }
280}
281
joshualitt374b2f72015-07-21 08:05:03 -0700282inline GrAtlasTextBlob*
joshualitt5425a9a2015-12-11 11:05:43 -0800283GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, const SkPaint& skPaint,
joshualitt79dfb2b2015-05-11 08:58:08 -0700284 const SkMatrix& viewMatrix,
285 const char text[], size_t byteLength,
joshualitt5425a9a2015-12-11 11:05:43 -0800286 SkScalar x, SkScalar y) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700287 int glyphCount = skPaint.countText(text, byteLength);
joshualitt1d89e8d2015-04-01 12:40:54 -0700288
joshualitta6bf4c52016-01-19 06:59:29 -0800289 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::kGrayTextVASize);
290 blob->fViewMatrix = viewMatrix;
291
joshualitt0d2199b2016-01-20 06:36:09 -0800292 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps,
293 *fContext->caps()->shaderCaps())) {
294 GrTextUtils::DrawDFText(blob, 0, fContext->getBatchFontCache(), fSurfaceProps,
295 skPaint, paint.getColor(), viewMatrix, text,
296 byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700297 } else {
joshualitte76b4bb32015-12-28 07:23:58 -0800298 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), fSurfaceProps, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800299 paint.getColor(), viewMatrix, text, byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700300 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700301 return blob;
joshualitt1d89e8d2015-04-01 12:40:54 -0700302}
303
joshualitt374b2f72015-07-21 08:05:03 -0700304inline GrAtlasTextBlob*
joshualitt5425a9a2015-12-11 11:05:43 -0800305GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& skPaint,
joshualitt79dfb2b2015-05-11 08:58:08 -0700306 const SkMatrix& viewMatrix,
307 const char text[], size_t byteLength,
308 const SkScalar pos[], int scalarsPerPosition,
joshualitt5425a9a2015-12-11 11:05:43 -0800309 const SkPoint& offset) {
joshualitt9bd2daf2015-04-17 09:30:06 -0700310 int glyphCount = skPaint.countText(text, byteLength);
311
joshualitta6bf4c52016-01-19 06:59:29 -0800312 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBlob::kGrayTextVASize);
313 blob->fViewMatrix = viewMatrix;
joshualitt9bd2daf2015-04-17 09:30:06 -0700314
joshualitt0d2199b2016-01-20 06:36:09 -0800315 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, fSurfaceProps,
316 *fContext->caps()->shaderCaps())) {
317 GrTextUtils::DrawDFPosText(blob, 0, fContext->getBatchFontCache(), fSurfaceProps,
318 skPaint, paint.getColor(), viewMatrix, text,
319 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700320 } else {
joshualitte76b4bb32015-12-28 07:23:58 -0800321 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), fSurfaceProps, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800322 paint.getColor(), viewMatrix, text,
323 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700324 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700325 return blob;
326}
327
robertphillips433625e2015-12-04 06:58:16 -0800328void GrAtlasTextContext::onDrawText(GrDrawContext* dc,
herbe59124e2015-11-18 10:54:39 -0800329 const GrClip& clip,
joshualitt79dfb2b2015-05-11 08:58:08 -0700330 const GrPaint& paint, const SkPaint& skPaint,
331 const SkMatrix& viewMatrix,
332 const char text[], size_t byteLength,
333 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
joshualitt374b2f72015-07-21 08:05:03 -0700334 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt5425a9a2015-12-11 11:05:43 -0800335 this->createDrawTextBlob(paint, skPaint, viewMatrix, text, byteLength, x, y));
joshualitt2e2202e2015-12-10 11:22:08 -0800336 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPaint, paint,
337 clip, regionClipBounds);
joshualitt79dfb2b2015-05-11 08:58:08 -0700338}
339
robertphillips433625e2015-12-04 06:58:16 -0800340void GrAtlasTextContext::onDrawPosText(GrDrawContext* dc,
robertphillipsccb1b572015-05-27 11:02:55 -0700341 const GrClip& clip,
joshualitt79dfb2b2015-05-11 08:58:08 -0700342 const GrPaint& paint, const SkPaint& skPaint,
343 const SkMatrix& viewMatrix,
344 const char text[], size_t byteLength,
345 const SkScalar pos[], int scalarsPerPosition,
346 const SkPoint& offset, const SkIRect& regionClipBounds) {
joshualitt374b2f72015-07-21 08:05:03 -0700347 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt5425a9a2015-12-11 11:05:43 -0800348 this->createDrawPosTextBlob(paint, skPaint, viewMatrix,
robertphillips2334fb62015-06-17 05:43:33 -0700349 text, byteLength,
350 pos, scalarsPerPosition,
joshualitt5425a9a2015-12-11 11:05:43 -0800351 offset));
joshualitt79dfb2b2015-05-11 08:58:08 -0700352
joshualitt2e2202e2015-12-10 11:22:08 -0800353 blob->flushThrowaway(fContext, dc, fSurfaceProps, fDistanceAdjustTable, skPaint, paint, clip,
354 regionClipBounds);
joshualitt9bd2daf2015-04-17 09:30:06 -0700355}
356
joshualitt79dfb2b2015-05-11 08:58:08 -0700357///////////////////////////////////////////////////////////////////////////////////////////////////
358
359#ifdef GR_TEST_UTILS
360
bsalomonabd30f52015-08-13 13:34:48 -0700361DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700362 static uint32_t gContextID = SK_InvalidGenID;
halcanary96fcdcc2015-08-27 07:41:13 -0700363 static GrAtlasTextContext* gTextContext = nullptr;
robertphillipsfcf78292015-06-19 11:49:52 -0700364 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
joshualitt79dfb2b2015-05-11 08:58:08 -0700365
366 if (context->uniqueID() != gContextID) {
367 gContextID = context->uniqueID();
halcanary385fe4d2015-08-26 13:07:48 -0700368 delete gTextContext;
robertphillips2334fb62015-06-17 05:43:33 -0700369
joshualitt79dfb2b2015-05-11 08:58:08 -0700370 // We don't yet test the fall back to paths in the GrTextContext base class. This is mostly
371 // because we don't really want to have a gpu device here.
372 // We enable distance fields by twiddling a knob on the paint
robertphillipsf6703fa2015-09-01 05:36:47 -0700373 gTextContext = GrAtlasTextContext::Create(context, gSurfaceProps);
joshualitt79dfb2b2015-05-11 08:58:08 -0700374 }
375
joshualitt79dfb2b2015-05-11 08:58:08 -0700376 // Setup dummy SkPaint / GrPaint
377 GrColor color = GrRandomColor(random);
joshualitt6c891102015-05-13 08:51:49 -0700378 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
joshualitt79dfb2b2015-05-11 08:58:08 -0700379 SkPaint skPaint;
joshualitt79dfb2b2015-05-11 08:58:08 -0700380 skPaint.setColor(color);
381 skPaint.setLCDRenderText(random->nextBool());
382 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
383 skPaint.setSubpixelText(random->nextBool());
384
385 GrPaint grPaint;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700386 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700387 SkFAIL("couldn't convert paint\n");
388 }
389
390 const char* text = "The quick brown fox jumps over the lazy dog.";
391 int textLen = (int)strlen(text);
392
393 // Setup clip
394 GrClip clip;
joshualitt79dfb2b2015-05-11 08:58:08 -0700395
396 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only
397 // intend to test the batch with this unit test, that is okay.
joshualitt374b2f72015-07-21 08:05:03 -0700398 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt5425a9a2015-12-11 11:05:43 -0800399 gTextContext->createDrawTextBlob(grPaint, skPaint, viewMatrix, text,
400 static_cast<size_t>(textLen), 0, 0));
joshualitt79dfb2b2015-05-11 08:58:08 -0700401
402 SkScalar transX = static_cast<SkScalar>(random->nextU());
403 SkScalar transY = static_cast<SkScalar>(random->nextU());
joshualitt374b2f72015-07-21 08:05:03 -0700404 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0];
joshualitt2e2202e2015-12-10 11:22:08 -0800405 return blob->createBatch(info, textLen, 0, 0, color, transX, transY, skPaint,
406 gSurfaceProps, gTextContext->dfAdjustTable(),
407 context->getBatchFontCache());
joshualitt79dfb2b2015-05-11 08:58:08 -0700408}
409
410#endif