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