blob: 0f36fe355af3d9c48ad8c5ee48e83167dc43a789 [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"
joshualittb7133be2015-04-08 09:08:31 -070011#include "GrTextBlobCache.h"
joshualitt29677982015-12-11 06:08:59 -080012#include "GrTextUtils.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070013
joshualitt1d89e8d2015-04-01 12:40:54 -070014#include "SkDraw.h"
15#include "SkDrawFilter.h"
bsalomonf1b7a1d2015-09-28 06:26:28 -070016#include "SkGrPriv.h"
joshualitt1d89e8d2015-04-01 12:40:54 -070017
joshualitt27004b72016-02-11 12:00:33 -080018GrAtlasTextContext::GrAtlasTextContext()
19 : fDistanceAdjustTable(new GrDistanceFieldAdjustTable) {
joshualitt9bd2daf2015-04-17 09:30:06 -070020}
21
joshualitt1d89e8d2015-04-01 12:40:54 -070022
joshualitt27004b72016-02-11 12:00:33 -080023GrAtlasTextContext* GrAtlasTextContext::Create() {
24 return new GrAtlasTextContext();
joshualitt1d89e8d2015-04-01 12:40:54 -070025}
26
joshualitt2c89bc12016-02-11 05:42:30 -080027bool GrAtlasTextContext::canDraw(const SkPaint& skPaint,
28 const SkMatrix& viewMatrix,
joshualitt27004b72016-02-11 12:00:33 -080029 const SkSurfaceProps& props,
30 const GrShaderCaps& shaderCaps) {
31 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps) ||
joshualitt9bd2daf2015-04-17 09:30:06 -070032 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
joshualitt1d89e8d2015-04-01 12:40:54 -070033}
34
joshualitt9e36c1a2015-04-14 12:17:27 -070035GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) {
36 GrColor canonicalColor = paint.computeLuminanceColor();
37 if (lcd) {
38 // This is the correct computation, but there are tons of cases where LCD can be overridden.
39 // For now we just regenerate if any run in a textblob has LCD.
40 // TODO figure out where all of these overrides are and see if we can incorporate that logic
41 // at a higher level *OR* use sRGB
42 SkASSERT(false);
43 //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
44 } else {
45 // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
46 // gamma corrected masks anyways, nor color
47 U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
48 SkColorGetG(canonicalColor),
49 SkColorGetB(canonicalColor));
50 // reduce to our finite number of bits
51 canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
52 }
53 return canonicalColor;
54}
55
56// TODO if this function ever shows up in profiling, then we can compute this value when the
57// textblob is being built and cache it. However, for the time being textblobs mostly only have 1
58// run so this is not a big deal to compute here.
59bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) {
halcanary33779752015-10-27 14:01:05 -070060 SkTextBlobRunIterator it(blob);
joshualitt9e36c1a2015-04-14 12:17:27 -070061 for (; !it.done(); it.next()) {
62 if (it.isLCD()) {
63 return true;
64 }
65 }
66 return false;
67}
68
joshualitt27004b72016-02-11 12:00:33 -080069void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
robertphillipsccb1b572015-05-27 11:02:55 -070070 const GrClip& clip, const SkPaint& skPaint,
joshualitt2c89bc12016-02-11 05:42:30 -080071 const SkMatrix& viewMatrix,
72 const SkSurfaceProps& props, const SkTextBlob* blob,
robertphillipsccb1b572015-05-27 11:02:55 -070073 SkScalar x, SkScalar y,
joshualittdbd35932015-04-02 09:19:04 -070074 SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
joshualitt9b8e79e2015-04-24 09:57:12 -070075 // If we have been abandoned, then don't draw
joshualitt27004b72016-02-11 12:00:33 -080076 if (context->abandoned()) {
robertphillipsea461502015-05-26 11:38:03 -070077 return;
78 }
79
joshualitt374b2f72015-07-21 08:05:03 -070080 SkAutoTUnref<GrAtlasTextBlob> cacheBlob;
joshualitt53b5f442015-04-13 06:33:59 -070081 SkMaskFilter::BlurRec blurRec;
joshualitt374b2f72015-07-21 08:05:03 -070082 GrAtlasTextBlob::Key key;
joshualitt53b5f442015-04-13 06:33:59 -070083 // It might be worth caching these things, but its not clear at this time
84 // TODO for animated mask filters, this will fill up our cache. We need a safeguard here
85 const SkMaskFilter* mf = skPaint.getMaskFilter();
joshualitt2a0e9f32015-04-13 06:12:21 -070086 bool canCache = !(skPaint.getPathEffect() ||
joshualitt53b5f442015-04-13 06:33:59 -070087 (mf && !mf->asABlur(&blurRec)) ||
joshualitt2a0e9f32015-04-13 06:12:21 -070088 drawFilter);
89
joshualitt27004b72016-02-11 12:00:33 -080090 GrTextBlobCache* cache = context->getTextBlobCache();
joshualitt2a0e9f32015-04-13 06:12:21 -070091 if (canCache) {
joshualitt9e36c1a2015-04-14 12:17:27 -070092 bool hasLCD = HasLCD(blob);
joshualitte4cee1f2015-05-11 13:04:28 -070093
94 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
joshualitt2c89bc12016-02-11 05:42:30 -080095 SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() :
joshualitte4cee1f2015-05-11 13:04:28 -070096 kUnknown_SkPixelGeometry;
97
joshualitt9e36c1a2015-04-14 12:17:27 -070098 // TODO we want to figure out a way to be able to use the canonical color on LCD text,
99 // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
100 // ensure we always match the same key
101 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
102 ComputeCanonicalColor(skPaint, hasLCD);
103
joshualitte4cee1f2015-05-11 13:04:28 -0700104 key.fPixelGeometry = pixelGeometry;
joshualitt53b5f442015-04-13 06:33:59 -0700105 key.fUniqueID = blob->uniqueID();
106 key.fStyle = skPaint.getStyle();
107 key.fHasBlur = SkToBool(mf);
joshualitt9e36c1a2015-04-14 12:17:27 -0700108 key.fCanonicalColor = canonicalColor;
joshualitt27004b72016-02-11 12:00:33 -0800109 cacheBlob.reset(SkSafeRef(cache->find(key)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700110 }
111
joshualitt2a0e9f32015-04-13 06:12:21 -0700112 SkScalar transX = 0.f;
113 SkScalar transY = 0.f;
114
joshualitt9e36c1a2015-04-14 12:17:27 -0700115 // Though for the time being runs in the textblob can override the paint, they only touch font
116 // info.
117 GrPaint grPaint;
joshualitt27004b72016-02-11 12:00:33 -0800118 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700119 return;
120 }
joshualitt9e36c1a2015-04-14 12:17:27 -0700121
joshualittb7133be2015-04-08 09:08:31 -0700122 if (cacheBlob) {
joshualittfd5f6c12015-12-10 07:44:50 -0800123 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColor(), blurRec,
124 viewMatrix, x, y)) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700125 // We have to remake the blob because changes may invalidate our masks.
126 // TODO we could probably get away reuse most of the time if the pointer is unique,
127 // but we'd have to clear the subrun information
joshualitt27004b72016-02-11 12:00:33 -0800128 cache->remove(cacheBlob);
129 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
130 RegenerateTextBlob(cacheBlob, context->getBatchFontCache(),
131 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
132 viewMatrix, props,
133 blob, x, y, drawFilter);
joshualittb7133be2015-04-08 09:08:31 -0700134 } else {
joshualitt27004b72016-02-11 12:00:33 -0800135 cache->makeMRU(cacheBlob);
joshualitt2f2ee832016-02-10 08:52:24 -0800136
137 if (CACHE_SANITY_CHECK) {
joshualitt259fbf12015-07-21 11:39:34 -0700138 int glyphCount = 0;
139 int runCount = 0;
140 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
joshualitt27004b72016-02-11 12:00:33 -0800141 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(cache->createBlob(glyphCount, runCount));
joshualitt92303772016-02-10 11:55:52 -0800142 sanityBlob->setupKey(key, blurRec, skPaint);
joshualitt27004b72016-02-11 12:00:33 -0800143 RegenerateTextBlob(sanityBlob, context->getBatchFontCache(),
144 *context->caps()->shaderCaps(), skPaint,
145 grPaint.getColor(), viewMatrix, props,
146 blob, x, y, drawFilter);
joshualitt259fbf12015-07-21 11:39:34 -0700147 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
148 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700149 }
150 } else {
joshualitt2a0e9f32015-04-13 06:12:21 -0700151 if (canCache) {
joshualitt27004b72016-02-11 12:00:33 -0800152 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700153 } else {
joshualitt27004b72016-02-11 12:00:33 -0800154 cacheBlob.reset(cache->createBlob(blob));
joshualitt2a0e9f32015-04-13 06:12:21 -0700155 }
joshualitt27004b72016-02-11 12:00:33 -0800156 RegenerateTextBlob(cacheBlob, context->getBatchFontCache(),
157 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
158 viewMatrix, props,
159 blob, x, y, drawFilter);
joshualitt1d89e8d2015-04-01 12:40:54 -0700160 }
161
joshualitt27004b72016-02-11 12:00:33 -0800162 cacheBlob->flushCached(context, dc, blob, props, fDistanceAdjustTable, skPaint,
joshualitt2e2202e2015-12-10 11:22:08 -0800163 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY);
joshualitt1d89e8d2015-04-01 12:40:54 -0700164}
165
joshualitt27004b72016-02-11 12:00:33 -0800166void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob,
167 GrBatchFontCache* fontCache,
168 const GrShaderCaps& shaderCaps,
joshualitt9e36c1a2015-04-14 12:17:27 -0700169 const SkPaint& skPaint, GrColor color,
170 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800171 const SkSurfaceProps& props,
joshualittdbd35932015-04-02 09:19:04 -0700172 const SkTextBlob* blob, SkScalar x, SkScalar y,
joshualitta6bf4c52016-01-19 06:59:29 -0800173 SkDrawFilter* drawFilter) {
joshualitt323c2eb2016-01-20 06:48:47 -0800174 cacheBlob->initReusableBlob(color, viewMatrix, x, y);
joshualitt1d89e8d2015-04-01 12:40:54 -0700175
176 // Regenerate textblob
177 SkPaint runPaint = skPaint;
halcanary33779752015-10-27 14:01:05 -0700178 SkTextBlobRunIterator it(blob);
joshualitt1d89e8d2015-04-01 12:40:54 -0700179 for (int run = 0; !it.done(); it.next(), run++) {
180 int glyphCount = it.glyphCount();
181 size_t textLen = glyphCount * sizeof(uint16_t);
182 const SkPoint& offset = it.offset();
183 // applyFontToPaint() always overwrites the exact same attributes,
184 // so it is safe to not re-seed the paint for this reason.
185 it.applyFontToPaint(&runPaint);
186
187 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
188 // A false return from filter() means we should abort the current draw.
189 runPaint = skPaint;
190 continue;
191 }
192
joshualitt8e84a1e2016-02-16 11:09:25 -0800193 runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));
joshualitt1d89e8d2015-04-01 12:40:54 -0700194
joshualitt18b072d2015-12-07 12:26:12 -0800195 cacheBlob->push_back_run(run);
joshualitt1d89e8d2015-04-01 12:40:54 -0700196
joshualitt27004b72016-02-11 12:00:33 -0800197 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) {
joshualittfcfb9fc2015-04-21 07:35:10 -0700198 switch (it.positioning()) {
199 case SkTextBlob::kDefault_Positioning: {
joshualitt27004b72016-02-11 12:00:33 -0800200 GrTextUtils::DrawDFText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800201 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800202 (const char *)it.glyphs(), textLen,
203 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700204 break;
205 }
206 case SkTextBlob::kHorizontal_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800207 SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
joshualitt27004b72016-02-11 12:00:33 -0800208 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800209 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800210 (const char*)it.glyphs(), textLen, it.pos(),
211 1, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700212 break;
213 }
214 case SkTextBlob::kFull_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800215 SkPoint dfOffset = SkPoint::Make(x, y);
joshualitt27004b72016-02-11 12:00:33 -0800216 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800217 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800218 (const char*)it.glyphs(), textLen, it.pos(),
219 2, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700220 break;
221 }
222 }
joshualittfcfb9fc2015-04-21 07:35:10 -0700223 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
joshualitt323c2eb2016-01-20 06:48:47 -0800224 cacheBlob->setRunDrawAsPaths(run);
joshualittfcfb9fc2015-04-21 07:35:10 -0700225 } else {
joshualittfcfb9fc2015-04-21 07:35:10 -0700226 switch (it.positioning()) {
227 case SkTextBlob::kDefault_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800228 GrTextUtils::DrawBmpText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800229 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800230 (const char *)it.glyphs(), textLen,
231 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700232 break;
233 case SkTextBlob::kHorizontal_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800234 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800235 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800236 (const char*)it.glyphs(), textLen, it.pos(), 1,
237 SkPoint::Make(x, y + offset.y()));
joshualittfcfb9fc2015-04-21 07:35:10 -0700238 break;
239 case SkTextBlob::kFull_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800240 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800241 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800242 (const char*)it.glyphs(), textLen, it.pos(), 2,
243 SkPoint::Make(x, y));
joshualittfcfb9fc2015-04-21 07:35:10 -0700244 break;
245 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700246 }
247
248 if (drawFilter) {
249 // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
250 runPaint = skPaint;
251 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700252 }
253}
254
joshualitt374b2f72015-07-21 08:05:03 -0700255inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800256GrAtlasTextContext::CreateDrawTextBlob(GrTextBlobCache* blobCache,
257 GrBatchFontCache* fontCache,
258 const GrShaderCaps& shaderCaps,
259 const GrPaint& paint,
joshualitt2c89bc12016-02-11 05:42:30 -0800260 const SkPaint& skPaint,
joshualitt79dfb2b2015-05-11 08:58:08 -0700261 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800262 const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700263 const char text[], size_t byteLength,
joshualitt5425a9a2015-12-11 11:05:43 -0800264 SkScalar x, SkScalar y) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700265 int glyphCount = skPaint.countText(text, byteLength);
joshualitt1d89e8d2015-04-01 12:40:54 -0700266
joshualitt27004b72016-02-11 12:00:33 -0800267 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800268 blob->initThrowawayBlob(viewMatrix, x, y);
joshualitta6bf4c52016-01-19 06:59:29 -0800269
joshualitt27004b72016-02-11 12:00:33 -0800270 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
271 GrTextUtils::DrawDFText(blob, 0, fontCache, props,
joshualitt0d2199b2016-01-20 06:36:09 -0800272 skPaint, paint.getColor(), viewMatrix, text,
273 byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700274 } else {
joshualitt27004b72016-02-11 12:00:33 -0800275 GrTextUtils::DrawBmpText(blob, 0, fontCache, props, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800276 paint.getColor(), viewMatrix, text, byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700277 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700278 return blob;
joshualitt1d89e8d2015-04-01 12:40:54 -0700279}
280
joshualitt374b2f72015-07-21 08:05:03 -0700281inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800282GrAtlasTextContext::CreateDrawPosTextBlob(GrTextBlobCache* blobCache, GrBatchFontCache* fontCache,
283 const GrShaderCaps& shaderCaps, const GrPaint& paint,
284 const SkPaint& skPaint,
joshualitt2c89bc12016-02-11 05:42:30 -0800285 const SkMatrix& viewMatrix, const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700286 const char text[], size_t byteLength,
287 const SkScalar pos[], int scalarsPerPosition,
joshualitt5425a9a2015-12-11 11:05:43 -0800288 const SkPoint& offset) {
joshualitt9bd2daf2015-04-17 09:30:06 -0700289 int glyphCount = skPaint.countText(text, byteLength);
290
joshualitt27004b72016-02-11 12:00:33 -0800291 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800292 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y());
joshualitt9bd2daf2015-04-17 09:30:06 -0700293
joshualitt27004b72016-02-11 12:00:33 -0800294 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
295 GrTextUtils::DrawDFPosText(blob, 0, fontCache, props,
joshualitt0d2199b2016-01-20 06:36:09 -0800296 skPaint, paint.getColor(), viewMatrix, text,
297 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700298 } else {
joshualitt27004b72016-02-11 12:00:33 -0800299 GrTextUtils::DrawBmpPosText(blob, 0, fontCache, props, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800300 paint.getColor(), viewMatrix, text,
301 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700302 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700303 return blob;
304}
305
joshualitt27004b72016-02-11 12:00:33 -0800306void GrAtlasTextContext::drawText(GrContext* context,
307 GrDrawContext* dc,
joshualitte55750e2016-02-10 12:52:21 -0800308 const GrClip& clip,
309 const GrPaint& paint, const SkPaint& skPaint,
310 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800311 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800312 const char text[], size_t byteLength,
313 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800314 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800315 return;
joshualitt27004b72016-02-11 12:00:33 -0800316 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
joshualitte55750e2016-02-10 12:52:21 -0800317 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800318 CreateDrawTextBlob(context->getTextBlobCache(), context->getBatchFontCache(),
319 *context->caps()->shaderCaps(),
320 paint, skPaint,
321 viewMatrix, props,
322 text, byteLength, x, y));
323 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
joshualitte55750e2016-02-10 12:52:21 -0800324 clip, regionClipBounds);
325 return;
326 }
327
328 // fall back to drawing as a path
joshualitt27004b72016-02-11 12:00:33 -0800329 GrTextUtils::DrawTextAsPath(context, dc, clip, skPaint, viewMatrix, text, byteLength, x, y,
joshualitte55750e2016-02-10 12:52:21 -0800330 regionClipBounds);
joshualitt79dfb2b2015-05-11 08:58:08 -0700331}
332
joshualitt27004b72016-02-11 12:00:33 -0800333void GrAtlasTextContext::drawPosText(GrContext* context,
334 GrDrawContext* dc,
joshualitte55750e2016-02-10 12:52:21 -0800335 const GrClip& clip,
336 const GrPaint& paint, const SkPaint& skPaint,
337 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800338 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800339 const char text[], size_t byteLength,
340 const SkScalar pos[], int scalarsPerPosition,
341 const SkPoint& offset, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800342 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800343 return;
joshualitt27004b72016-02-11 12:00:33 -0800344 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
joshualitte55750e2016-02-10 12:52:21 -0800345 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800346 CreateDrawPosTextBlob(context->getTextBlobCache(),
347 context->getBatchFontCache(),
348 *context->caps()->shaderCaps(),
349 paint, skPaint, viewMatrix, props,
350 text, byteLength,
351 pos, scalarsPerPosition,
352 offset));
353 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
joshualitte55750e2016-02-10 12:52:21 -0800354 clip, regionClipBounds);
355 return;
356 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700357
joshualitte55750e2016-02-10 12:52:21 -0800358 // fall back to drawing as a path
joshualitt27004b72016-02-11 12:00:33 -0800359 GrTextUtils::DrawPosTextAsPath(context, dc, props, clip, skPaint, viewMatrix, text,
joshualitte55750e2016-02-10 12:52:21 -0800360 byteLength, pos, scalarsPerPosition, offset, regionClipBounds);
joshualitt9bd2daf2015-04-17 09:30:06 -0700361}
362
joshualitt79dfb2b2015-05-11 08:58:08 -0700363///////////////////////////////////////////////////////////////////////////////////////////////////
364
365#ifdef GR_TEST_UTILS
366
bsalomonabd30f52015-08-13 13:34:48 -0700367DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700368 static uint32_t gContextID = SK_InvalidGenID;
halcanary96fcdcc2015-08-27 07:41:13 -0700369 static GrAtlasTextContext* gTextContext = nullptr;
robertphillipsfcf78292015-06-19 11:49:52 -0700370 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
joshualitt79dfb2b2015-05-11 08:58:08 -0700371
372 if (context->uniqueID() != gContextID) {
373 gContextID = context->uniqueID();
halcanary385fe4d2015-08-26 13:07:48 -0700374 delete gTextContext;
robertphillips2334fb62015-06-17 05:43:33 -0700375
joshualitt27004b72016-02-11 12:00:33 -0800376 gTextContext = GrAtlasTextContext::Create();
joshualitt79dfb2b2015-05-11 08:58:08 -0700377 }
378
joshualitt79dfb2b2015-05-11 08:58:08 -0700379 // Setup dummy SkPaint / GrPaint
380 GrColor color = GrRandomColor(random);
joshualitt6c891102015-05-13 08:51:49 -0700381 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
joshualitt79dfb2b2015-05-11 08:58:08 -0700382 SkPaint skPaint;
joshualitt79dfb2b2015-05-11 08:58:08 -0700383 skPaint.setColor(color);
384 skPaint.setLCDRenderText(random->nextBool());
385 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
386 skPaint.setSubpixelText(random->nextBool());
387
388 GrPaint grPaint;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700389 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700390 SkFAIL("couldn't convert paint\n");
391 }
392
393 const char* text = "The quick brown fox jumps over the lazy dog.";
394 int textLen = (int)strlen(text);
395
396 // Setup clip
397 GrClip clip;
joshualitt79dfb2b2015-05-11 08:58:08 -0700398
399 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only
400 // intend to test the batch with this unit test, that is okay.
joshualitt374b2f72015-07-21 08:05:03 -0700401 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800402 GrAtlasTextContext::CreateDrawTextBlob(context->getTextBlobCache(),
403 context->getBatchFontCache(),
404 *context->caps()->shaderCaps(), grPaint, skPaint,
405 viewMatrix,
406 gSurfaceProps, text,
407 static_cast<size_t>(textLen), 0, 0));
joshualitt79dfb2b2015-05-11 08:58:08 -0700408
joshualitt7481e752016-01-22 06:08:48 -0800409 // We'd like to be able to test this with random translations, but currently the vertex
410 // bounds and vertices will get out of sync
411 SkScalar transX = 0.f;//SkIntToScalar(random->nextU());
412 SkScalar transY = 0.f;//SkIntToScalar(random->nextU());
joshualitt323c2eb2016-01-20 06:48:47 -0800413 return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint,
414 gSurfaceProps, gTextContext->dfAdjustTable(),
415 context->getBatchFontCache());
joshualitt79dfb2b2015-05-11 08:58:08 -0700416}
417
418#endif