17c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt/*
27c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt * Copyright 2015 Google Inc.
37c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt *
47c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt * Use of this source code is governed by a BSD-style license that can be
57c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt * found in the LICENSE file.
67c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt */
77c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
8f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon#include "GrAtlasGlyphCache.h"
9cabe20cafd5f091a68bbc2c0c48755ba9b61b0b7kkinnunen#include "GrContext.h"
107c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#include "GrGpu.h"
117c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#include "GrRectanizer.h"
127c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#include "GrSurfacePriv.h"
1395e3c058ef633782f7549e9e1c2727d60dbc8ee5Hal Canary#include "SkAutoMalloc.h"
147c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#include "SkString.h"
157c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
167c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#include "SkDistanceFieldGen.h"
178cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang#include "GrDistanceFieldGenFromVector.h"
187c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
19f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomonbool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
2062db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt    int index = MaskFormatToAtlasIndex(format);
2162db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt    if (!fAtlases[index]) {
2286dc226b6024c61fa711475aa9fc2cfd53811ccbbrianosman        GrPixelConfig config = MaskFormatToPixelConfig(format, *fContext->caps());
23da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt        int width = fAtlasConfigs[index].fWidth;
24da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt        int height = fAtlasConfigs[index].fHeight;
25da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt        int numPlotsX = fAtlasConfigs[index].numPlotsX();
26da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt        int numPlotsY = fAtlasConfigs[index].numPlotsY();
27da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt
28256c37bc9ea2a0420b8ac1084f6d645aaeb919f0Robert Phillips        fAtlases[index] = GrDrawOpAtlas::Make(
2932f2818c9d10090efeea62ccc211d48a33322dfbRobert Phillips                fContext, config, width, height, numPlotsX, numPlotsY,
3032f2818c9d10090efeea62ccc211d48a33322dfbRobert Phillips                &GrAtlasGlyphCache::HandleEviction, (void*)this);
31b356cbc765468e2594fca9ec6e5476a3da145d26joshualitt        if (!fAtlases[index]) {
3262db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt            return false;
337c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
347c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
3562db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt    return true;
3662db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt}
3762db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt
386d342285a4546b54cb17570aae7eeb8a123c81aeEric KarlGrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes)
396d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl        : fContext(context), fPreserveStrike(nullptr) {
406d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    // Calculate RGBA size. Must be between 1024 x 512 and MaxTextureSize x MaxTextureSize / 2
416d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int log2MaxTextureSize = log2(context->caps()->maxTextureSize());
426d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int log2MaxDim = 10;
436d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
446d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl        int maxDim = 1 << log2MaxDim;
456d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl        int minDim = 1 << (log2MaxDim - 1);
46da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt
476d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl        if (maxDim * minDim * 4 >= maxTextureBytes) break;
486d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    }
496d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl
506d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int log2MinDim = log2MaxDim - 1;
516d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int maxDim = 1 << log2MaxDim;
526d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int minDim = 1 << log2MinDim;
536d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    // Plots are either 256 or 512.
546d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2)));
556d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    int minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3)));
566d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl
576d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    // Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8
586d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    // format is already very compact.
596d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fWidth = maxDim;
606d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fHeight = maxDim;
616d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fLog2Width = log2MaxDim;
626d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fLog2Height = log2MaxDim;
636d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = maxPlot;
646d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = minPlot;
65da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt
666d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    // A565 and ARGB use maxDim x minDim.
676d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fWidth = minDim;
686d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fHeight = maxDim;
696d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fLog2Width = log2MinDim;
706d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fLog2Height = log2MaxDim;
716d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = minPlot;
726d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = minPlot;
73da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt
746d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fWidth = minDim;
756d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim;
766d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fLog2Width = log2MinDim;
776d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fLog2Height = log2MaxDim;
786d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot;
796d342285a4546b54cb17570aae7eeb8a123c81aeEric Karl    fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot;
807c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
817c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
82f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian SalomonGrAtlasGlyphCache::~GrAtlasGlyphCache() {
83c5fd5c41abd1e50293643c40e11e1f62cd22d3e9bsalomon    StrikeHash::Iter iter(&fCache);
847c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    while (!iter.done()) {
85a5f1d5a95a350275c8ea63307d5ceaaccaa0c89bjoshualitt        (*iter).fIsAbandoned = true;
86ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt        (*iter).unref();
877c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        ++iter;
887c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
897c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
907c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
91f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomonvoid GrAtlasGlyphCache::freeAll() {
92c5fd5c41abd1e50293643c40e11e1f62cd22d3e9bsalomon    StrikeHash::Iter iter(&fCache);
937c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    while (!iter.done()) {
94a5f1d5a95a350275c8ea63307d5ceaaccaa0c89bjoshualitt        (*iter).fIsAbandoned = true;
95ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt        (*iter).unref();
967c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        ++iter;
977c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
987c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    fCache.rewind();
997c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    for (int i = 0; i < kMaskFormatCount; ++i) {
10096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fAtlases[i] = nullptr;
1017c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
1027c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
1037c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
1042ee084e73056b0ad76b721017f576168b7306da3Brian Salomonvoid GrAtlasGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
105f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon    GrAtlasGlyphCache* fontCache = reinterpret_cast<GrAtlasGlyphCache*>(ptr);
1067c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
107c5fd5c41abd1e50293643c40e11e1f62cd22d3e9bsalomon    StrikeHash::Iter iter(&fontCache->fCache);
1087c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    for (; !iter.done(); ++iter) {
109f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon        GrAtlasTextStrike* strike = &*iter;
1107c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        strike->removeID(id);
1117c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
1127c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        // clear out any empty strikes.  We will preserve the strike whose call to addToAtlas
1137c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        // triggered the eviction
1147c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        if (strike != fontCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) {
115f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon            fontCache->fCache.remove(GrAtlasTextStrike::GetKey(*strike));
116ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt            strike->fIsAbandoned = true;
117ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt            strike->unref();
1187c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
1197c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
1207c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
1217c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
12231c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#ifdef SK_DEBUG
12331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "GrContextPriv.h"
12431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "GrSurfaceProxy.h"
12531c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "GrSurfaceContext.h"
12631c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "GrTextureProxy.h"
12731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
12831c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "SkBitmap.h"
12931c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "SkImageEncoder.h"
13031c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include "SkStream.h"
13131c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#include <stdio.h>
13231c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
13331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips/**
13431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips  * Write the contents of the surface proxy to a PNG. Returns true if successful.
13531c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips  * @param filename      Full path to desired file
13631c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips  */
13731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillipsstatic bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) {
13877b3f32936dd069fa6a27f870b3b30035733d940Robert Phillips    if (!sProxy) {
13977b3f32936dd069fa6a27f870b3b30035733d940Robert Phillips        return false;
14077b3f32936dd069fa6a27f870b3b30035733d940Robert Phillips    }
141c949ce9d808dbf7c2db7dc0b85271969ba46b69aRobert Phillips
142c949ce9d808dbf7c2db7dc0b85271969ba46b69aRobert Phillips    SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(),
143c949ce9d808dbf7c2db7dc0b85271969ba46b69aRobert Phillips                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
14431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    SkBitmap bm;
145c949ce9d808dbf7c2db7dc0b85271969ba46b69aRobert Phillips    if (!bm.tryAllocPixels(ii)) {
14631c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        return false;
14731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    }
14831c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
14931c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
1502c86249465c28a532c8be55b6ba497021e3110ecRobert Phillips                                                                            sk_ref_sp(sProxy),
1512c86249465c28a532c8be55b6ba497021e3110ecRobert Phillips                                                                            nullptr));
152f200a90f3e58ce20753420cadced850d7d00dca1Robert Phillips    if (!sContext || !sContext->asTextureProxy()) {
15331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        return false;
15431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    }
15531c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
156c949ce9d808dbf7c2db7dc0b85271969ba46b69aRobert Phillips    bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0);
15731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    if (!result) {
15831c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        SkDebugf("------ failed to read pixels for %s\n", filename);
15931c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        return false;
16031c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    }
16131c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
16231c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    // remove any previous version of this file
16331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    remove(filename);
16431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
16531c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    SkFILEWStream file(filename);
16631c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    if (!file.isValid()) {
16731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        SkDebugf("------ failed to create file: %s\n", filename);
16831c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        remove(filename);   // remove any partial file
16931c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        return false;
17031c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    }
17131c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
17231c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
17331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        SkDebugf("------ failed to encode %s\n", filename);
17431c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        remove(filename);   // remove any partial file
17531c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips        return false;
17631c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    }
17731c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
17831c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips    return true;
17931c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips}
18031c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
181f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomonvoid GrAtlasGlyphCache::dump() const {
1827c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    static int gDumpCount = 0;
1837c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    for (int i = 0; i < kMaskFormatCount; ++i) {
1847c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        if (fAtlases[i]) {
18532f2818c9d10090efeea62ccc211d48a33322dfbRobert Phillips            sk_sp<GrTextureProxy> proxy = fAtlases[i]->getProxy();
18632f2818c9d10090efeea62ccc211d48a33322dfbRobert Phillips            if (proxy) {
1877c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt                SkString filename;
1887c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#ifdef SK_BUILD_FOR_ANDROID
1897c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt                filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
1907c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#else
1917c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt                filename.printf("fontcache_%d%d.png", gDumpCount, i);
1927c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt#endif
19331c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips
19432f2818c9d10090efeea62ccc211d48a33322dfbRobert Phillips                save_pixels(fContext, proxy.get(), filename.c_str());
1957c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt            }
1967c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
1977c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
1987c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    ++gDumpCount;
1997c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
20031c2608e859b1f1c25eeea429f5ab2fee1529facRobert Phillips#endif
2017c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
2022ee084e73056b0ad76b721017f576168b7306da3Brian Salomonvoid GrAtlasGlyphCache::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) {
203594f9ed9c9cf0fcbbc2fa111b09d376014314315Ben Wagner    // Delete any old atlases.
204594f9ed9c9cf0fcbbc2fa111b09d376014314315Ben Wagner    // This should be safe to do as long as we are not in the middle of a flush.
205da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt    for (int i = 0; i < kMaskFormatCount; i++) {
206594f9ed9c9cf0fcbbc2fa111b09d376014314315Ben Wagner        fAtlases[i] = nullptr;
207da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt    }
208da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt    memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs));
209da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt}
210da04e0e80a0113e1d838f7406cd8a8d545b8c02bjoshualitt
2117c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt///////////////////////////////////////////////////////////////////////////////
2127c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
213c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic inline GrMaskFormat get_packed_glyph_mask_format(const SkGlyph& glyph) {
214c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
215c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    switch (format) {
216c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        case SkMask::kBW_Format:
217c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            // fall through to kA8 -- we store BW glyphs in our 8-bit cache
218c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        case SkMask::kA8_Format:
219c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            return kA8_GrMaskFormat;
220c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        case SkMask::kLCD16_Format:
221c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            return kA565_GrMaskFormat;
222c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        case SkMask::kARGB32_Format:
223c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            return kARGB_GrMaskFormat;
224c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        default:
225c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            SkDEBUGFAIL("unsupported SkMask::Format");
226c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            return kA8_GrMaskFormat;
227c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
228c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
229c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
230c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic inline bool get_packed_glyph_bounds(SkGlyphCache* cache, const SkGlyph& glyph,
231c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                           SkIRect* bounds) {
232c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon#if 1
233c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // crbug:510931
234c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // Retrieving the image from the cache can actually change the mask format.
235c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    cache->findImage(glyph);
236c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon#endif
237c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
238c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
239c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    return true;
240c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
241c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
242c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic inline bool get_packed_glyph_df_bounds(SkGlyphCache* cache, const SkGlyph& glyph,
243c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                              SkIRect* bounds) {
244c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon#if 1
245c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // crbug:510931
246c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // Retrieving the image from the cache can actually change the mask format.
247c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    cache->findImage(glyph);
248c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon#endif
249c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
250c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
251c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
252c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    return true;
253c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
254c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
255c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
256c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon// A8, RGB565, or RGBA8888.
257c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomontemplate <typename INT_TYPE>
258c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic void expand_bits(INT_TYPE* dst,
259c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                        const uint8_t* src,
260c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                        int width,
261c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                        int height,
262c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                        int dstRowBytes,
263c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                        int srcRowBytes) {
264c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    for (int i = 0; i < height; ++i) {
265c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        int rowWritesLeft = width;
266c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        const uint8_t* s = src;
267c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        INT_TYPE* d = dst;
268c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        while (rowWritesLeft > 0) {
269c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            unsigned mask = *s++;
270c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
271c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
272c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            }
273c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        }
274c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
275c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        src += srcRowBytes;
276c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
277c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
278c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
279c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, int width,
280c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                   int height, int dstRB, GrMaskFormat expectedMaskFormat,
281c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                   void* dst) {
282c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(glyph.fWidth == width);
283c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(glyph.fHeight == height);
284c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    const void* src = cache->findImage(glyph);
285c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    if (nullptr == src) {
286c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        return false;
287c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
288c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
289c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // crbug:510931
290c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // Retrieving the image from the cache can actually change the mask format.  This case is very
291c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // uncommon so for now we just draw a clear box for these glyphs.
292c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    if (get_packed_glyph_mask_format(glyph) != expectedMaskFormat) {
293c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
294c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        for (int y = 0; y < height; y++) {
295c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            sk_bzero(dst, width * bpp);
296c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            dst = (char*)dst + dstRB;
297c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        }
298c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        return true;
299c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
300c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
301c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    int srcRB = glyph.rowBytes();
302c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
303c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // check the glyph's format, not the strike's format, and to be able to convert to any of the
304c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // GrMaskFormats.
305c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    if (SkMask::kBW_Format == glyph.fMaskFormat) {
306c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        // expand bits to our mask type
307c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
308c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        switch (expectedMaskFormat) {
309c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            case kA8_GrMaskFormat:{
310c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
311c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                expand_bits(bytes, bits, width, height, dstRB, srcRB);
312c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                break;
313c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            }
314c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            case kA565_GrMaskFormat: {
315c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
316c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                expand_bits(rgb565, bits, width, height, dstRB, srcRB);
317c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                break;
318c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            }
319c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            default:
320c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                SkFAIL("Invalid GrMaskFormat");
321c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        }
322c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    } else if (srcRB == dstRB) {
323c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        memcpy(dst, src, dstRB * height);
324c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    } else {
325c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
326c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        for (int y = 0; y < height; y++) {
327c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            memcpy(dst, src, width * bbp);
328c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            src = (const char*)src + srcRB;
329c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon            dst = (char*)dst + dstRB;
330c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        }
331c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
332c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    return true;
333c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
334c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
335c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomonstatic bool get_packed_glyph_df_image(SkGlyphCache* cache, const SkGlyph& glyph,
336c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                      int width, int height, void* dst) {
337c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
338c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
3398cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang
3408cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang#ifndef SK_USE_LEGACY_DISTANCE_FIELDS
3418cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    const SkPath* path = cache->findPath(glyph);
3428cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    if (nullptr == path) {
343c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        return false;
344c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    }
3458cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang
3468cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    SkDEBUGCODE(SkRect glyphBounds = SkRect::MakeXYWH(glyph.fLeft,
3478cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                                      glyph.fTop,
3488cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                                      glyph.fWidth,
3498cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                                      glyph.fHeight));
3508cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    SkASSERT(glyphBounds.contains(path->getBounds()));
3518cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang
352c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    // now generate the distance field
353c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(dst);
3548cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    SkMatrix drawMatrix;
3558cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    drawMatrix.setTranslate((SkScalar)-glyph.fLeft, (SkScalar)-glyph.fTop);
356478422596eb2521ad6f912d36299df7a36959873rmistry
3578cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    // Generate signed distance field directly from SkPath
3588cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    bool succeed = GrGenerateDistanceFieldFromPath((unsigned char*)dst,
3598cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                           *path, drawMatrix,
3608cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                           width, height, width * sizeof(unsigned char));
3618cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang
3628cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    if (!succeed) {
3638cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang#endif
3648cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        const void* image = cache->findImage(glyph);
3658cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        if (nullptr == image) {
3668cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            return false;
3678cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        }
3688cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang
3698cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        // now generate the distance field
3708cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        SkASSERT(dst);
3718cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
3728cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        if (SkMask::kA8_Format == maskFormat) {
3738cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            // make the distance field from the image
3748cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            SkGenerateDistanceFieldFromA8Image((unsigned char*)dst,
3758cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               (unsigned char*)image,
3768cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               glyph.fWidth, glyph.fHeight,
3778cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               glyph.rowBytes());
3788cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        } else if (SkMask::kBW_Format == maskFormat) {
3798cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            // make the distance field from the image
3808cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            SkGenerateDistanceFieldFromBWImage((unsigned char*)dst,
3818cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               (unsigned char*)image,
3828cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               glyph.fWidth, glyph.fHeight,
3838cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang                                               glyph.rowBytes());
3848cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        } else {
3858cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang            return false;
3868cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang        }
3878cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang#ifndef SK_USE_LEGACY_DISTANCE_FIELDS
3888cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang    }
3898cbb4246e58c97e2ac51087d2708795b3b59f5e9joel.liang#endif
390f93f5151612a4b1adfe1dad0490bd1c01ee73598bsalomon    return true;
391c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon}
392c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
393c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon///////////////////////////////////////////////////////////////////////////////
394c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon
3957c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt/*
3967c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    The text strike is specific to a given font/style/matrix setup, which is
3977c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    represented by the GrHostFontScaler object we are given in getGlyph().
3987c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
3997c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    We map a 32bit glyphID to a GrGlyph record, which in turn points to a
4007c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    atlas and a position within that texture.
4017c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt */
4027c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
403f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian SalomonGrAtlasTextStrike::GrAtlasTextStrike(GrAtlasGlyphCache* owner, const SkDescriptor& key)
404c5fd5c41abd1e50293643c40e11e1f62cd22d3e9bsalomon    : fFontScalerKey(key)
4057c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    , fPool(9/*start allocations at 512 bytes*/)
406f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon    , fAtlasGlyphCache(owner) // no need to ref, it won't go away before we do
407ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt    , fAtlasedGlyphs(0)
408c5fd5c41abd1e50293643c40e11e1f62cd22d3e9bsalomon    , fIsAbandoned(false) {}
4097c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
410f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian SalomonGrAtlasTextStrike::~GrAtlasTextStrike() {
4117c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
4127c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    while (!iter.done()) {
413852f15da7ceb53cfb49b9f728baa6dbc53b27694mtklein        (*iter).reset();
4147c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        ++iter;
4157c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
4167c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
4177c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
418f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian SalomonGrGlyph* GrAtlasTextStrike::generateGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed,
419c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                          SkGlyphCache* cache) {
4207c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    SkIRect bounds;
4217c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(packed)) {
422c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        if (!get_packed_glyph_df_bounds(cache, skGlyph, &bounds)) {
42396fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
4247c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
4257c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    } else {
426c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        if (!get_packed_glyph_bounds(cache, skGlyph, &bounds)) {
42796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
4287c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
4297c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
430c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    GrMaskFormat format = get_packed_glyph_mask_format(skGlyph);
4316c2c2b07ed83e1f83008fac6eb1b62670b1dbdb1joshualitt
4329428a37255586da6d34b86c6ed0d56729dbfd731Herb Derby    GrGlyph* glyph = fPool.make<GrGlyph>();
4337c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    glyph->init(packed, bounds, format);
4347c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    fCache.add(glyph);
4357c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    return glyph;
4367c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
4377c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
4382ee084e73056b0ad76b721017f576168b7306da3Brian Salomonvoid GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
4397c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
4407c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    while (!iter.done()) {
4417c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        if (id == (*iter).fID) {
4422ee084e73056b0ad76b721017f576168b7306da3Brian Salomon            (*iter).fID = GrDrawOpAtlas::kInvalidAtlasID;
4437c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt            fAtlasedGlyphs--;
4447c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt            SkASSERT(fAtlasedGlyphs >= 0);
4457c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
4467c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        ++iter;
4477c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
4487c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
4497c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
450f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomonbool GrAtlasTextStrike::addGlyphToAtlas(GrDrawOp::Target* target,
45150aa15b88ab149952dbc69e849139887e8a82410joshualitt                                        GrGlyph* glyph,
452c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                        SkGlyphCache* cache,
4534f19ca325e8d0122e0a04345272d17e674460806joshualitt                                        GrMaskFormat expectedMaskFormat) {
4547c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    SkASSERT(glyph);
455c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    SkASSERT(cache);
4567c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    SkASSERT(fCache.find(glyph->fPackedID));
4577c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
4584f19ca325e8d0122e0a04345272d17e674460806joshualitt    int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
4597c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
4607c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    size_t size = glyph->fBounds.area() * bytesPerPixel;
46129f8679068ecbd693e123a59b09a5ade3cfde996joshualitt    SkAutoSMalloc<1024> storage(size);
4627c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
463c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon    const SkGlyph& skGlyph = GrToSkGlyph(cache, glyph->fPackedID);
4647c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID)) {
465c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        if (!get_packed_glyph_df_image(cache, skGlyph, glyph->width(), glyph->height(),
466c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                       storage.get())) {
4677c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt            return false;
4687c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
4697c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    } else {
470c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon        if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(),
471c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                    glyph->width() * bytesPerPixel, expectedMaskFormat,
472c2878e23d405e7ae77f6110602ad75ce1f6b941cbsalomon                                    storage.get())) {
4737c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt            return false;
4747c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        }
4757c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
4767c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
477f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon    bool success = fAtlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat,
4787c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt                                               glyph->width(), glyph->height(),
4797c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt                                               storage.get(), &glyph->fAtlasLocation);
4807c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    if (success) {
4812ee084e73056b0ad76b721017f576168b7306da3Brian Salomon        SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID);
4827c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt        fAtlasedGlyphs++;
4837c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    }
4847c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt    return success;
4857c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt}
486