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