1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkGlyphCache.h" 119defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com#include "SkGlyphCache_Globals.h" 12caaf85441ce8a2231c9543088ee7a523328a2419reed@google.com#include "SkGraphics.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPaint.h" 149ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkPath.h" 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplates.h" 16baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com#include "SkTLS.h" 1778341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com#include "SkTypeface.h" 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 196a2b39f2e7680b1300aa16c71e2a9cb31c5277cfreed@google.com//#define SPEW_PURGE_STATUS 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//#define RECORD_HASH_EFFICIENCY 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 22a12ddbbf5a9791687b41c608448353ebc6cfa9cfreed@google.combool gSkSuppressFontCachePurgeSpew; 23a12ddbbf5a9791687b41c608448353ebc6cfa9cfreed@google.com 249defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com// Returns the shared globals 259defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comstatic SkGlyphCache_Globals& getSharedGlobals() { 269defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // we leak this, so we don't incur any shutdown cost of the destructor 279defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals, 289defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com (SkGlyphCache_Globals::kYes_UseMutex)); 299defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return *gGlobals; 309defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 319defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 329defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com// Returns the TLS globals (if set), or the shared globals 339defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comstatic SkGlyphCache_Globals& getGlobals() { 349defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 359defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return tls ? *tls : getSharedGlobals(); 369defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 379defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef RECORD_HASH_EFFICIENCY 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static uint32_t gHashSuccess; 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static uint32_t gHashCollision; 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static void RecordHashSuccess() { 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com gHashSuccess += 1; 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static void RecordHashCollisionIf(bool pred) { 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (pred) { 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com gHashCollision += 1; 51ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t total = gHashSuccess + gHashCollision; 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("Font Cache Hash success rate: %d%%\n", 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 100 * gHashSuccess / total); 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #define RecordHashSuccess() (void)0 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #define RecordHashCollisionIf(pred) (void)0 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define RecordHashCollision() RecordHashCollisionIf(true) 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 65c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com// so we don't grow our arrays a lot 66c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com#define kMinGlyphCount 16 67c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com#define kMinGlyphImageSize (16*2) 68c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com#define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphCount) 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 7042eacd7f693510758d71fdb07805a240d6176372reed@google.comSkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkScalerContext* ctx) 7142eacd7f693510758d71fdb07805a240d6176372reed@google.com : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) { 7278341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com SkASSERT(typeface); 7342eacd7f693510758d71fdb07805a240d6176372reed@google.com SkASSERT(desc); 7442eacd7f693510758d71fdb07805a240d6176372reed@google.com SkASSERT(ctx); 7578341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPrev = fNext = NULL; 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fDesc = desc->copy(); 792f45f0074cf3f265711b74eb3a1d757ae4b2ce02reed@google.com fScalerContext->getFontMetrics(&fFontMetrics); 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // init to 0 so that all of the pointers will be null 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(fGlyphHash, 0, sizeof(fGlyphHash)); 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // init with 0xFF so that the charCode field will be -1, which is invalid 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash)); 85ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 86c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com fMemoryUsed = sizeof(*this); 87ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 88c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com fGlyphArray.setReserve(kMinGlyphCount); 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAuxProcList = NULL; 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkGlyphCache::~SkGlyphCache() { 94c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com#if 0 95c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com { 96c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); 97c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t glyphAlloc = fGlyphAlloc.totalCapacity(); 98c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t glyphHashUsed = 0; 99c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t uniHashUsed = 0; 100c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com for (int i = 0; i < kHashCount; ++i) { 101c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0; 102c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharToGlyphHash[0]) : 0; 103c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com } 104c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); 105c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com size_t imageUsed = 0; 106c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com for (int i = 0; i < fGlyphArray.count(); ++i) { 107c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com const SkGlyph& g = *fGlyphArray[i]; 108c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com if (g.fImage) { 109c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com imageUsed += g.fHeight * g.rowBytes(); 110c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com } 111c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com } 112c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com 113c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com printf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, glyphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n", 114c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), glyphHashUsed, sizeof(fCharToGlyphHash), uniHashUsed); 1151bda0434d06e2cff123683fcf0b01bf30f33ab7dskia.committer@gmail.com 116c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com } 117c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com#endif 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph** gptr = fGlyphArray.begin(); 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph** stop = fGlyphArray.end(); 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (gptr < stop) { 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPath* path = (*gptr)->fPath; 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path) { 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(path); 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com gptr += 1; 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDescriptor::Free(fDesc); 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(fScalerContext); 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->invokeAndRemoveAuxProcs(); 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 135e216b62841acd5db9d91b63960805568259a2e0ereed@android.com#define VALIDATE() AutoValidate av(this) 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define VALIDATE() 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comuint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(charCode); 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const CharGlyphRec& rec = fCharToGlyphHash[ID2HashIndex(id)]; 144ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec.fID == id) { 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return rec.fGlyph->getGlyphID(); 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fScalerContext->charToGlyphID(charCode); 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 152739245e986d7a78b96129f559363b7ab6fb0a21creed@android.comSkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { 153739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com return fScalerContext->glyphIDToChar(glyphID); 154739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com} 155739245e986d7a78b96129f559363b7ab6fb0a21creed@android.com 156019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.orgunsigned SkGlyphCache::getGlyphCount() { 157019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org return fScalerContext->getGlyphCount(); 158019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org} 159019978975b2cb2b2cfe270c72b53db0326002401ctguil@chromium.org 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(charCode); 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; 166ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fID != id) { 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the UniChar 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fID = id; 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the glyph index 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fGlyph = this->lookupMetrics(id, kJustAdvance_MetricsType); 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *rec->fGlyph; 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(glyphID); 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned index = ID2HashIndex(id); 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* glyph = fGlyphHash[index]; 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == glyph || glyph->fID != id) { 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType); 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fGlyphHash[index] = glyph; 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *glyph; 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(charCode); 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; 196ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fID != id) { 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashCollisionIf(rec->fGlyph != NULL); 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the UniChar 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fID = id; 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the glyph index 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashSuccess(); 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fGlyph->isJustAdvance()) { 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(rec->fGlyph); 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(rec->fGlyph->isFullMetrics()); 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *rec->fGlyph; 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed x, SkFixed y) { 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(charCode, x, y); 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; 219ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fID != id) { 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashCollisionIf(rec->fGlyph != NULL); 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the UniChar 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fID = id; 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this ID is based on the glyph index 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y); 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); 227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashSuccess(); 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fGlyph->isJustAdvance()) { 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(rec->fGlyph); 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(rec->fGlyph->isFullMetrics()); 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *rec->fGlyph; 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(glyphID); 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned index = ID2HashIndex(id); 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* glyph = fGlyphHash[index]; 242ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == glyph || glyph->fID != id) { 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashCollisionIf(glyph != NULL); 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com glyph = this->lookupMetrics(glyphID, kFull_MetricsType); 246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fGlyphHash[index] = glyph; 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashSuccess(); 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph->isJustAdvance()) { 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(glyph); 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(glyph->isFullMetrics()); 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *glyph; 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed x, SkFixed y) { 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com VALIDATE(); 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t id = SkGlyph::MakeID(glyphID, x, y); 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned index = ID2HashIndex(id); 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* glyph = fGlyphHash[index]; 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == glyph || glyph->fID != id) { 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashCollisionIf(glyph != NULL); 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com glyph = this->lookupMetrics(id, kFull_MetricsType); 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fGlyphHash[index] = glyph; 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com RecordHashSuccess(); 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph->isJustAdvance()) { 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(glyph); 272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(glyph->isFullMetrics()); 275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *glyph; 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph* glyph; 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int hi = 0; 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = fGlyphArray.count(); 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (count) { 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyph** gptr = fGlyphArray.begin(); 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int lo = 0; 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com hi = count - 1; 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (lo < hi) { 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int mid = (hi + lo) >> 1; 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (gptr[mid]->fID < id) { 292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com lo = mid + 1; 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com hi = mid; 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com glyph = gptr[hi]; 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph->fID == id) { 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (kFull_MetricsType == mtype && glyph->isJustAdvance()) { 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(glyph); 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return glyph; 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // check if we need to bump hi before falling though to the allocator 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph->fID < id) { 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com hi += 1; 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // not found, but hi tells us where to inser the new glyph 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMemoryUsed += sizeof(SkGlyph); 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChunkAlloc::kThrow_AllocFailType); 316e216b62841acd5db9d91b63960805568259a2e0ereed@android.com glyph->init(id); 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *fGlyphArray.insert(hi) = glyph; 318ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (kJustAdvance_MetricsType == mtype) { 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getAdvance(glyph); 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(kFull_MetricsType == mtype); 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getMetrics(glyph); 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return glyph; 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst void* SkGlyphCache::findImage(const SkGlyph& glyph) { 330029b014370d8a89edd3ee71f653b6ebb2bd47a9escarybeasts@gmail.com if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph.fImage == NULL) { 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t size = glyph.computeImageSize(); 333c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChunkAlloc::kReturnNil_AllocFailType); 335ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com // check that alloc() actually succeeded 336ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com if (glyph.fImage) { 337ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com fScalerContext->getImage(glyph); 338ea9bd4b8a675f3f92e815f79c2f5c456661235bareed@google.com // TODO: the scaler may have changed the maskformat during 339ea9bd4b8a675f3f92e815f79c2f5c456661235bareed@google.com // getImage (e.g. from AA or LCD to BW) which means we may have 340ea9bd4b8a675f3f92e815f79c2f5c456661235bareed@google.com // overallocated the buffer. Check if the new computedImageSize 341ea9bd4b8a675f3f92e815f79c2f5c456661235bareed@google.com // is smaller, and if so, strink the alloc size in fImageAlloc. 342ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com fMemoryUsed += size; 343ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com } 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return glyph.fImage; 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph.fWidth) { 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (glyph.fPath == NULL) { 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const_cast<SkGlyph&>(glyph).fPath = SkNEW(SkPath); 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fScalerContext->getPath(glyph, glyph.fPath); 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMemoryUsed += sizeof(SkPath) + 35546597516083edf81db0ed946d5ef7ba04057c008bsalomon@google.com glyph.fPath->countPoints() * sizeof(SkPoint); 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return glyph.fPath; 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const AuxProcRec* rec = fAuxProcList; 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (rec) { 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fProc == proc) { 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (dataPtr) { 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *dataPtr = rec->fData; 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec = rec->fNext; 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkGlyphCache::setAuxProc(void (*proc)(void*), void* data) { 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (proc == NULL) { 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com AuxProcRec* rec = fAuxProcList; 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (rec) { 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rec->fProc == proc) { 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fData = data; 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec = rec->fNext; 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // not found, create a new rec 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec = SkNEW(AuxProcRec); 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fProc = proc; 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fData = data; 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fNext = fAuxProcList; 395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAuxProcList = rec; 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkGlyphCache::invokeAndRemoveAuxProcs() { 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com AuxProcRec* rec = fAuxProcList; 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (rec) { 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec->fProc(rec->fData); 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com AuxProcRec* next = rec->fNext; 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(rec); 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rec = next; 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 411b64e323a250ba2e19645ee17965bcd89d09d597freed@google.com#include "SkThread.h" 412b64e323a250ba2e19645ee17965bcd89d09d597freed@google.com 4139defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comsize_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { 414490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com static const size_t minLimit = 256 * 1024; 415490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com if (newLimit < minLimit) { 416490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com newLimit = minLimit; 417490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com } 4188db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 4199defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkAutoMutexAcquire ac(fMutex); 4208db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 4219defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com size_t prevLimit = fCacheSizeLimit; 4229defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fCacheSizeLimit = newLimit; 4239defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalPurge(); 424490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com return prevLimit; 425490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com} 426490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 4279defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comint SkGlyphCache_Globals::setCacheCountLimit(int newCount) { 4289defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (newCount < 0) { 4299defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com newCount = 0; 4309defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 4318db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 43212b8acf22365abbd361f5f5796184340a5472b08reed@google.com SkAutoMutexAcquire ac(fMutex); 4338db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 4349defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com int prevCount = fCacheCountLimit; 4359defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fCacheCountLimit = newCount; 4369defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalPurge(); 4379defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return prevCount; 43812b8acf22365abbd361f5f5796184340a5472b08reed@google.com} 43912b8acf22365abbd361f5f5796184340a5472b08reed@google.com 4409defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comvoid SkGlyphCache_Globals::purgeAll() { 4419defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkAutoMutexAcquire ac(fMutex); 4429defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalPurge(fTotalMemoryUsed); 443490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com} 444490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* context) { 447b64e323a250ba2e19645ee17965bcd89d09d597freed@google.com SkGlyphCache_Globals& globals = getGlobals(); 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoMutexAcquire ac(globals.fMutex); 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache* cache; 450ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com globals.validate(); 452ae30cc1b4d11395a4e845ad003d8263f8395213breed@google.com 4539defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (proc(cache, context)) { 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com globals.validate(); 460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* This guy calls the visitor from within the mutext lock, so the visitor 463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cannot: 464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com - take too much time 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com - try to acquire the mutext again 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com - call a fontscaler (which might call into the cache) 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 46878341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.comSkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, 46978341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com const SkDescriptor* desc, 470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool (*proc)(const SkGlyphCache*, void*), 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* context) { 47278341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com if (!typeface) { 47378341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com typeface = SkTypeface::GetDefaultTypeface(); 47478341a3cbe1c3e6d9aa6aa1ff390aa9aac1ede4freed@google.com } 475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(desc); 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 477b64e323a250ba2e19645ee17965bcd89d09d597freed@google.com SkGlyphCache_Globals& globals = getGlobals(); 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoMutexAcquire ac(globals.fMutex); 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache* cache; 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool insideMutex = true; 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com globals.validate(); 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 4849defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 485bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (cache->fDesc->equals(*desc)) { 4869defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com globals.internalDetachCache(cache); 487bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com goto FOUND_IT; 488bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 489bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* Release the mutex now, before we create a new entry (which might have 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com side-effects like trying to access the cache/mutex (yikes!) 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ac.release(); // release the mutex now 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com insideMutex = false; // can't use globals anymore 496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 49742eacd7f693510758d71fdb07805a240d6176372reed@google.com // Check if we can create a scaler-context before creating the glyphcache. 49842eacd7f693510758d71fdb07805a240d6176372reed@google.com // If not, we may have exhausted OS/font resources, so try purging the 49942eacd7f693510758d71fdb07805a240d6176372reed@google.com // cache once and try again. 50042eacd7f693510758d71fdb07805a240d6176372reed@google.com { 501bcb996959ff24d7cc2c5cbaa1b4dd5b47bb9c8ccreed@google.com // pass true the first time, to notice if the scalercontext failed, 502bcb996959ff24d7cc2c5cbaa1b4dd5b47bb9c8ccreed@google.com // so we can try the purge. 503bcb996959ff24d7cc2c5cbaa1b4dd5b47bb9c8ccreed@google.com SkScalerContext* ctx = typeface->createScalerContext(desc, true); 50442eacd7f693510758d71fdb07805a240d6176372reed@google.com if (!ctx) { 50542eacd7f693510758d71fdb07805a240d6176372reed@google.com getSharedGlobals().purgeAll(); 506bcb996959ff24d7cc2c5cbaa1b4dd5b47bb9c8ccreed@google.com ctx = typeface->createScalerContext(desc, false); 507bcb996959ff24d7cc2c5cbaa1b4dd5b47bb9c8ccreed@google.com SkASSERT(ctx); 50842eacd7f693510758d71fdb07805a240d6176372reed@google.com } 50942eacd7f693510758d71fdb07805a240d6176372reed@google.com cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); 51042eacd7f693510758d71fdb07805a240d6176372reed@google.com } 511bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comFOUND_IT: 513e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 514e216b62841acd5db9d91b63960805568259a2e0ereed@android.com AutoValidate av(cache); 515e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 5169defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (!proc(cache, context)) { // need to reattach 517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (insideMutex) { 5189defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com globals.internalAttachCacheToHead(cache); 519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 5209defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com globals.attachCacheToHead(cache); 521bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 522bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cache = NULL; 523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return cache; 525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkGlyphCache::AttachCache(SkGlyphCache* cache) { 528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cache); 529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(cache->fNext == NULL); 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5319defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com getGlobals().attachCacheToHead(cache); 5329defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5349defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com/////////////////////////////////////////////////////////////////////////////// 535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5369defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comvoid SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { 5379defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkAutoMutexAcquire ac(fMutex); 538bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5399defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->validate(); 5409defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com cache->validate(); 541bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5429defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalAttachCacheToHead(cache); 5439defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalPurge(); 544bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5469defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comSkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { 5479defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkGlyphCache* cache = fHead; 548bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (cache) { 549bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (cache->fNext) { 550bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cache = cache->fNext; 551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return cache; 554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5569defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comsize_t SkGlyphCache_Globals::internalPurge(size_t minBytesNeeded) { 5579defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->validate(); 558935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 5599defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com size_t bytesNeeded = 0; 5609defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (fTotalMemoryUsed > fCacheSizeLimit) { 5619defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit; 5629defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 5639defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com bytesNeeded = SkMax32(bytesNeeded, minBytesNeeded); 5649defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (bytesNeeded) { 5659defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // no small purges! 5669defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com bytesNeeded = SkMax32(bytesNeeded, fTotalMemoryUsed >> 2); 567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5699defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com int countNeeded = 0; 5709defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (fCacheCount > fCacheCountLimit) { 5719defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com countNeeded = fCacheCount - fCacheCountLimit; 5729defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // no small purges! 5739defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com countNeeded = SkMax32(countNeeded, fCacheCount >> 2); 574bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 575bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5769defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // early exit 5779defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (!countNeeded && !bytesNeeded) { 5789defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return 0; 5799defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 580bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 581bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t bytesFreed = 0; 5829defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com int countFreed = 0; 583bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5849defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // we start at the tail and proceed backwards, as the linklist is in LRU 5859defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com // order, with unimportant entries at the tail. 5869defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkGlyphCache* cache = this->internalGetTail(); 5879defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com while (cache != NULL && 5889defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com (bytesFreed < bytesNeeded || countFreed < countNeeded)) { 589bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkGlyphCache* prev = cache->fPrev; 590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bytesFreed += cache->fMemoryUsed; 5919defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com countFreed += 1; 592bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5939defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->internalDetachCache(cache); 594bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE(cache); 595bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cache = prev; 596bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 597bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5989defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com this->validate(); 599bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 600bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SPEW_PURGE_STATUS 6019defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (countFreed && !gSkSuppressFontCachePurgeSpew) { 602bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("purging %dK from font cache [%d entries]\n", 6039defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com (int)(bytesFreed >> 10), countFreed); 604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 606bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return bytesFreed; 608bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6109defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comvoid SkGlyphCache_Globals::internalAttachCacheToHead(SkGlyphCache* cache) { 6119defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkASSERT(NULL == cache->fPrev && NULL == cache->fNext); 6129defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (fHead) { 6139defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fHead->fPrev = cache; 6149defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com cache->fNext = fHead; 6159defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 6169defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fHead = cache; 6178db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 6189defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fCacheCount += 1; 6199defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fTotalMemoryUsed += cache->fMemoryUsed; 6209defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6219defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6229defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comvoid SkGlyphCache_Globals::internalDetachCache(SkGlyphCache* cache) { 6239defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkASSERT(fCacheCount > 0); 6249defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fCacheCount -= 1; 6259defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fTotalMemoryUsed -= cache->fMemoryUsed; 6269defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6279defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (cache->fPrev) { 6289defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com cache->fPrev->fNext = cache->fNext; 6299defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } else { 6309defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com fHead = cache->fNext; 6319defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 6329defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com if (cache->fNext) { 6339defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com cache->fNext->fPrev = cache->fPrev; 6349defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 6359defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com cache->fPrev = cache->fNext = NULL; 6369defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6379defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 638e216b62841acd5db9d91b63960805568259a2e0ereed@android.com/////////////////////////////////////////////////////////////////////////////// 639e216b62841acd5db9d91b63960805568259a2e0ereed@android.com 640490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com#ifdef SK_DEBUG 6419defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 642e216b62841acd5db9d91b63960805568259a2e0ereed@android.comvoid SkGlyphCache::validate() const { 6434a0d8c8c1a6281cf2440b54606e894cc32354abfdjsollen@google.com#ifdef SK_DEBUG_GLYPH_CACHE 644e216b62841acd5db9d91b63960805568259a2e0ereed@android.com int count = fGlyphArray.count(); 645e216b62841acd5db9d91b63960805568259a2e0ereed@android.com for (int i = 0; i < count; i++) { 646e216b62841acd5db9d91b63960805568259a2e0ereed@android.com const SkGlyph* glyph = fGlyphArray[i]; 647e216b62841acd5db9d91b63960805568259a2e0ereed@android.com SkASSERT(glyph); 648e216b62841acd5db9d91b63960805568259a2e0ereed@android.com SkASSERT(fGlyphAlloc.contains(glyph)); 649e216b62841acd5db9d91b63960805568259a2e0ereed@android.com if (glyph->fImage) { 650c67a3e573cd4660bc57622fd4550effcacc046c8reed@google.com SkASSERT(fGlyphAlloc.contains(glyph->fImage)); 651e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 652e216b62841acd5db9d91b63960805568259a2e0ereed@android.com } 6534a0d8c8c1a6281cf2440b54606e894cc32354abfdjsollen@google.com#endif 654e216b62841acd5db9d91b63960805568259a2e0ereed@android.com} 6559defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6569defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comvoid SkGlyphCache_Globals::validate() const { 6579defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com size_t computedBytes = 0; 6589defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com int computedCount = 0; 6598db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 6609defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com const SkGlyphCache* head = fHead; 6619defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com while (head != NULL) { 6629defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com computedBytes += head->fMemoryUsed; 6639defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com computedCount += 1; 6649defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com head = head->fNext; 6659defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com } 6668db5ae540517d2c31d40e2de5722d8dbb7ff3c68skia.committer@gmail.com 6679defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkASSERT(fTotalMemoryUsed == computedBytes); 6689defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkASSERT(fCacheCount == computedCount); 6699defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6709defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 671e216b62841acd5db9d91b63960805568259a2e0ereed@android.com#endif 672490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 673490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com/////////////////////////////////////////////////////////////////////////////// 674490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com/////////////////////////////////////////////////////////////////////////////// 675490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 676490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com#include "SkTypefaceCache.h" 677490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 678490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.comsize_t SkGraphics::GetFontCacheLimit() { 6799defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().getCacheSizeLimit(); 680490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com} 681490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 682490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.comsize_t SkGraphics::SetFontCacheLimit(size_t bytes) { 6839defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().setCacheSizeLimit(bytes); 684490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com} 685490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 6863094b00052a6652f3c11894b21aed2acb5381987reed@google.comsize_t SkGraphics::GetFontCacheUsed() { 6879defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().getTotalMemoryUsed(); 6889defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6899defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6909defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comint SkGraphics::GetFontCacheCountLimit() { 6919defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().getCacheCountLimit(); 6929defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6939defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6949defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comint SkGraphics::SetFontCacheCountLimit(int count) { 6959defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().setCacheCountLimit(count); 6969defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com} 6979defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com 6989defd9148e467f08ccd45cb7800a82f2660ef42freed@google.comint SkGraphics::GetFontCacheCountUsed() { 6999defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return getSharedGlobals().getCacheCountUsed(); 7003094b00052a6652f3c11894b21aed2acb5381987reed@google.com} 7013094b00052a6652f3c11894b21aed2acb5381987reed@google.com 702490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.comvoid SkGraphics::PurgeFontCache() { 70312b8acf22365abbd361f5f5796184340a5472b08reed@google.com getSharedGlobals().purgeAll(); 704490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com SkTypefaceCache::PurgeAll(); 705490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com} 706490800bd6cfbaae642a67e373e343f29f7b6f917reed@google.com 707baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.comsize_t SkGraphics::GetTLSFontCacheLimit() { 708baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 7099defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com return tls ? tls->getCacheSizeLimit() : 0; 710baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com} 711baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com 71271f48188df42fc0da08be7f2ff036d0a6ba1b8f0reed@google.comvoid SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 713baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com if (0 == bytes) { 714baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com SkGlyphCache_Globals::DeleteTLS(); 715baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com } else { 7169defd9148e467f08ccd45cb7800a82f2660ef42freed@google.com SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); 717baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com } 718baaaeb0f86173a4ffb29cf75f90b9473ea7d2125reed@google.com} 719