11d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt/* 21d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * Copyright 2015 Google Inc. 31d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * 41d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * Use of this source code is governed by a BSD-style license that can be 51d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * found in the LICENSE file. 61d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt */ 71d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrAtlasTextContext.h" 873c4e64f4bb90059cf822dac9eaf30e1c38bec77robertphillips#include "GrContext.h" 9f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips#include "GrContextPriv.h" 10b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt#include "GrTextBlobCache.h" 1152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon#include "SkDistanceFieldGen.h" 121d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkDraw.h" 131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkDrawFilter.h" 1454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth#include "SkDrawProcs.h" 1552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon#include "SkFindAndPlaceGlyph.h" 163b65598bceb65736486db27ed49a56d787032747Brian Osman#include "SkGr.h" 17c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth#include "SkGraphics.h" 18af597481143ca4b17884360604be954a71cc34cfBrian Salomon#include "SkMakeUnique.h" 1980747ef591ff3c09c2b610eb21258132d1ff4ef5Mike Reed#include "SkMaskFilterBase.h" 2054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth#include "SkTextMapStateProc.h" 2154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 22649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon#include "ops/GrMeshDrawOp.h" 2327004b7e653a38570d3fd1621ed0107e5443b31ajoshualitt 24af597481143ca4b17884360604be954a71cc34cfBrian Salomon// DF sizes and thresholds for usage of the small and medium sizes. For example, above 25af597481143ca4b17884360604be954a71cc34cfBrian Salomon// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at 26af597481143ca4b17884360604be954a71cc34cfBrian Salomon// which we switch over to drawing as paths as controlled by Options. 27af597481143ca4b17884360604be954a71cc34cfBrian Salomonstatic const int kSmallDFFontSize = 32; 28af597481143ca4b17884360604be954a71cc34cfBrian Salomonstatic const int kSmallDFFontLimit = 32; 29825d4d798aed471ceff48fcb03667b268bc15a83Jim Van Verthstatic const int kMediumDFFontSize = 72; 30825d4d798aed471ceff48fcb03667b268bc15a83Jim Van Verthstatic const int kMediumDFFontLimit = 72; 31825d4d798aed471ceff48fcb03667b268bc15a83Jim Van Verthstatic const int kLargeDFFontSize = 162; 32af597481143ca4b17884360604be954a71cc34cfBrian Salomon 33af597481143ca4b17884360604be954a71cc34cfBrian Salomonstatic const int kDefaultMinDistanceFieldFontSize = 18; 34af597481143ca4b17884360604be954a71cc34cfBrian Salomon#ifdef SK_BUILD_FOR_ANDROID 35af597481143ca4b17884360604be954a71cc34cfBrian Salomonstatic const int kDefaultMaxDistanceFieldFontSize = 384; 36af597481143ca4b17884360604be954a71cc34cfBrian Salomon#else 37af597481143ca4b17884360604be954a71cc34cfBrian Salomonstatic const int kDefaultMaxDistanceFieldFontSize = 2 * kLargeDFFontSize; 38af597481143ca4b17884360604be954a71cc34cfBrian Salomon#endif 39af597481143ca4b17884360604be954a71cc34cfBrian Salomon 40af597481143ca4b17884360604be954a71cc34cfBrian SalomonGrAtlasTextContext::GrAtlasTextContext(const Options& options) 41af597481143ca4b17884360604be954a71cc34cfBrian Salomon : fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { 42af597481143ca4b17884360604be954a71cc34cfBrian Salomon fMaxDistanceFieldFontSize = options.fMaxDistanceFieldFontSize < 0.f 43af597481143ca4b17884360604be954a71cc34cfBrian Salomon ? kDefaultMaxDistanceFieldFontSize 44af597481143ca4b17884360604be954a71cc34cfBrian Salomon : options.fMaxDistanceFieldFontSize; 45af597481143ca4b17884360604be954a71cc34cfBrian Salomon fMinDistanceFieldFontSize = options.fMinDistanceFieldFontSize < 0.f 46af597481143ca4b17884360604be954a71cc34cfBrian Salomon ? kDefaultMinDistanceFieldFontSize 47af597481143ca4b17884360604be954a71cc34cfBrian Salomon : options.fMinDistanceFieldFontSize; 48b5086961f335d6757a88ce7507c445485aaba2e6Brian Salomon fDistanceFieldVerticesAlwaysHaveW = options.fDistanceFieldVerticesAlwaysHaveW; 499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 51af597481143ca4b17884360604be954a71cc34cfBrian Salomonstd::unique_ptr<GrAtlasTextContext> GrAtlasTextContext::Make(const Options& options) { 52af597481143ca4b17884360604be954a71cc34cfBrian Salomon return std::unique_ptr<GrAtlasTextContext>(new GrAtlasTextContext(options)); 531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 541d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 556f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian SalomonSkColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) { 566f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon SkColor canonicalColor = paint.computeLuminanceColor(); 579e36c1a9306f052331550dab4728b9875127bfb5joshualitt if (lcd) { 589e36c1a9306f052331550dab4728b9875127bfb5joshualitt // This is the correct computation, but there are tons of cases where LCD can be overridden. 599e36c1a9306f052331550dab4728b9875127bfb5joshualitt // For now we just regenerate if any run in a textblob has LCD. 609e36c1a9306f052331550dab4728b9875127bfb5joshualitt // TODO figure out where all of these overrides are and see if we can incorporate that logic 619e36c1a9306f052331550dab4728b9875127bfb5joshualitt // at a higher level *OR* use sRGB 629e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkASSERT(false); 639e36c1a9306f052331550dab4728b9875127bfb5joshualitt //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor); 649e36c1a9306f052331550dab4728b9875127bfb5joshualitt } else { 659e36c1a9306f052331550dab4728b9875127bfb5joshualitt // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have 669e36c1a9306f052331550dab4728b9875127bfb5joshualitt // gamma corrected masks anyways, nor color 679e36c1a9306f052331550dab4728b9875127bfb5joshualitt U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor), 689e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkColorGetG(canonicalColor), 699e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkColorGetB(canonicalColor)); 709e36c1a9306f052331550dab4728b9875127bfb5joshualitt // reduce to our finite number of bits 719e36c1a9306f052331550dab4728b9875127bfb5joshualitt canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum)); 729e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 739e36c1a9306f052331550dab4728b9875127bfb5joshualitt return canonicalColor; 749e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 759e36c1a9306f052331550dab4728b9875127bfb5joshualitt 76d8327a8c8bad870112b574c4533270370f5c1ccfHerb DerbySkScalerContextFlags GrAtlasTextContext::ComputeScalerContextFlags( 77d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby const GrColorSpaceInfo& colorSpaceInfo) { 785280dcbae3affd73be5d5e0ff3db8823e26901e6brianosman // If we're doing gamma-correct rendering, then we can disable the gamma hacks. 795280dcbae3affd73be5d5e0ff3db8823e26901e6brianosman // Otherwise, leave them on. In either case, we still want the contrast boost: 80f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon if (colorSpaceInfo.isGammaCorrect()) { 81d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby return SkScalerContextFlags::kBoostContrast; 8232f7782706fbf692c613457a74d080e18e27b15abrianosman } else { 83d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby return SkScalerContextFlags::kFakeGammaAndBoostContrast; 8432f7782706fbf692c613457a74d080e18e27b15abrianosman } 8532f7782706fbf692c613457a74d080e18e27b15abrianosman} 8632f7782706fbf692c613457a74d080e18e27b15abrianosman 879e36c1a9306f052331550dab4728b9875127bfb5joshualitt// TODO if this function ever shows up in profiling, then we can compute this value when the 889e36c1a9306f052331550dab4728b9875127bfb5joshualitt// textblob is being built and cache it. However, for the time being textblobs mostly only have 1 899e36c1a9306f052331550dab4728b9875127bfb5joshualitt// run so this is not a big deal to compute here. 909e36c1a9306f052331550dab4728b9875127bfb5joshualittbool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { 91337797580de42cdb722caab4bed121311ed7d0d2halcanary SkTextBlobRunIterator it(blob); 929e36c1a9306f052331550dab4728b9875127bfb5joshualitt for (; !it.done(); it.next()) { 939e36c1a9306f052331550dab4728b9875127bfb5joshualitt if (it.isLCD()) { 949e36c1a9306f052331550dab4728b9875127bfb5joshualitt return true; 959e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 969e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 979e36c1a9306f052331550dab4728b9875127bfb5joshualitt return false; 989e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 999e36c1a9306f052331550dab4728b9875127bfb5joshualitt 100f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomonvoid GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target, 101ccb1b5751075506b4615d2112889d01ee8ad6436robertphillips const GrClip& clip, const SkPaint& skPaint, 102f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon const SkMatrix& viewMatrix, const SkSurfaceProps& props, 103f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon const SkTextBlob* blob, SkScalar x, SkScalar y, 104dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt SkDrawFilter* drawFilter, const SkIRect& clipBounds) { 1059b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt // If we have been abandoned, then don't draw 10627004b7e653a38570d3fd1621ed0107e5443b31ajoshualitt if (context->abandoned()) { 107ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips return; 108ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips } 109ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 110144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary sk_sp<GrAtlasTextBlob> cacheBlob; 11180747ef591ff3c09c2b610eb21258132d1ff4ef5Mike Reed SkMaskFilterBase::BlurRec blurRec; 112374b2f7cea8b1117f0dd17cdecd2b3ec85b141d4joshualitt GrAtlasTextBlob::Key key; 11353b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // It might be worth caching these things, but its not clear at this time 11453b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // TODO for animated mask filters, this will fill up our cache. We need a safeguard here 11553b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt const SkMaskFilter* mf = skPaint.getMaskFilter(); 1162a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt bool canCache = !(skPaint.getPathEffect() || 11780747ef591ff3c09c2b610eb21258132d1ff4ef5Mike Reed (mf && !as_MFB(mf)->asABlur(&blurRec)) || 1182a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt drawFilter); 119d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo()); 1202a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 121c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto glyphCache = context->contextPriv().getGlyphCache(); 122c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); 123f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache(); 124f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 1252a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (canCache) { 1269e36c1a9306f052331550dab4728b9875127bfb5joshualitt bool hasLCD = HasLCD(blob); 127e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt 128e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry 1292c89bc153b5228c6316b5cfa070cad3d6da169cajoshualitt SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : 130e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt kUnknown_SkPixelGeometry; 131e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt 1329e36c1a9306f052331550dab4728b9875127bfb5joshualitt // TODO we want to figure out a way to be able to use the canonical color on LCD text, 1339e36c1a9306f052331550dab4728b9875127bfb5joshualitt // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to 1349e36c1a9306f052331550dab4728b9875127bfb5joshualitt // ensure we always match the same key 1359e36c1a9306f052331550dab4728b9875127bfb5joshualitt GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : 1369e36c1a9306f052331550dab4728b9875127bfb5joshualitt ComputeCanonicalColor(skPaint, hasLCD); 1379e36c1a9306f052331550dab4728b9875127bfb5joshualitt 138e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt key.fPixelGeometry = pixelGeometry; 13953b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fUniqueID = blob->uniqueID(); 14053b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fStyle = skPaint.getStyle(); 14153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fHasBlur = SkToBool(mf); 1429e36c1a9306f052331550dab4728b9875127bfb5joshualitt key.fCanonicalColor = canonicalColor; 1438d7ffcee75661a50ce298dc1b3bc0b76bea018e7brianosman key.fScalerContextFlags = scalerContextFlags; 144f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips cacheBlob = textBlobCache->find(key); 1452a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 1462a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 147f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); 148b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt if (cacheBlob) { 1496f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) { 1501d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // We have to remake the blob because changes may invalidate our masks. 1511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // TODO we could probably get away reuse most of the time if the pointer is unique, 1521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // but we'd have to clear the subrun information 153f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips textBlobCache->remove(cacheBlob.get()); 154f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); 155c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->regenerateTextBlob(cacheBlob.get(), glyphCache, 156af597481143ca4b17884360604be954a71cc34cfBrian Salomon *context->caps()->shaderCaps(), paint, scalerContextFlags, 157af597481143ca4b17884360604be954a71cc34cfBrian Salomon viewMatrix, props, blob, x, y, drawFilter); 158b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt } else { 159f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips textBlobCache->makeMRU(cacheBlob.get()); 1602f2ee83a9c1ff05a94265b175e51c63fc424d554joshualitt 1612f2ee83a9c1ff05a94265b175e51c63fc424d554joshualitt if (CACHE_SANITY_CHECK) { 162259fbf191625d504e20c7ede69d988735fc569adjoshualitt int glyphCount = 0; 163259fbf191625d504e20c7ede69d988735fc569adjoshualitt int runCount = 0; 164259fbf191625d504e20c7ede69d988735fc569adjoshualitt GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); 165f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips sk_sp<GrAtlasTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount)); 166923037724231f11b9249dbb5bf9688835b5ff9b0joshualitt sanityBlob->setupKey(key, blurRec, skPaint); 167c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->regenerateTextBlob(sanityBlob.get(), glyphCache, 168af597481143ca4b17884360604be954a71cc34cfBrian Salomon *context->caps()->shaderCaps(), paint, scalerContextFlags, 169af597481143ca4b17884360604be954a71cc34cfBrian Salomon viewMatrix, props, blob, x, y, drawFilter); 170259fbf191625d504e20c7ede69d988735fc569adjoshualitt GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); 171259fbf191625d504e20c7ede69d988735fc569adjoshualitt } 1721d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 1731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 1742a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (canCache) { 175f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); 1762a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } else { 177f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips cacheBlob = textBlobCache->makeBlob(blob); 1782a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 179c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->regenerateTextBlob(cacheBlob.get(), glyphCache, 180af597481143ca4b17884360604be954a71cc34cfBrian Salomon *context->caps()->shaderCaps(), paint, scalerContextFlags, 181af597481143ca4b17884360604be954a71cc34cfBrian Salomon viewMatrix, props, blob, x, y, drawFilter); 1821d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 1831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 184c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips cacheBlob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, 18554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth clip, viewMatrix, clipBounds, x, y); 1861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 1871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 188af597481143ca4b17884360604be954a71cc34cfBrian Salomonvoid GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, 189c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 19027004b7e653a38570d3fd1621ed0107e5443b31ajoshualitt const GrShaderCaps& shaderCaps, 1916f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon const GrTextUtils::Paint& paint, 192d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 19358c3cce1144f83bc7e4ee5e93931b8721560735bJim Van Verth const SkMatrix& viewMatrix, 1946f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon const SkSurfaceProps& props, const SkTextBlob* blob, 195af597481143ca4b17884360604be954a71cc34cfBrian Salomon SkScalar x, SkScalar y, 196af597481143ca4b17884360604be954a71cc34cfBrian Salomon SkDrawFilter* drawFilter) const { 197bc2cdd154bf5a031ca9d3a530123d9f7a4c0925dJim Van Verth cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, x, y); 1981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Regenerate textblob 200337797580de42cdb722caab4bed121311ed7d0d2halcanary SkTextBlobRunIterator it(blob); 2016f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon GrTextUtils::RunPaint runPaint(&paint, drawFilter, props); 2021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt for (int run = 0; !it.done(); it.next(), run++) { 2031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int glyphCount = it.glyphCount(); 2041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt size_t textLen = glyphCount * sizeof(uint16_t); 2051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkPoint& offset = it.offset(); 2066f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon cacheBlob->push_back_run(run); 20754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (!runPaint.modifyForRun([it](SkPaint* p) { it.applyFontToPaint(p); })) { 2081d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt continue; 2091d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 21054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags()); 21154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 212af597481143ca4b17884360604be954a71cc34cfBrian Salomon if (this->canDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) { 213fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt switch (it.positioning()) { 214fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kDefault_Positioning: { 215c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, 216af597481143ca4b17884360604be954a71cc34cfBrian Salomon viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), 217af597481143ca4b17884360604be954a71cc34cfBrian Salomon y + offset.y()); 218fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 219fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 220fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kHorizontal_Positioning: { 2215425a9a1807b2b2eafdd5c5f4c184f7161807f66joshualitt SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); 222c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, 223af597481143ca4b17884360604be954a71cc34cfBrian Salomon scalerContextFlags, viewMatrix, (const char*)it.glyphs(), 224af597481143ca4b17884360604be954a71cc34cfBrian Salomon textLen, it.pos(), 1, dfOffset); 225fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 226fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 227fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kFull_Positioning: { 2285425a9a1807b2b2eafdd5c5f4c184f7161807f66joshualitt SkPoint dfOffset = SkPoint::Make(x, y); 229c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, 230af597481143ca4b17884360604be954a71cc34cfBrian Salomon scalerContextFlags, viewMatrix, (const char*)it.glyphs(), 231af597481143ca4b17884360604be954a71cc34cfBrian Salomon textLen, it.pos(), 2, dfOffset); 232fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 233fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 234fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 235fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } else { 236fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt switch (it.positioning()) { 237fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kDefault_Positioning: 238c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, 23952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), 24052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon y + offset.y()); 241fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 242fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kHorizontal_Positioning: 243c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, 24452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, 245c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint::Make(x, y + offset.y())); 246fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 247fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kFull_Positioning: 248c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, 24952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, 250c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint::Make(x, y)); 251fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 252fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 2531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 2541d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 2551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 2561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 257c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malitainline sk_sp<GrAtlasTextBlob> 258af597481143ca4b17884360604be954a71cc34cfBrian SalomonGrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, 259c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 260c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const GrShaderCaps& shaderCaps, 261c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const GrTextUtils::Paint& paint, 262d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 263c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const SkMatrix& viewMatrix, 264c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const SkSurfaceProps& props, 265c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const char text[], size_t byteLength, 266af597481143ca4b17884360604be954a71cc34cfBrian Salomon SkScalar x, SkScalar y) const { 2676f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon int glyphCount = paint.skPaint().countText(text, byteLength); 268b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon if (!glyphCount) { 269b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon return nullptr; 270b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon } 271c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1); 2727481e75830dfae1e9084ff62e3d8438879e31aaajoshualitt blob->initThrowawayBlob(viewMatrix, x, y); 27354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth blob->setRunPaintFlags(0, paint.skPaint().getFlags()); 2749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 275af597481143ca4b17884360604be954a71cc34cfBrian Salomon if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { 276c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, 277af597481143ca4b17884360604be954a71cc34cfBrian Salomon text, byteLength, x, y); 2789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 279c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text, 28052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon byteLength, x, y); 2819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 28279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return blob; 2831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 2841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 285c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malitainline sk_sp<GrAtlasTextBlob> 286af597481143ca4b17884360604be954a71cc34cfBrian SalomonGrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, 287c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 288c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const GrShaderCaps& shaderCaps, 289c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const GrTextUtils::Paint& paint, 290d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 291c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const SkMatrix& viewMatrix, 292c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const SkSurfaceProps& props, 293c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const char text[], size_t byteLength, 294c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita const SkScalar pos[], int scalarsPerPosition, const 295af597481143ca4b17884360604be954a71cc34cfBrian Salomon SkPoint& offset) const { 2966f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon int glyphCount = paint.skPaint().countText(text, byteLength); 297b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon if (!glyphCount) { 298b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon return nullptr; 299b3f6ac44dba7b8bc30c37753c7ce1257633525d6Brian Salomon } 3009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 301c337c9e02057fc61ef22ac80fa2e5f3dae92b498Florin Malita sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1); 3027481e75830dfae1e9084ff62e3d8438879e31aaajoshualitt blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); 30354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth blob->setRunPaintFlags(0, paint.skPaint().getFlags()); 3049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 305af597481143ca4b17884360604be954a71cc34cfBrian Salomon if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { 306c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, 307af597481143ca4b17884360604be954a71cc34cfBrian Salomon text, byteLength, pos, scalarsPerPosition, offset); 3089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 309c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, 310c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips text, byteLength, pos, scalarsPerPosition, offset); 3119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 31279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return blob; 31379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 31479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 315f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomonvoid GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* target, 3166f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon const GrClip& clip, const SkPaint& skPaint, 31782f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const SkMatrix& viewMatrix, const SkSurfaceProps& props, 31882f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const char text[], size_t byteLength, SkScalar x, SkScalar y, 31982f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const SkIRect& regionClipBounds) { 32027004b7e653a38570d3fd1621ed0107e5443b31ajoshualitt if (context->abandoned()) { 321e55750e3fe12cbae30eebb10ecb6fcf89ffbea9bjoshualitt return; 3226f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon } 323f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 324c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto glyphCache = context->contextPriv().getGlyphCache(); 325c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); 326f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips auto textBlobCache = context->contextPriv().getTextBlobCache(); 327f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 328f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); 32954d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth sk_sp<GrAtlasTextBlob> blob( 330c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->makeDrawTextBlob(textBlobCache, glyphCache, 33154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth *context->caps()->shaderCaps(), paint, 33254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth ComputeScalerContextFlags(target->colorSpaceInfo()), 33354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth viewMatrix, props, text, byteLength, x, y)); 33454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (blob) { 335c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, 33654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth clip, viewMatrix, regionClipBounds, x, y); 337e55750e3fe12cbae30eebb10ecb6fcf89ffbea9bjoshualitt } 33879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 33979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 340f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomonvoid GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, 3416f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon const GrClip& clip, const SkPaint& skPaint, 34282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const SkMatrix& viewMatrix, const SkSurfaceProps& props, 34382f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const char text[], size_t byteLength, const SkScalar pos[], 34482f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon int scalarsPerPosition, const SkPoint& offset, 34582f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon const SkIRect& regionClipBounds) { 346f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); 34727004b7e653a38570d3fd1621ed0107e5443b31ajoshualitt if (context->abandoned()) { 348e55750e3fe12cbae30eebb10ecb6fcf89ffbea9bjoshualitt return; 349f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips } 350f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 351c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto glyphCache = context->contextPriv().getGlyphCache(); 352c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); 353f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips auto textBlobCache = context->contextPriv().getTextBlobCache(); 354f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 35554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob( 356c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips textBlobCache, glyphCache, 35754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth *context->caps()->shaderCaps(), paint, 35854d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, 35954d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth byteLength, pos, scalarsPerPosition, offset)); 36054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (blob) { 361c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, 36254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth clip, viewMatrix, regionClipBounds, offset.fX, offset.fY); 363e55750e3fe12cbae30eebb10ecb6fcf89ffbea9bjoshualitt } 3649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 3659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 36652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomonvoid GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, 367c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, const SkSurfaceProps& props, 368d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby const GrTextUtils::Paint& paint, 369d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 37052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkMatrix& viewMatrix, const char text[], 37152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon size_t byteLength, SkScalar x, SkScalar y) { 37252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(byteLength == 0 || text != nullptr); 37352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 37452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // nothing to draw 37552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (text == nullptr || byteLength == 0) { 37652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return; 37752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 37852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 37952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Ensure the blob is set for bitmaptext 38052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon blob->setHasBitmap(); 38152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 38254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { 383c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix, 384c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth text, byteLength, x, y); 38554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth return; 38654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 387caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips 388caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips sk_sp<GrTextStrike> currStrike; 38952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); 39052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkFindAndPlaceGlyph::ProcessText(paint.skPaint().getTextEncoding(), text, byteLength, {x, y}, 39152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon viewMatrix, paint.skPaint().getTextAlign(), cache, 39252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 39352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon position += rounding; 394c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, 395c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth glyph, SkScalarFloorToScalar(position.fX), 396c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkScalarFloorToScalar(position.fY), 397f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth paint.filteredPremulColor(), cache, 398f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SK_Scalar1); 39952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon }); 40052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 40152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache::AttachCache(cache); 40252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 40352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 40452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomonvoid GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, 405c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, const SkSurfaceProps& props, 40652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const GrTextUtils::Paint& paint, 407d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 408d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby const SkMatrix& viewMatrix, 40952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const char text[], size_t byteLength, const SkScalar pos[], 410c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth int scalarsPerPosition, const SkPoint& offset) { 41152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(byteLength == 0 || text != nullptr); 41252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 41352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 41452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // nothing to draw 41552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (text == nullptr || byteLength == 0) { 41652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return; 41752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 41852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 41952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Ensure the blob is set for bitmaptext 42052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon blob->setHasBitmap(); 42152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 42254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { 423c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DrawBmpPosTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, 424c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); 42554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth return; 42654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 42754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 428caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips sk_sp<GrTextStrike> currStrike; 42952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); 43052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkFindAndPlaceGlyph::ProcessPosText( 43152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon paint.skPaint().getTextEncoding(), text, byteLength, offset, viewMatrix, pos, 43252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon scalarsPerPosition, paint.skPaint().getTextAlign(), cache, 43352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 43452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon position += rounding; 435c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, 436c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkScalarFloorToScalar(position.fX), 437c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkScalarFloorToScalar(position.fY), 438c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth paint.filteredPremulColor(), cache, SK_Scalar1); 43952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon }); 44052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 44152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache::AttachCache(cache); 44252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 44352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 44454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verthvoid GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex, 445c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 446c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkSurfaceProps& props, 447c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const GrTextUtils::Paint& origPaint, 448c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalerContextFlags scalerContextFlags, 449c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkMatrix& viewMatrix, const char text[], 45054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth size_t byteLength, SkScalar x, SkScalar y) { 45154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth // nothing to draw 45254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (text == nullptr || byteLength == 0) { 45354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth return; 45454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 45554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 45654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 457c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint pathPaint(origPaint); 458c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth pathPaint.setStyle(SkPaint::kFill_Style); 459c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth pathPaint.setPathEffect(nullptr); 46054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 461c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true); 462080a928a249115ec425771dd055682edf74d5258Jim Van Verth FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint, glyphCache, iter.getPathScale()); 463c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 464c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkGlyph* iterGlyph; 46554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const SkPath* iterPath; 46654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth SkScalar xpos = 0; 467c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const char* lastText = text; 468c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth while (iter.next(&iterGlyph, &iterPath, &xpos)) { 469c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (iterGlyph) { 470c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint pos = SkPoint::Make(xpos + x, y); 471c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fallbackTextHelper.appendText(*iterGlyph, iter.getText() - lastText, lastText, pos); 472c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } else if (iterPath) { 47354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth blob->appendPathGlyph(runIndex, *iterPath, xpos + x, y, iter.getPathScale(), false); 47454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 475c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth lastText = iter.getText(); 47654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 477c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 478c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags); 47954d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth} 48054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 48154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verthvoid GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runIndex, 482c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 48354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const SkSurfaceProps& props, 48454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const GrTextUtils::Paint& origPaint, 485c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalerContextFlags scalerContextFlags, 486c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkMatrix& viewMatrix, 48754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const char text[], size_t byteLength, 48854d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const SkScalar pos[], int scalarsPerPosition, 489c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkPoint& offset) { 49054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 49154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 49254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth // nothing to draw 49354d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (text == nullptr || byteLength == 0) { 49454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth return; 49554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 49654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 49754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth // setup our std paint, in hopes of getting hits in the cache 498c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint pathPaint(origPaint); 499c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalar matrixScale = pathPaint.setupForAsPaths(); 500080a928a249115ec425771dd055682edf74d5258Jim Van Verth FallbackTextHelper fallbackTextHelper(viewMatrix, origPaint, glyphCache, matrixScale); 50154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 50254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 503c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth pathPaint.setStyle(SkPaint::kFill_Style); 504c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth pathPaint.setPathEffect(nullptr); 50554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 506c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(pathPaint.getTextEncoding(), 507c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth pathPaint.isDevKernText(), 508c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth true); 509c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkAutoGlyphCache autoCache(pathPaint, &props, nullptr); 51054d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth SkGlyphCache* cache = autoCache.getCache(); 51154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 51254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const char* stop = text + byteLength; 513c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const char* lastText = text; 514c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkTextAlignProc alignProc(pathPaint.getTextAlign()); 51554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 51654d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 51754d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth while (text < stop) { 51854d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth const SkGlyph& glyph = glyphCacheProc(cache, &text); 51954d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth if (glyph.fWidth) { 520c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint tmsLoc; 521c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth tmsProc(pos, &tmsLoc); 522c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint loc; 523c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth alignProc(tmsLoc, glyph, &loc); 524c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 525c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fallbackTextHelper.appendText(glyph, text - lastText, lastText, loc); 526c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } else { 527c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkPath* path = cache->findPath(glyph); 528c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (path) { 529c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth blob->appendPathGlyph(runIndex, *path, loc.fX, loc.fY, matrixScale, false); 530c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 53154d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 53254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 533c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth lastText = text; 53454d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth pos += scalarsPerPosition; 53554d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth } 536c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 537c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags); 53854d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth} 53954d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 54052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomonvoid GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, 541caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips GrGlyphCache* grGlyphCache, 542caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips sk_sp<GrTextStrike>* strike, 543c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, 544c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrColor color, SkGlyphCache* skGlyphCache, 545c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkScalar textRatio) { 54652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!*strike) { 547c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips *strike = grGlyphCache->getStrike(skGlyphCache); 54852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 54952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 55052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), 55152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skGlyph.getSubXFixed(), 55252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skGlyph.getSubYFixed(), 55352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon GrGlyph::kCoverage_MaskStyle); 554c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache); 55552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!glyph) { 55652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return; 55752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 55852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 559c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkASSERT(skGlyph.fWidth == glyph->width()); 560c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth SkASSERT(skGlyph.fHeight == glyph->height()); 561c65b65dd816b7a9fbd148f577f0271cd555c4df6Jim Van Verth 562f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft); 563f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar dy = SkIntToScalar(glyph->fBounds.fTop); 564f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar width = SkIntToScalar(glyph->fBounds.width()); 565f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar height = SkIntToScalar(glyph->fBounds.height()); 56652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 567f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth dx *= textRatio; 568f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth dy *= textRatio; 569f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth width *= textRatio; 570f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth height *= textRatio; 57152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 572f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height); 57352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 574c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy, 575f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth textRatio, true); 57652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 57752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 578af597481143ca4b17884360604be954a71cc34cfBrian Salomonbool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, 57952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkSurfaceProps& props, 580af597481143ca4b17884360604be954a71cc34cfBrian Salomon const GrShaderCaps& caps) const { 58152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!viewMatrix.hasPerspective()) { 58252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar maxScale = viewMatrix.getMaxScale(); 58352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar scaledTextSize = maxScale * skPaint.getTextSize(); 58452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Hinted text looks far better at small resolutions 58552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Scaling up beyond 2x yields undesireable artifacts 586af597481143ca4b17884360604be954a71cc34cfBrian Salomon if (scaledTextSize < fMinDistanceFieldFontSize || 587af597481143ca4b17884360604be954a71cc34cfBrian Salomon scaledTextSize > fMaxDistanceFieldFontSize) { 58852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return false; 58952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 59052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 59152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon bool useDFT = props.isUseDeviceIndependentFonts(); 59252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon#if SK_FORCE_DISTANCE_FIELD_TEXT 59352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon useDFT = true; 59452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon#endif 59552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 59652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!useDFT && scaledTextSize < kLargeDFFontSize) { 59752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return false; 59852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 59952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 60052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 6018ad91a9bf896d728b905124847d74787aac698a7Mike Reed // mask filters modify alpha, which doesn't translate well to distance 6028ad91a9bf896d728b905124847d74787aac698a7Mike Reed if (skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { 60352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return false; 60452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 60552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 60652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // TODO: add some stroking support 60752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (skPaint.getStyle() != SkPaint::kFill_Style) { 60852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return false; 60952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 61052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 61152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return true; 61252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 61352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 614af597481143ca4b17884360604be954a71cc34cfBrian Salomonvoid GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, 61552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint* skPaint, 61652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar* textRatio, 617af597481143ca4b17884360604be954a71cc34cfBrian Salomon const SkMatrix& viewMatrix) const { 61852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar textSize = skPaint->getTextSize(); 61952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar scaledTextSize = textSize; 62052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 62152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (viewMatrix.hasPerspective()) { 62252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // for perspective, we simply force to the medium size 62352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // TODO: compute a size based on approximate screen area 62452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon scaledTextSize = kMediumDFFontLimit; 62552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } else { 62652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar maxScale = viewMatrix.getMaxScale(); 62752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // if we have non-unity scale, we need to choose our base text size 62852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // based on the SkPaint's text size multiplied by the max scale factor 62952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? 63052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { 63152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon scaledTextSize *= maxScale; 63252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 63352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 63452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 63552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // We have three sizes of distance field text, and within each size 'bucket' there is a floor 63652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // and ceiling. A scale outside of this range would require regenerating the distance fields 63752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar dfMaskScaleFloor; 63852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar dfMaskScaleCeil; 63952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (scaledTextSize <= kSmallDFFontLimit) { 640af597481143ca4b17884360604be954a71cc34cfBrian Salomon dfMaskScaleFloor = fMinDistanceFieldFontSize; 64152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon dfMaskScaleCeil = kSmallDFFontLimit; 64252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon *textRatio = textSize / kSmallDFFontSize; 64352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); 64452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } else if (scaledTextSize <= kMediumDFFontLimit) { 64552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon dfMaskScaleFloor = kSmallDFFontLimit; 64652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon dfMaskScaleCeil = kMediumDFFontLimit; 64752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon *textRatio = textSize / kMediumDFFontSize; 64852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); 64952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } else { 65052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon dfMaskScaleFloor = kMediumDFFontLimit; 651af597481143ca4b17884360604be954a71cc34cfBrian Salomon dfMaskScaleCeil = fMaxDistanceFieldFontSize; 65252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon *textRatio = textSize / kLargeDFFontSize; 65352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); 65452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 65552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 65652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Because there can be multiple runs in the blob, we want the overall maxMinScale, and 65752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale 65852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can 65952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // tolerate before we'd have to move to a large mip size. When we actually test these values 66052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test 66152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // against these values to decide if we can reuse or not(ie, will a given scale change our mip 66252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // level) 66352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); 66452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); 66552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 66652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setAntiAlias(true); 66752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setLCDRenderText(false); 66852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setAutohinted(false); 66952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setHinting(SkPaint::kNormal_Hinting); 67052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skPaint->setSubpixelText(true); 67152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 67252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 673af597481143ca4b17884360604be954a71cc34cfBrian Salomonvoid GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex, 674c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, const SkSurfaceProps& props, 675d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby const GrTextUtils::Paint& paint, 676d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 67752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkMatrix& viewMatrix, const char text[], 678af597481143ca4b17884360604be954a71cc34cfBrian Salomon size_t byteLength, SkScalar x, SkScalar y) const { 67952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(byteLength == 0 || text != nullptr); 68052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 68152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // nothing to draw 68252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (text == nullptr || byteLength == 0) { 68352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return; 68452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 68552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 68652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkPaint& skPaint = paint.skPaint(); 68752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint::GlyphCacheProc glyphCacheProc = 68852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), skPaint.isDevKernText(), true); 68952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkAutoDescriptor desc; 69052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalerContextEffects effects; 69152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // We apply the fake-gamma by altering the distance in the shader, so we ignore the 69252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). 693980a48de64baf2f974f6c99096391280d1c1d22cHerb Derby SkScalerContext::CreateDescriptorAndEffectsUsingPaint( 694980a48de64baf2f974f6c99096391280d1c1d22cHerb Derby skPaint, &props, SkScalerContextFlags::kNone, nullptr, &desc, &effects); 69552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache* origPaintCache = 69652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache::DetachCache(skPaint.getTypeface(), effects, desc.getDesc()); 69752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 69852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkTArray<SkScalar> positions; 69952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 70052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const char* textPtr = text; 70152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar stopX = 0; 70252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar stopY = 0; 70352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar origin = 0; 70452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon switch (skPaint.getTextAlign()) { 70552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon case SkPaint::kRight_Align: origin = SK_Scalar1; break; 70652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon case SkPaint::kCenter_Align: origin = SK_ScalarHalf; break; 70752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon case SkPaint::kLeft_Align: origin = 0; break; 70852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 70952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 71052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkAutoKern autokern; 71152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const char* stop = text + byteLength; 71252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon while (textPtr < stop) { 71352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // don't need x, y here, since all subpixel variants will have the 71452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // same advance 71552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr); 71652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 71752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar width = SkFloatToScalar(glyph.fAdvanceX) + autokern.adjust(glyph); 71852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon positions.push_back(stopX + origin * width); 71952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 72052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar height = SkFloatToScalar(glyph.fAdvanceY); 72152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon positions.push_back(stopY + origin * height); 72252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 72352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon stopX += width; 72452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon stopY += height; 72552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 72652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(textPtr == stop); 72752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 72852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache::AttachCache(origPaintCache); 72952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 73052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // now adjust starting point depending on alignment 73152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar alignX = stopX; 73252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar alignY = stopY; 73352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { 73452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon alignX = SkScalarHalf(alignX); 73552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon alignY = SkScalarHalf(alignY); 73652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) { 73752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon alignX = 0; 73852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon alignY = 0; 73952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 74052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon x -= alignX; 74152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon y -= alignY; 74252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPoint offset = SkPoint::Make(x, y); 74352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 744c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips this->drawDFPosText(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix, 745af597481143ca4b17884360604be954a71cc34cfBrian Salomon text, byteLength, positions.begin(), 2, offset); 74652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 74752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 748af597481143ca4b17884360604be954a71cc34cfBrian Salomonvoid GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, 749c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, const SkSurfaceProps& props, 750d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby const GrTextUtils::Paint& paint, 751d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby SkScalerContextFlags scalerContextFlags, 75252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkMatrix& viewMatrix, const char text[], 75352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon size_t byteLength, const SkScalar pos[], 754af597481143ca4b17884360604be954a71cc34cfBrian Salomon int scalarsPerPosition, const SkPoint& offset) const { 75552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(byteLength == 0 || text != nullptr); 75652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 75752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 75852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // nothing to draw 75952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (text == nullptr || byteLength == 0) { 76052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon return; 76152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 76252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 763b5086961f335d6757a88ce7507c445485aaba2e6Brian Salomon bool hasWCoord = viewMatrix.hasPerspective() || fDistanceFieldVerticesAlwaysHaveW; 764b5086961f335d6757a88ce7507c445485aaba2e6Brian Salomon 76552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // Setup distance field paint and text ratio 76652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar textRatio; 76752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint dfPaint(paint); 768af597481143ca4b17884360604be954a71cc34cfBrian Salomon this->initDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); 76952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon blob->setHasDistanceField(); 77052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), 7715c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.skPaint().isAntiAlias(), hasWCoord); 77252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 773080a928a249115ec425771dd055682edf74d5258Jim Van Verth FallbackTextHelper fallbackTextHelper(viewMatrix, paint, glyphCache, textRatio); 774c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 775caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips sk_sp<GrTextStrike> currStrike; 77652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 77752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // We apply the fake-gamma by altering the distance in the shader, so we ignore the 77852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). 77952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache* cache = 780d8327a8c8bad870112b574c4533270370f5c1ccfHerb Derby blob->setupCache(runIndex, props, SkScalerContextFlags::kNone, dfPaint, nullptr); 78152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint::GlyphCacheProc glyphCacheProc = 78252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), dfPaint.isDevKernText(), true); 78352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 78452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const char* stop = text + byteLength; 78552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 786f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkPaint::Align align = dfPaint.getTextAlign(); 787f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar alignMul = SkPaint::kCenter_Align == align ? SK_ScalarHalf : 788f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth (SkPaint::kRight_Align == align ? SK_Scalar1 : 0); 789f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth while (text < stop) { 790f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth const char* lastText = text; 791f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth // the last 2 parameters are ignored 792f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth const SkGlyph& glyph = glyphCacheProc(cache, &text); 793f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth 794f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth if (glyph.fWidth) { 795c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint glyphPos(offset); 796c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth glyphPos.fX += pos[0] - SkFloatToScalar(glyph.fAdvanceX) * alignMul * textRatio; 797c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth glyphPos.fY += (2 == scalarsPerPosition ? pos[1] : 0) - 798c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio; 799f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth 800f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth if (glyph.fMaskFormat != SkMask::kARGB32_Format) { 801c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips DfAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, glyphPos.fX, 802c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth glyphPos.fY, paint.filteredPremulColor(), cache, textRatio); 803f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth } else { 804f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth // can't append color glyph to SDF batch, send to fallback 805c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fallbackTextHelper.appendText(glyph, SkToInt(text - lastText), lastText, glyphPos); 80652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 80752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 808f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth pos += scalarsPerPosition; 80952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 81052db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 81152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkGlyphCache::AttachCache(cache); 81254d9c889fb6aca043a7b005d61de4e0e65a3ae53Jim Van Verth 813c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, paint, scalerContextFlags); 81452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 81552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 816f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth// TODO: merge with BmpAppendGlyph 817f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verthvoid GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, 818caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips GrGlyphCache* grGlyphCache, sk_sp<GrTextStrike>* strike, 81952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, 820c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrColor color, SkGlyphCache* skGlyphCache, 821f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkScalar textRatio) { 82252db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!*strike) { 823c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips *strike = grGlyphCache->getStrike(skGlyphCache); 82452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 82552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 82652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), 82752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skGlyph.getSubXFixed(), 82852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon skGlyph.getSubYFixed(), 82952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon GrGlyph::kDistance_MaskStyle); 830c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache); 83152db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon if (!glyph) { 832f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth return; 83352db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon } 83452db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 83552db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); 83652db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); 83752db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2 * SK_DistanceFieldInset); 83852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2 * SK_DistanceFieldInset); 83952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 840f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth dx *= textRatio; 841f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth dy *= textRatio; 842f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth width *= textRatio; 843f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth height *= textRatio; 844f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height); 845f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth 846c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy, 847f4c13166de2ad3c67a4a391d8595b5c8fa04ad4dJim Van Verth textRatio, false); 84852db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon} 84952db9400d74dcade2fa94ff08d0e583151144dd4Brian Salomon 85079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt/////////////////////////////////////////////////////////////////////////////////////////////////// 85179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 852c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verthvoid GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, int count, 853c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const char* text, SkPoint glyphPos) { 854c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio; 855c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (!fUseScaledFallback) { 856c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalar scaledGlyphSize = maxDim * fMaxScale; 857c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) { 858c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fUseScaledFallback = true; 859c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 860c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 861c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 862c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fFallbackTxt.append(count, text); 863c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (fUseScaledFallback) { 864080a928a249115ec425771dd055682edf74d5258Jim Van Verth // If there's a glyph in the font that's particularly large, it's possible 865080a928a249115ec425771dd055682edf74d5258Jim Van Verth // that fScaledFallbackTextSize may end up minimizing too much. We'd rather skip 866080a928a249115ec425771dd055682edf74d5258Jim Van Verth // that glyph than make the others pixelated, so we set a minimum size of half the 867080a928a249115ec425771dd055682edf74d5258Jim Van Verth // maximum text size to avoid this case. 868080a928a249115ec425771dd055682edf74d5258Jim Van Verth SkScalar glyphTextSize = SkTMax(SkScalarFloorToScalar(fMaxTextSize*fTextSize / maxDim), 869080a928a249115ec425771dd055682edf74d5258Jim Van Verth 0.5f*fMaxTextSize); 870c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fScaledFallbackTextSize = SkTMin(glyphTextSize, fScaledFallbackTextSize); 871c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 872c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth *fFallbackPos.append() = glyphPos; 873c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth} 874c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 875c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verthvoid GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int runIndex, 876c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrGlyphCache* glyphCache, 877c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkSurfaceProps& props, 878c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const GrTextUtils::Paint& paint, 879c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalerContextFlags scalerContextFlags) { 880c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (fFallbackTxt.count()) { 881c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth blob->initOverride(runIndex); 882c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth blob->setHasBitmap(); 883c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkGlyphCache* cache = nullptr; 884c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkPaint& skPaint = paint.skPaint(); 885c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint::GlyphCacheProc glyphCacheProc = 886c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), 887c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth skPaint.isDevKernText(), true); 888c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkColor textColor = paint.filteredPremulColor(); 889c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalar textRatio = SK_Scalar1; 890c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth fViewMatrix.mapPoints(fFallbackPos.begin(), fFallbackPos.count()); 891c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth if (fUseScaledFallback) { 892c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth // Set up paint and matrix to scale glyphs 893c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPaint scaledPaint(skPaint); 894c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth scaledPaint.setTextSize(fScaledFallbackTextSize); 895c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth // remove maxScale from viewMatrix and move it into textRatio 896c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth // this keeps the base glyph size consistent regardless of matrix scale 897c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkMatrix modMatrix(fViewMatrix); 898c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkScalar invScale = SkScalarInvert(fMaxScale); 899c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth modMatrix.preScale(invScale, invScale); 900c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth textRatio = fTextSize * fMaxScale / fScaledFallbackTextSize; 901c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth cache = blob->setupCache(runIndex, props, scalerContextFlags, scaledPaint, 902c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth &modMatrix); 903c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } else { 904c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, 905c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth &fViewMatrix); 906c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 907c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 908caf1ebb95f7fea81d416b81beb4b46c25643c714Robert Phillips sk_sp<GrTextStrike> currStrike; 909c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const char* text = fFallbackTxt.begin(); 910c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const char* stop = text + fFallbackTxt.count(); 911c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkPoint* glyphPos = fFallbackPos.begin(); 912c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth while (text < stop) { 913c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth const SkGlyph& glyph = glyphCacheProc(cache, &text); 914c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, 915c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth glyphPos->fX, glyphPos->fY, textColor, 916c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth cache, textRatio); 917c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth glyphPos++; 918c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 919c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 920c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth SkGlyphCache::AttachCache(cache); 921c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth } 922c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth} 923c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 924c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 925c401bb9c14332aa6c4c19d7f299f1512bf07c6a2Jim Van Verth 9266f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 92779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 928f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon#include "GrRenderTargetContext.h" 929f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon 93044acb5b09bb87163bc9c010be915b3f33e3157ebBrian SalomonGR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) { 93179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt static uint32_t gContextID = SK_InvalidGenID; 932af597481143ca4b17884360604be954a71cc34cfBrian Salomon static std::unique_ptr<GrAtlasTextContext> gTextContext; 933fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); 93479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 93579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (context->uniqueID() != gContextID) { 93679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt gContextID = context->uniqueID(); 937af597481143ca4b17884360604be954a71cc34cfBrian Salomon gTextContext = GrAtlasTextContext::Make(GrAtlasTextContext::Options()); 93879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 93979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 9401105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman // Setup dummy SkPaint / GrPaint / GrRenderTargetContext 941ec8f8b064340b030fc4ce10f6cbbc3d6f63b946fBrian Osman sk_sp<GrRenderTargetContext> rtc(context->makeDeferredRenderTargetContext( 9421105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman SkBackingFit::kApprox, 1024, 1024, kRGBA_8888_GrPixelConfig, nullptr)); 9438fe485b793f6b3c286700988138e1395b0d33487brianosman 9446c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 94544acb5b09bb87163bc9c010be915b3f33e3157ebBrian Salomon 94644acb5b09bb87163bc9c010be915b3f33e3157ebBrian Salomon // Because we the GrTextUtils::Paint requires an SkPaint for font info, we ignore the GrPaint 94744acb5b09bb87163bc9c010be915b3f33e3157ebBrian Salomon // param. 94879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkPaint skPaint; 9496f1d36cc54dc635f5e4d0f925ef79c14914342bbBrian Salomon skPaint.setColor(random->nextU()); 95079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setLCDRenderText(random->nextBool()); 95179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); 95279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setSubpixelText(random->nextBool()); 9534cbb6e6d551e8bea2c040b1aa9dce253cffb9af0Brian Salomon GrTextUtils::Paint utilsPaint(&skPaint, &rtc->colorSpaceInfo()); 95479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 95579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char* text = "The quick brown fox jumps over the lazy dog."; 95679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt int textLen = (int)strlen(text); 95779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 958b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt // create some random x/y offsets, including negative offsets 959b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt static const int kMaxTrans = 1024; 960b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt int xPos = (random->nextU() % 2) * 2 - 1; 961b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt int yPos = (random->nextU() % 2) * 2 - 1; 962b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt int xInt = (random->nextU() % kMaxTrans) * xPos; 963b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt int yInt = (random->nextU() % kMaxTrans) * yPos; 964b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt SkScalar x = SkIntToScalar(xInt); 965b8d864902b4c9e893cbdc62eb77c4d49416a2bc1joshualitt SkScalar y = SkIntToScalar(yInt); 9669d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 967c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto glyphCache = context->contextPriv().getGlyphCache(); 968c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); 969f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips 97009d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon // right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to 97109d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon // test the text op with this unit test, that is okay. 972af597481143ca4b17884360604be954a71cc34cfBrian Salomon sk_sp<GrAtlasTextBlob> blob(gTextContext->makeDrawTextBlob( 973c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips context->contextPriv().getTextBlobCache(), glyphCache, 97444acb5b09bb87163bc9c010be915b3f33e3157ebBrian Salomon *context->caps()->shaderCaps(), utilsPaint, 9755ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon GrAtlasTextContext::kTextBlobOpScalerContextFlags, viewMatrix, gSurfaceProps, text, 9765ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon static_cast<size_t>(textLen), x, y)); 9775ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon 97844acb5b09bb87163bc9c010be915b3f33e3157ebBrian Salomon return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, gSurfaceProps, 979c4039ea466d39ede0ea44fc7a18f1174f893f11dRobert Phillips gTextContext->dfAdjustTable(), restrictedAtlasManager, 980f18b1d88aa98f81d2c115a59d887265fea63f876Brian Salomon rtc->textTarget()); 98179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 98279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 98379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt#endif 984