blob: 76bdfc83cb848eed175c2d452d13cebaca62e7e6 [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"
Brian Osman11052242016-10-27 14:47:55 -040010#include "GrRenderTargetContext.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
Brian Osman11052242016-10-27 14:47:55 -040056uint32_t GrAtlasTextContext::ComputeScalerContextFlags(GrRenderTargetContext* rtc) {
brianosman5280dcb2016-04-14 06:02:59 -070057 // If we're doing gamma-correct rendering, then we can disable the gamma hacks.
58 // Otherwise, leave them on. In either case, we still want the contrast boost:
Brian Osman11052242016-10-27 14:47:55 -040059 if (rtc->isGammaCorrect()) {
brianosmana1e8f8d2016-04-08 06:47:54 -070060 return SkPaint::kBoostContrast_ScalerContextFlag;
brianosman32f77822016-04-07 06:25:45 -070061 } else {
brianosmana1e8f8d2016-04-08 06:47:54 -070062 return SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags;
brianosman32f77822016-04-07 06:25:45 -070063 }
64}
65
joshualitt9e36c1a2015-04-14 12:17:27 -070066// TODO if this function ever shows up in profiling, then we can compute this value when the
67// textblob is being built and cache it. However, for the time being textblobs mostly only have 1
68// run so this is not a big deal to compute here.
69bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) {
halcanary33779752015-10-27 14:01:05 -070070 SkTextBlobRunIterator it(blob);
joshualitt9e36c1a2015-04-14 12:17:27 -070071 for (; !it.done(); it.next()) {
72 if (it.isLCD()) {
73 return true;
74 }
75 }
76 return false;
77}
78
Brian Osman11052242016-10-27 14:47:55 -040079void GrAtlasTextContext::drawTextBlob(GrContext* context, GrRenderTargetContext* rtc,
robertphillipsccb1b572015-05-27 11:02:55 -070080 const GrClip& clip, const SkPaint& skPaint,
joshualitt2c89bc12016-02-11 05:42:30 -080081 const SkMatrix& viewMatrix,
82 const SkSurfaceProps& props, const SkTextBlob* blob,
robertphillipsccb1b572015-05-27 11:02:55 -070083 SkScalar x, SkScalar y,
joshualittdbd35932015-04-02 09:19:04 -070084 SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
joshualitt9b8e79e2015-04-24 09:57:12 -070085 // If we have been abandoned, then don't draw
joshualitt27004b72016-02-11 12:00:33 -080086 if (context->abandoned()) {
robertphillipsea461502015-05-26 11:38:03 -070087 return;
88 }
89
Hal Canary144caf52016-11-07 17:57:18 -050090 sk_sp<GrAtlasTextBlob> cacheBlob;
joshualitt53b5f442015-04-13 06:33:59 -070091 SkMaskFilter::BlurRec blurRec;
joshualitt374b2f72015-07-21 08:05:03 -070092 GrAtlasTextBlob::Key key;
joshualitt53b5f442015-04-13 06:33:59 -070093 // It might be worth caching these things, but its not clear at this time
94 // TODO for animated mask filters, this will fill up our cache. We need a safeguard here
95 const SkMaskFilter* mf = skPaint.getMaskFilter();
joshualitt2a0e9f32015-04-13 06:12:21 -070096 bool canCache = !(skPaint.getPathEffect() ||
joshualitt53b5f442015-04-13 06:33:59 -070097 (mf && !mf->asABlur(&blurRec)) ||
joshualitt2a0e9f32015-04-13 06:12:21 -070098 drawFilter);
Brian Osman11052242016-10-27 14:47:55 -040099 uint32_t scalerContextFlags = ComputeScalerContextFlags(rtc);
joshualitt2a0e9f32015-04-13 06:12:21 -0700100
joshualitt27004b72016-02-11 12:00:33 -0800101 GrTextBlobCache* cache = context->getTextBlobCache();
joshualitt2a0e9f32015-04-13 06:12:21 -0700102 if (canCache) {
joshualitt9e36c1a2015-04-14 12:17:27 -0700103 bool hasLCD = HasLCD(blob);
joshualitte4cee1f2015-05-11 13:04:28 -0700104
105 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
joshualitt2c89bc12016-02-11 05:42:30 -0800106 SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() :
joshualitte4cee1f2015-05-11 13:04:28 -0700107 kUnknown_SkPixelGeometry;
108
joshualitt9e36c1a2015-04-14 12:17:27 -0700109 // TODO we want to figure out a way to be able to use the canonical color on LCD text,
110 // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
111 // ensure we always match the same key
112 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
113 ComputeCanonicalColor(skPaint, hasLCD);
114
joshualitte4cee1f2015-05-11 13:04:28 -0700115 key.fPixelGeometry = pixelGeometry;
joshualitt53b5f442015-04-13 06:33:59 -0700116 key.fUniqueID = blob->uniqueID();
117 key.fStyle = skPaint.getStyle();
118 key.fHasBlur = SkToBool(mf);
joshualitt9e36c1a2015-04-14 12:17:27 -0700119 key.fCanonicalColor = canonicalColor;
brianosman8d7ffce2016-04-21 08:29:06 -0700120 key.fScalerContextFlags = scalerContextFlags;
joshualitt27004b72016-02-11 12:00:33 -0800121 cacheBlob.reset(SkSafeRef(cache->find(key)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700122 }
123
joshualitt9e36c1a2015-04-14 12:17:27 -0700124 // Though for the time being runs in the textblob can override the paint, they only touch font
125 // info.
126 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400127 if (!SkPaintToGrPaint(context, rtc, skPaint, viewMatrix, &grPaint)) {
bsalomonbed83a62015-04-15 14:18:34 -0700128 return;
129 }
joshualitt9e36c1a2015-04-14 12:17:27 -0700130
joshualittb7133be2015-04-08 09:08:31 -0700131 if (cacheBlob) {
joshualitt8e0ef292016-02-19 14:13:03 -0800132 if (cacheBlob->mustRegenerate(skPaint, grPaint.getColor(), blurRec, viewMatrix, x, y)) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700133 // We have to remake the blob because changes may invalidate our masks.
134 // TODO we could probably get away reuse most of the time if the pointer is unique,
135 // but we'd have to clear the subrun information
Hal Canary144caf52016-11-07 17:57:18 -0500136 cache->remove(cacheBlob.get());
joshualitt27004b72016-02-11 12:00:33 -0800137 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
Hal Canary144caf52016-11-07 17:57:18 -0500138 RegenerateTextBlob(cacheBlob.get(), context->getBatchFontCache(),
joshualitt27004b72016-02-11 12:00:33 -0800139 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
brianosmana1e8f8d2016-04-08 06:47:54 -0700140 scalerContextFlags, viewMatrix, props,
joshualitt27004b72016-02-11 12:00:33 -0800141 blob, x, y, drawFilter);
joshualittb7133be2015-04-08 09:08:31 -0700142 } else {
Hal Canary144caf52016-11-07 17:57:18 -0500143 cache->makeMRU(cacheBlob.get());
joshualitt2f2ee832016-02-10 08:52:24 -0800144
145 if (CACHE_SANITY_CHECK) {
joshualitt259fbf12015-07-21 11:39:34 -0700146 int glyphCount = 0;
147 int runCount = 0;
148 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
Hal Canary144caf52016-11-07 17:57:18 -0500149 sk_sp<GrAtlasTextBlob> sanityBlob(cache->createBlob(glyphCount, runCount));
joshualitt92303772016-02-10 11:55:52 -0800150 sanityBlob->setupKey(key, blurRec, skPaint);
Hal Canary144caf52016-11-07 17:57:18 -0500151 RegenerateTextBlob(sanityBlob.get(), context->getBatchFontCache(),
joshualitt27004b72016-02-11 12:00:33 -0800152 *context->caps()->shaderCaps(), skPaint,
brianosmana1e8f8d2016-04-08 06:47:54 -0700153 grPaint.getColor(), scalerContextFlags, viewMatrix, props,
joshualitt27004b72016-02-11 12:00:33 -0800154 blob, x, y, drawFilter);
joshualitt259fbf12015-07-21 11:39:34 -0700155 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
156 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700157 }
158 } else {
joshualitt2a0e9f32015-04-13 06:12:21 -0700159 if (canCache) {
joshualitt27004b72016-02-11 12:00:33 -0800160 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, skPaint)));
joshualitt2a0e9f32015-04-13 06:12:21 -0700161 } else {
joshualitt27004b72016-02-11 12:00:33 -0800162 cacheBlob.reset(cache->createBlob(blob));
joshualitt2a0e9f32015-04-13 06:12:21 -0700163 }
Hal Canary144caf52016-11-07 17:57:18 -0500164 RegenerateTextBlob(cacheBlob.get(), context->getBatchFontCache(),
joshualitt27004b72016-02-11 12:00:33 -0800165 *context->caps()->shaderCaps(), skPaint, grPaint.getColor(),
brianosmana1e8f8d2016-04-08 06:47:54 -0700166 scalerContextFlags, viewMatrix, props,
joshualitt27004b72016-02-11 12:00:33 -0800167 blob, x, y, drawFilter);
joshualitt1d89e8d2015-04-01 12:40:54 -0700168 }
169
Hal Canary144caf52016-11-07 17:57:18 -0500170 cacheBlob->flushCached(context, rtc, blob, props, fDistanceAdjustTable.get(), skPaint,
joshualitt8e0ef292016-02-19 14:13:03 -0800171 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y);
joshualitt1d89e8d2015-04-01 12:40:54 -0700172}
173
joshualitt27004b72016-02-11 12:00:33 -0800174void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob,
175 GrBatchFontCache* fontCache,
176 const GrShaderCaps& shaderCaps,
joshualitt9e36c1a2015-04-14 12:17:27 -0700177 const SkPaint& skPaint, GrColor color,
brianosmana1e8f8d2016-04-08 06:47:54 -0700178 uint32_t scalerContextFlags,
joshualitt9e36c1a2015-04-14 12:17:27 -0700179 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800180 const SkSurfaceProps& props,
joshualittdbd35932015-04-02 09:19:04 -0700181 const SkTextBlob* blob, SkScalar x, SkScalar y,
joshualitta6bf4c52016-01-19 06:59:29 -0800182 SkDrawFilter* drawFilter) {
joshualitt323c2eb2016-01-20 06:48:47 -0800183 cacheBlob->initReusableBlob(color, viewMatrix, x, y);
joshualitt1d89e8d2015-04-01 12:40:54 -0700184
185 // Regenerate textblob
186 SkPaint runPaint = skPaint;
halcanary33779752015-10-27 14:01:05 -0700187 SkTextBlobRunIterator it(blob);
joshualitt1d89e8d2015-04-01 12:40:54 -0700188 for (int run = 0; !it.done(); it.next(), run++) {
189 int glyphCount = it.glyphCount();
190 size_t textLen = glyphCount * sizeof(uint16_t);
191 const SkPoint& offset = it.offset();
192 // applyFontToPaint() always overwrites the exact same attributes,
193 // so it is safe to not re-seed the paint for this reason.
194 it.applyFontToPaint(&runPaint);
195
196 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
197 // A false return from filter() means we should abort the current draw.
198 runPaint = skPaint;
199 continue;
200 }
201
joshualitt8e84a1e2016-02-16 11:09:25 -0800202 runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));
joshualitt1d89e8d2015-04-01 12:40:54 -0700203
joshualitt18b072d2015-12-07 12:26:12 -0800204 cacheBlob->push_back_run(run);
joshualitt1d89e8d2015-04-01 12:40:54 -0700205
joshualitt27004b72016-02-11 12:00:33 -0800206 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) {
joshualittfcfb9fc2015-04-21 07:35:10 -0700207 switch (it.positioning()) {
208 case SkTextBlob::kDefault_Positioning: {
joshualitt27004b72016-02-11 12:00:33 -0800209 GrTextUtils::DrawDFText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700210 props, runPaint, color, scalerContextFlags,
211 viewMatrix, (const char *)it.glyphs(), textLen,
joshualitt0d2199b2016-01-20 06:36:09 -0800212 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700213 break;
214 }
215 case SkTextBlob::kHorizontal_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800216 SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
joshualitt27004b72016-02-11 12:00:33 -0800217 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700218 props, runPaint, color, scalerContextFlags,
219 viewMatrix, (const char*)it.glyphs(), textLen,
220 it.pos(), 1, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700221 break;
222 }
223 case SkTextBlob::kFull_Positioning: {
joshualitt5425a9a2015-12-11 11:05:43 -0800224 SkPoint dfOffset = SkPoint::Make(x, y);
joshualitt27004b72016-02-11 12:00:33 -0800225 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700226 props, runPaint, color, scalerContextFlags,
227 viewMatrix, (const char*)it.glyphs(), textLen,
228 it.pos(), 2, dfOffset);
joshualittfcfb9fc2015-04-21 07:35:10 -0700229 break;
230 }
231 }
joshualittfcfb9fc2015-04-21 07:35:10 -0700232 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
joshualitt323c2eb2016-01-20 06:48:47 -0800233 cacheBlob->setRunDrawAsPaths(run);
joshualittfcfb9fc2015-04-21 07:35:10 -0700234 } else {
joshualittfcfb9fc2015-04-21 07:35:10 -0700235 switch (it.positioning()) {
236 case SkTextBlob::kDefault_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800237 GrTextUtils::DrawBmpText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700238 props, runPaint, color, scalerContextFlags,
239 viewMatrix, (const char *)it.glyphs(), textLen,
joshualitt29677982015-12-11 06:08:59 -0800240 x + offset.x(), y + offset.y());
joshualittfcfb9fc2015-04-21 07:35:10 -0700241 break;
242 case SkTextBlob::kHorizontal_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800243 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700244 props, runPaint, color, scalerContextFlags,
245 viewMatrix, (const char*)it.glyphs(), textLen,
246 it.pos(), 1, SkPoint::Make(x, y + offset.y()));
joshualittfcfb9fc2015-04-21 07:35:10 -0700247 break;
248 case SkTextBlob::kFull_Positioning:
joshualitt27004b72016-02-11 12:00:33 -0800249 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache,
brianosmana1e8f8d2016-04-08 06:47:54 -0700250 props, runPaint, color, scalerContextFlags,
251 viewMatrix, (const char*)it.glyphs(), textLen,
252 it.pos(), 2, SkPoint::Make(x, y));
joshualittfcfb9fc2015-04-21 07:35:10 -0700253 break;
254 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700255 }
256
257 if (drawFilter) {
258 // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
259 runPaint = skPaint;
260 }
joshualitt1d89e8d2015-04-01 12:40:54 -0700261 }
262}
263
joshualitt374b2f72015-07-21 08:05:03 -0700264inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800265GrAtlasTextContext::CreateDrawTextBlob(GrTextBlobCache* blobCache,
266 GrBatchFontCache* fontCache,
267 const GrShaderCaps& shaderCaps,
268 const GrPaint& paint,
joshualitt2c89bc12016-02-11 05:42:30 -0800269 const SkPaint& skPaint,
brianosmana1e8f8d2016-04-08 06:47:54 -0700270 uint32_t scalerContextFlags,
joshualitt79dfb2b2015-05-11 08:58:08 -0700271 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800272 const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700273 const char text[], size_t byteLength,
joshualitt5425a9a2015-12-11 11:05:43 -0800274 SkScalar x, SkScalar y) {
joshualitt1d89e8d2015-04-01 12:40:54 -0700275 int glyphCount = skPaint.countText(text, byteLength);
joshualitt1d89e8d2015-04-01 12:40:54 -0700276
joshualitt27004b72016-02-11 12:00:33 -0800277 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800278 blob->initThrowawayBlob(viewMatrix, x, y);
joshualitta6bf4c52016-01-19 06:59:29 -0800279
joshualitt27004b72016-02-11 12:00:33 -0800280 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
brianosmana1e8f8d2016-04-08 06:47:54 -0700281 GrTextUtils::DrawDFText(blob, 0, fontCache, props, skPaint, paint.getColor(),
282 scalerContextFlags, viewMatrix, text, byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700283 } else {
brianosmana1e8f8d2016-04-08 06:47:54 -0700284 GrTextUtils::DrawBmpText(blob, 0, fontCache, props, skPaint, paint.getColor(),
285 scalerContextFlags, viewMatrix, text, byteLength, x, y);
joshualitt9bd2daf2015-04-17 09:30:06 -0700286 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700287 return blob;
joshualitt1d89e8d2015-04-01 12:40:54 -0700288}
289
joshualitt374b2f72015-07-21 08:05:03 -0700290inline GrAtlasTextBlob*
joshualitt27004b72016-02-11 12:00:33 -0800291GrAtlasTextContext::CreateDrawPosTextBlob(GrTextBlobCache* blobCache, GrBatchFontCache* fontCache,
292 const GrShaderCaps& shaderCaps, const GrPaint& paint,
brianosmana1e8f8d2016-04-08 06:47:54 -0700293 const SkPaint& skPaint, uint32_t scalerContextFlags,
joshualitt2c89bc12016-02-11 05:42:30 -0800294 const SkMatrix& viewMatrix, const SkSurfaceProps& props,
joshualitt79dfb2b2015-05-11 08:58:08 -0700295 const char text[], size_t byteLength,
296 const SkScalar pos[], int scalarsPerPosition,
joshualitt5425a9a2015-12-11 11:05:43 -0800297 const SkPoint& offset) {
joshualitt9bd2daf2015-04-17 09:30:06 -0700298 int glyphCount = skPaint.countText(text, byteLength);
299
joshualitt27004b72016-02-11 12:00:33 -0800300 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1);
joshualitt7481e752016-01-22 06:08:48 -0800301 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y());
joshualitt9bd2daf2015-04-17 09:30:06 -0700302
joshualitt27004b72016-02-11 12:00:33 -0800303 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps)) {
304 GrTextUtils::DrawDFPosText(blob, 0, fontCache, props,
brianosmana1e8f8d2016-04-08 06:47:54 -0700305 skPaint, paint.getColor(), scalerContextFlags, viewMatrix, text,
joshualitt0d2199b2016-01-20 06:36:09 -0800306 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700307 } else {
joshualitt27004b72016-02-11 12:00:33 -0800308 GrTextUtils::DrawBmpPosText(blob, 0, fontCache, props, skPaint,
brianosmana1e8f8d2016-04-08 06:47:54 -0700309 paint.getColor(), scalerContextFlags, viewMatrix, text,
joshualitt29677982015-12-11 06:08:59 -0800310 byteLength, pos, scalarsPerPosition, offset);
joshualitt9bd2daf2015-04-17 09:30:06 -0700311 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700312 return blob;
313}
314
joshualitt27004b72016-02-11 12:00:33 -0800315void GrAtlasTextContext::drawText(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400316 GrRenderTargetContext* rtc,
joshualitte55750e2016-02-10 12:52:21 -0800317 const GrClip& clip,
318 const GrPaint& paint, const SkPaint& skPaint,
319 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800320 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800321 const char text[], size_t byteLength,
322 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800323 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800324 return;
joshualitt27004b72016-02-11 12:00:33 -0800325 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
Hal Canary144caf52016-11-07 17:57:18 -0500326 sk_sp<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800327 CreateDrawTextBlob(context->getTextBlobCache(), context->getBatchFontCache(),
328 *context->caps()->shaderCaps(),
329 paint, skPaint,
Brian Osman11052242016-10-27 14:47:55 -0400330 ComputeScalerContextFlags(rtc),
joshualitt27004b72016-02-11 12:00:33 -0800331 viewMatrix, props,
332 text, byteLength, x, y));
Hal Canary144caf52016-11-07 17:57:18 -0500333 blob->flushThrowaway(context, rtc, props, fDistanceAdjustTable.get(), skPaint, paint,
joshualitt8e0ef292016-02-19 14:13:03 -0800334 clip, viewMatrix, regionClipBounds, x, y);
joshualitte55750e2016-02-10 12:52:21 -0800335 return;
336 }
337
338 // fall back to drawing as a path
Brian Osman11052242016-10-27 14:47:55 -0400339 GrTextUtils::DrawTextAsPath(context, rtc, clip, skPaint, viewMatrix, text, byteLength, x, y,
joshualitte55750e2016-02-10 12:52:21 -0800340 regionClipBounds);
joshualitt79dfb2b2015-05-11 08:58:08 -0700341}
342
joshualitt27004b72016-02-11 12:00:33 -0800343void GrAtlasTextContext::drawPosText(GrContext* context,
Brian Osman11052242016-10-27 14:47:55 -0400344 GrRenderTargetContext* rtc,
joshualitte55750e2016-02-10 12:52:21 -0800345 const GrClip& clip,
346 const GrPaint& paint, const SkPaint& skPaint,
347 const SkMatrix& viewMatrix,
joshualitt2c89bc12016-02-11 05:42:30 -0800348 const SkSurfaceProps& props,
joshualitte55750e2016-02-10 12:52:21 -0800349 const char text[], size_t byteLength,
350 const SkScalar pos[], int scalarsPerPosition,
351 const SkPoint& offset, const SkIRect& regionClipBounds) {
joshualitt27004b72016-02-11 12:00:33 -0800352 if (context->abandoned()) {
joshualitte55750e2016-02-10 12:52:21 -0800353 return;
joshualitt27004b72016-02-11 12:00:33 -0800354 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
Hal Canary144caf52016-11-07 17:57:18 -0500355 sk_sp<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800356 CreateDrawPosTextBlob(context->getTextBlobCache(),
357 context->getBatchFontCache(),
358 *context->caps()->shaderCaps(),
brianosman32f77822016-04-07 06:25:45 -0700359 paint, skPaint,
Brian Osman11052242016-10-27 14:47:55 -0400360 ComputeScalerContextFlags(rtc),
brianosman32f77822016-04-07 06:25:45 -0700361 viewMatrix, props,
joshualitt27004b72016-02-11 12:00:33 -0800362 text, byteLength,
363 pos, scalarsPerPosition,
364 offset));
Hal Canary144caf52016-11-07 17:57:18 -0500365 blob->flushThrowaway(context, rtc, props, fDistanceAdjustTable.get(), skPaint, paint,
joshualitt8e0ef292016-02-19 14:13:03 -0800366 clip, viewMatrix, regionClipBounds, offset.fX, offset.fY);
joshualitte55750e2016-02-10 12:52:21 -0800367 return;
368 }
joshualitt79dfb2b2015-05-11 08:58:08 -0700369
joshualitte55750e2016-02-10 12:52:21 -0800370 // fall back to drawing as a path
Brian Osman11052242016-10-27 14:47:55 -0400371 GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, skPaint, viewMatrix, text,
joshualitte55750e2016-02-10 12:52:21 -0800372 byteLength, pos, scalarsPerPosition, offset, regionClipBounds);
joshualitt9bd2daf2015-04-17 09:30:06 -0700373}
374
joshualitt79dfb2b2015-05-11 08:58:08 -0700375///////////////////////////////////////////////////////////////////////////////////////////////////
376
377#ifdef GR_TEST_UTILS
378
bsalomonabd30f52015-08-13 13:34:48 -0700379DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700380 static uint32_t gContextID = SK_InvalidGenID;
halcanary96fcdcc2015-08-27 07:41:13 -0700381 static GrAtlasTextContext* gTextContext = nullptr;
robertphillipsfcf78292015-06-19 11:49:52 -0700382 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
joshualitt79dfb2b2015-05-11 08:58:08 -0700383
384 if (context->uniqueID() != gContextID) {
385 gContextID = context->uniqueID();
halcanary385fe4d2015-08-26 13:07:48 -0700386 delete gTextContext;
robertphillips2334fb62015-06-17 05:43:33 -0700387
joshualitt27004b72016-02-11 12:00:33 -0800388 gTextContext = GrAtlasTextContext::Create();
joshualitt79dfb2b2015-05-11 08:58:08 -0700389 }
390
Brian Osman11052242016-10-27 14:47:55 -0400391 // Setup dummy SkPaint / GrPaint / GrRenderTargetContext
392 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeRenderTargetContext(
393 SkBackingFit::kApprox, 1024, 1024, kRGBA_8888_GrPixelConfig, nullptr));
brianosman8fe485b2016-07-25 12:31:51 -0700394
joshualitt79dfb2b2015-05-11 08:58:08 -0700395 GrColor color = GrRandomColor(random);
joshualitt6c891102015-05-13 08:51:49 -0700396 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
joshualitt79dfb2b2015-05-11 08:58:08 -0700397 SkPaint skPaint;
joshualitt79dfb2b2015-05-11 08:58:08 -0700398 skPaint.setColor(color);
399 skPaint.setLCDRenderText(random->nextBool());
400 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool());
401 skPaint.setSubpixelText(random->nextBool());
402
403 GrPaint grPaint;
Brian Osman11052242016-10-27 14:47:55 -0400404 if (!SkPaintToGrPaint(context, renderTargetContext.get(), skPaint, viewMatrix, &grPaint)) {
joshualitt79dfb2b2015-05-11 08:58:08 -0700405 SkFAIL("couldn't convert paint\n");
406 }
407
408 const char* text = "The quick brown fox jumps over the lazy dog.";
409 int textLen = (int)strlen(text);
410
joshualittb8d86492016-02-24 09:23:03 -0800411 // create some random x/y offsets, including negative offsets
412 static const int kMaxTrans = 1024;
413 int xPos = (random->nextU() % 2) * 2 - 1;
414 int yPos = (random->nextU() % 2) * 2 - 1;
415 int xInt = (random->nextU() % kMaxTrans) * xPos;
416 int yInt = (random->nextU() % kMaxTrans) * yPos;
417 SkScalar x = SkIntToScalar(xInt);
418 SkScalar y = SkIntToScalar(yInt);
halcanary9d524f22016-03-29 09:03:52 -0700419
joshualitt79dfb2b2015-05-11 08:58:08 -0700420 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only
421 // intend to test the batch with this unit test, that is okay.
Hal Canary144caf52016-11-07 17:57:18 -0500422 sk_sp<GrAtlasTextBlob> blob(
joshualitt27004b72016-02-11 12:00:33 -0800423 GrAtlasTextContext::CreateDrawTextBlob(context->getTextBlobCache(),
424 context->getBatchFontCache(),
425 *context->caps()->shaderCaps(), grPaint, skPaint,
brianosmana1e8f8d2016-04-08 06:47:54 -0700426 GrAtlasTextContext::kTextBlobBatchScalerContextFlags,
joshualitt27004b72016-02-11 12:00:33 -0800427 viewMatrix,
428 gSurfaceProps, text,
joshualittb8d86492016-02-24 09:23:03 -0800429 static_cast<size_t>(textLen), x, y));
joshualitt79dfb2b2015-05-11 08:58:08 -0700430
joshualitt8e0ef292016-02-19 14:13:03 -0800431 return blob->test_createBatch(textLen, 0, 0, viewMatrix, x, y, color, skPaint,
joshualitt323c2eb2016-01-20 06:48:47 -0800432 gSurfaceProps, gTextContext->dfAdjustTable(),
433 context->getBatchFontCache());
joshualitt79dfb2b2015-05-11 08:58:08 -0700434}
435
436#endif