blob: ec9e40cbae22fc3303ba02f9b458d3a86497b44e [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
robertphillips73c4e642016-03-02 11:36:59 -08009#include "GrContext.h"
robertphillipsea461502015-05-26 11:38:03 -070010#include "GrDrawContext.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
joshualitt9e36c1a2015-04-14 12:17:27 -0700112 // Though for the time being runs in the textblob can override the paint, they only touch font
113 // info.
114 GrPaint grPaint;
joshualitt27004b72016-02-11 12:00:33 -0800115 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700116 return;
117 }
joshualitt9e36c1a2015-04-14 12:17:27 -0700118
joshualittb7133be2015-04-08 09:08:31 -0700119 if (cacheBlob) {
joshualitt8e0ef292016-02-19 14:13:03 -0800120 if (cacheBlob->mustRegenerate(skPaint, grPaint.getColor(), blurRec, viewMatrix, x, y)) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700121 // We have to remake the blob because changes may invalidate our masks.
122 // TODO we could probably get away reuse most of the time if the pointer is unique,
123 // but we'd have to clear the subrun information
joshualitt27004b72016-02-11 12:00:33 -0800124 cache->remove(cacheBlob);
125 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
126 RegenerateTextBlob(cacheBlob, context->getBatchFontCache(),
127 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
128 viewMatrix, props,
129 blob, x, y, drawFilter);
joshualittb7133be2015-04-08 09:08:31 -0700130 } else {
joshualitt27004b72016-02-11 12:00:33 -0800131 cache->makeMRU(cacheBlob);
joshualitt2f2ee832016-02-10 08:52:24 -0800132
133 if (CACHE_SANITY_CHECK) {
joshualitt259fbf12015-07-21 11:39:34 -0700134 int glyphCount = 0;
135 int runCount = 0;
136 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
joshualitt27004b72016-02-11 12:00:33 -0800137 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(cache->createBlob(glyphCount, runCount));
joshualitt92303772016-02-10 11:55:52 -0800138 sanityBlob->setupKey(key, blurRec, skPaint);
joshualitt27004b72016-02-11 12:00:33 -0800139 RegenerateTextBlob(sanityBlob, context->getBatchFontCache(),
140 *context->caps()->shaderCaps(), skPaint,
141 grPaint.getColor(), viewMatrix, props,
142 blob, x, y, drawFilter);
joshualitt259fbf12015-07-21 11:39:34 -0700143 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
144 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700145 }
146 } else {
joshualitt2a0e9f32015-04-13 06:12:21 -0700147 if (canCache) {
joshualitt27004b72016-02-11 12:00:33 -0800148 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700149 } else {
joshualitt27004b72016-02-11 12:00:33 -0800150 cacheBlob.reset(cache->createBlob(blob));
joshualitt2a0e9f32015-04-13 06:12:21 -0700151 }
joshualitt27004b72016-02-11 12:00:33 -0800152 RegenerateTextBlob(cacheBlob, context->getBatchFontCache(),
153 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
154 viewMatrix, props,
155 blob, x, y, drawFilter);
joshualitt1d89e8d2015-04-01 12:40:54 -0700156 }
157
joshualitt27004b72016-02-11 12:00:33 -0800158 cacheBlob->flushCached(context, dc, blob, props, fDistanceAdjustTable, skPaint,
joshualitt8e0ef292016-02-19 14:13:03 -0800159 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y);
joshualitt1d89e8d2015-04-01 12:40:54 -0700160}
161
joshualitt27004b72016-02-11 12:00:33 -0800162void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob,
163 GrBatchFontCache* fontCache,
164 const GrShaderCaps& shaderCaps,
joshualitt9e36c1a2015-04-14 12:17:27 -0700165 const SkPaint& skPaint, GrColor color,
166 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800167 const SkSurfaceProps& props,
joshualittdbd35932015-04-02 09:19:04 -0700168 const SkTextBlob* blob, SkScalar x, SkScalar y,
joshualitta6bf4c52016-01-19 06:59:29 -0800169 SkDrawFilter* drawFilter) {
joshualitt323c2eb2016-01-20 06:48:47 -0800170 cacheBlob->initReusableBlob(color, viewMatrix, x, y);
joshualitt1d89e8d2015-04-01 12:40:54 -0700171
172 // Regenerate textblob
173 SkPaint runPaint = skPaint;
halcanary33779752015-10-27 14:01:05 -0700174 SkTextBlobRunIterator it(blob);
joshualitt1d89e8d2015-04-01 12:40:54 -0700175 for (int run = 0; !it.done(); it.next(), run++) {
176 int glyphCount = it.glyphCount();
177 size_t textLen = glyphCount * sizeof(uint16_t);
178 const SkPoint& offset = it.offset();
179 // applyFontToPaint() always overwrites the exact same attributes,
180 // so it is safe to not re-seed the paint for this reason.
181 it.applyFontToPaint(&runPaint);
182
183 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
184 // A false return from filter() means we should abort the current draw.
185 runPaint = skPaint;
186 continue;
187 }
188
joshualitt8e84a1e2016-02-16 11:09:25 -0800189 runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));
joshualitt1d89e8d2015-04-01 12:40:54 -0700190
joshualitt18b072d2015-12-07 12:26:12 -0800191 cacheBlob->push_back_run(run);
joshualitt1d89e8d2015-04-01 12:40:54 -0700192
joshualitt27004b72016-02-11 12:00:33 -0800193 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) {
joshualittfcfb9fc2015-04-21 07:35:10 -0700194 switch (it.positioning()) {
195 case SkTextBlob::kDefault_Positioning: {
joshualitt27004b72016-02-11 12:00:33 -0800196 GrTextUtils::DrawDFText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800197 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800198 (const char *)it.glyphs(), textLen,
199 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700200 break;
201 }
202 case SkTextBlob::kHorizontal_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800203 SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
joshualitt27004b72016-02-11 12:00:33 -0800204 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800205 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800206 (const char*)it.glyphs(), textLen, it.pos(),
207 1, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700208 break;
209 }
210 case SkTextBlob::kFull_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800211 SkPoint dfOffset = SkPoint::Make(x, y);
joshualitt27004b72016-02-11 12:00:33 -0800212 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800213 props, runPaint, color, viewMatrix,
joshualitt0d2199b2016-01-20 06:36:09 -0800214 (const char*)it.glyphs(), textLen, it.pos(),
215 2, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700216 break;
217 }
218 }
joshualittfcfb9fc2015-04-21 07:35:10 -0700219 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
joshualitt323c2eb2016-01-20 06:48:47 -0800220 cacheBlob->setRunDrawAsPaths(run);
joshualittfcfb9fc2015-04-21 07:35:10 -0700221 } else {
joshualittfcfb9fc2015-04-21 07:35:10 -0700222 switch (it.positioning()) {
223 case SkTextBlob::kDefault_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800224 GrTextUtils::DrawBmpText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800225 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800226 (const char *)it.glyphs(), textLen,
227 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700228 break;
229 case SkTextBlob::kHorizontal_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800230 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800231 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800232 (const char*)it.glyphs(), textLen, it.pos(), 1,
233 SkPoint::Make(x, y + offset.y()));
joshualittfcfb9fc2015-04-21 07:35:10 -0700234 break;
235 case SkTextBlob::kFull_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800236 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
joshualitt2c89bc12016-02-11 05:42:30 -0800237 props, runPaint, color, viewMatrix,
joshualitt29677982015-12-11 06:08:59 -0800238 (const char*)it.glyphs(), textLen, it.pos(), 2,
239 SkPoint::Make(x, y));
joshualittfcfb9fc2015-04-21 07:35:10 -0700240 break;
241 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700242 }
243
244 if (drawFilter) {
245 // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
246 runPaint = skPaint;
247 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700248 }
249}
250
joshualitt374b2f72015-07-21 08:05:03 -0700251inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800252GrAtlasTextContext::CreateDrawTextBlob(GrTextBlobCache* blobCache,
253 GrBatchFontCache* fontCache,
254 const GrShaderCaps& shaderCaps,
255 const GrPaint& paint,
joshualitt2c89bc12016-02-11 05:42:30 -0800256 const SkPaint& skPaint,
joshualitt79dfb2b2015-05-11 08:58:08 -0700257 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800258 const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700259 const char text[], size_t byteLength,
joshualitt5425a9a2015-12-11 11:05:43 -0800260 SkScalar x, SkScalar y) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700261 int glyphCount = skPaint.countText(text, byteLength);
joshualitt1d89e8d2015-04-01 12:40:54 -0700262
joshualitt27004b72016-02-11 12:00:33 -0800263 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800264 blob->initThrowawayBlob(viewMatrix, x, y);
joshualitta6bf4c52016-01-19 06:59:29 -0800265
joshualitt27004b72016-02-11 12:00:33 -0800266 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
267 GrTextUtils::DrawDFText(blob, 0, fontCache, props,
joshualitt0d2199b2016-01-20 06:36:09 -0800268 skPaint, paint.getColor(), viewMatrix, text,
269 byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700270 } else {
joshualitt27004b72016-02-11 12:00:33 -0800271 GrTextUtils::DrawBmpText(blob, 0, fontCache, props, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800272 paint.getColor(), viewMatrix, text, byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700273 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700274 return blob;
joshualitt1d89e8d2015-04-01 12:40:54 -0700275}
276
joshualitt374b2f72015-07-21 08:05:03 -0700277inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800278GrAtlasTextContext::CreateDrawPosTextBlob(GrTextBlobCache* blobCache, GrBatchFontCache* fontCache,
279 const GrShaderCaps& shaderCaps, const GrPaint& paint,
280 const SkPaint& skPaint,
joshualitt2c89bc12016-02-11 05:42:30 -0800281 const SkMatrix& viewMatrix, const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700282 const char text[], size_t byteLength,
283 const SkScalar pos[], int scalarsPerPosition,
joshualitt5425a9a2015-12-11 11:05:43 -0800284 const SkPoint& offset) {
joshualitt9bd2daf2015-04-17 09:30:06 -0700285 int glyphCount = skPaint.countText(text, byteLength);
286
joshualitt27004b72016-02-11 12:00:33 -0800287 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800288 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y());
joshualitt9bd2daf2015-04-17 09:30:06 -0700289
joshualitt27004b72016-02-11 12:00:33 -0800290 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
291 GrTextUtils::DrawDFPosText(blob, 0, fontCache, props,
joshualitt0d2199b2016-01-20 06:36:09 -0800292 skPaint, paint.getColor(), viewMatrix, text,
293 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700294 } else {
joshualitt27004b72016-02-11 12:00:33 -0800295 GrTextUtils::DrawBmpPosText(blob, 0, fontCache, props, skPaint,
joshualitt29677982015-12-11 06:08:59 -0800296 paint.getColor(), viewMatrix, text,
297 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700298 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700299 return blob;
300}
301
joshualitt27004b72016-02-11 12:00:33 -0800302void GrAtlasTextContext::drawText(GrContext* context,
303 GrDrawContext* dc,
joshualitte55750e2016-02-10 12:52:21 -0800304 const GrClip& clip,
305 const GrPaint& paint, const SkPaint& skPaint,
306 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800307 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800308 const char text[], size_t byteLength,
309 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800310 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800311 return;
joshualitt27004b72016-02-11 12:00:33 -0800312 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
joshualitte55750e2016-02-10 12:52:21 -0800313 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800314 CreateDrawTextBlob(context->getTextBlobCache(), context->getBatchFontCache(),
315 *context->caps()->shaderCaps(),
316 paint, skPaint,
317 viewMatrix, props,
318 text, byteLength, x, y));
319 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
joshualitt8e0ef292016-02-19 14:13:03 -0800320 clip, viewMatrix, regionClipBounds, x, y);
joshualitte55750e2016-02-10 12:52:21 -0800321 return;
322 }
323
324 // fall back to drawing as a path
joshualitt27004b72016-02-11 12:00:33 -0800325 GrTextUtils::DrawTextAsPath(context, dc, clip, skPaint, viewMatrix, text, byteLength, x, y,
joshualitte55750e2016-02-10 12:52:21 -0800326 regionClipBounds);
joshualitt79dfb2b2015-05-11 08:58:08 -0700327}
328
joshualitt27004b72016-02-11 12:00:33 -0800329void GrAtlasTextContext::drawPosText(GrContext* context,
330 GrDrawContext* dc,
joshualitte55750e2016-02-10 12:52:21 -0800331 const GrClip& clip,
332 const GrPaint& paint, const SkPaint& skPaint,
333 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800334 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800335 const char text[], size_t byteLength,
336 const SkScalar pos[], int scalarsPerPosition,
337 const SkPoint& offset, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800338 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800339 return;
joshualitt27004b72016-02-11 12:00:33 -0800340 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
joshualitte55750e2016-02-10 12:52:21 -0800341 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800342 CreateDrawPosTextBlob(context->getTextBlobCache(),
343 context->getBatchFontCache(),
344 *context->caps()->shaderCaps(),
345 paint, skPaint, viewMatrix, props,
346 text, byteLength,
347 pos, scalarsPerPosition,
348 offset));
349 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
joshualitt8e0ef292016-02-19 14:13:03 -0800350 clip, viewMatrix, regionClipBounds, offset.fX, offset.fY);
joshualitte55750e2016-02-10 12:52:21 -0800351 return;
352 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700353
joshualitte55750e2016-02-10 12:52:21 -0800354 // fall back to drawing as a path
joshualitt27004b72016-02-11 12:00:33 -0800355 GrTextUtils::DrawPosTextAsPath(context, dc, props, clip, skPaint, viewMatrix, text,
joshualitte55750e2016-02-10 12:52:21 -0800356 byteLength, pos, scalarsPerPosition, offset, regionClipBounds);
joshualitt9bd2daf2015-04-17 09:30:06 -0700357}
358
joshualitt79dfb2b2015-05-11 08:58:08 -0700359///////////////////////////////////////////////////////////////////////////////////////////////////
360
361#ifdef GR_TEST_UTILS
362
bsalomonabd30f52015-08-13 13:34:48 -0700363DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700364 static uint32_t gContextID = SK_InvalidGenID;
halcanary96fcdcc2015-08-27 07:41:13 -0700365 static GrAtlasTextContext* gTextContext = nullptr;
robertphillipsfcf78292015-06-19 11:49:52 -0700366 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
joshualitt79dfb2b2015-05-11 08:58:08 -0700367
368 if (context->uniqueID() != gContextID) {
369 gContextID = context->uniqueID();
halcanary385fe4d2015-08-26 13:07:48 -0700370 delete gTextContext;
robertphillips2334fb62015-06-17 05:43:33 -0700371
joshualitt27004b72016-02-11 12:00:33 -0800372 gTextContext = GrAtlasTextContext::Create();
joshualitt79dfb2b2015-05-11 08:58:08 -0700373 }
374
joshualitt79dfb2b2015-05-11 08:58:08 -0700375 // Setup dummy SkPaint / GrPaint
376 GrColor color = GrRandomColor(random);
joshualitt6c891102015-05-13 08:51:49 -0700377 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
joshualitt79dfb2b2015-05-11 08:58:08 -0700378 SkPaint skPaint;
joshualitt79dfb2b2015-05-11 08:58:08 -0700379 skPaint.setColor(color);
380 skPaint.setLCDRenderText(random->nextBool());
381 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
382 skPaint.setSubpixelText(random->nextBool());
383
384 GrPaint grPaint;
bsalomonf1b7a1d2015-09-28 06:26:28 -0700385 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700386 SkFAIL("couldn't convert paint\n");
387 }
388
389 const char* text = "The quick brown fox jumps over the lazy dog.";
390 int textLen = (int)strlen(text);
391
joshualittb8d86492016-02-24 09:23:03 -0800392 // create some random x/y offsets, including negative offsets
393 static const int kMaxTrans = 1024;
394 int xPos = (random->nextU() % 2) * 2 - 1;
395 int yPos = (random->nextU() % 2) * 2 - 1;
396 int xInt = (random->nextU() % kMaxTrans) * xPos;
397 int yInt = (random->nextU() % kMaxTrans) * yPos;
398 SkScalar x = SkIntToScalar(xInt);
399 SkScalar y = SkIntToScalar(yInt);
halcanary9d524f22016-03-29 09:03:52 -0700400
joshualitt79dfb2b2015-05-11 08:58:08 -0700401 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only
402 // intend to test the batch with this unit test, that is okay.
joshualitt374b2f72015-07-21 08:05:03 -0700403 SkAutoTUnref<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800404 GrAtlasTextContext::CreateDrawTextBlob(context->getTextBlobCache(),
405 context->getBatchFontCache(),
406 *context->caps()->shaderCaps(), grPaint, skPaint,
407 viewMatrix,
408 gSurfaceProps, text,
joshualittb8d86492016-02-24 09:23:03 -0800409 static_cast<size_t>(textLen), x, y));
joshualitt79dfb2b2015-05-11 08:58:08 -0700410
joshualitt8e0ef292016-02-19 14:13:03 -0800411 return blob->test_createBatch(textLen, 0, 0, viewMatrix, x, y, color, skPaint,
joshualitt323c2eb2016-01-20 06:48:47 -0800412 gSurfaceProps, gTextContext->dfAdjustTable(),
413 context->getBatchFontCache());
joshualitt79dfb2b2015-05-11 08:58:08 -0700414}
415
416#endif