1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11#include "SkTypefaceCache.h" 12#include "SkThread.h" 13 14#define TYPEFACE_CACHE_LIMIT 128 15 16void SkTypefaceCache::add(SkTypeface* face, SkTypeface::Style requestedStyle) { 17 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) { 18 this->purge(TYPEFACE_CACHE_LIMIT >> 2); 19 } 20 21 Rec* rec = fArray.append(); 22 rec->fFace = face; 23 rec->fRequestedStyle = requestedStyle; 24 face->ref(); 25} 26 27SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const { 28 const Rec* curr = fArray.begin(); 29 const Rec* stop = fArray.end(); 30 while (curr < stop) { 31 if (curr->fFace->uniqueID() == fontID) { 32 return curr->fFace; 33 } 34 curr += 1; 35 } 36 return NULL; 37} 38 39SkTypeface* SkTypefaceCache::findByProc(FindProc proc, void* ctx) const { 40 const Rec* curr = fArray.begin(); 41 const Rec* stop = fArray.end(); 42 while (curr < stop) { 43 if (proc(curr->fFace, curr->fRequestedStyle, ctx)) { 44 return curr->fFace; 45 } 46 curr += 1; 47 } 48 return NULL; 49} 50 51void SkTypefaceCache::purge(int numToPurge) { 52 int count = fArray.count(); 53 int i = 0; 54 while (i < count) { 55 SkTypeface* face = fArray[i].fFace; 56 if (1 == face->getRefCnt()) { 57 face->unref(); 58 fArray.remove(i); 59 --count; 60 if (--numToPurge == 0) { 61 return; 62 } 63 } else { 64 ++i; 65 } 66 } 67} 68 69void SkTypefaceCache::purgeAll() { 70 this->purge(fArray.count()); 71} 72 73/////////////////////////////////////////////////////////////////////////////// 74 75SkTypefaceCache& SkTypefaceCache::Get() { 76 static SkTypefaceCache gCache; 77 return gCache; 78} 79 80SkFontID SkTypefaceCache::NewFontID() { 81 static int32_t gFontID; 82 return sk_atomic_inc(&gFontID) + 1; 83} 84 85SK_DECLARE_STATIC_MUTEX(gMutex); 86 87void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) { 88 SkAutoMutexAcquire ama(gMutex); 89 Get().add(face, requestedStyle); 90} 91 92SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) { 93 SkAutoMutexAcquire ama(gMutex); 94 return Get().findByID(fontID); 95} 96 97SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { 98 SkAutoMutexAcquire ama(gMutex); 99 SkTypeface* typeface = Get().findByProc(proc, ctx); 100 SkSafeRef(typeface); 101 return typeface; 102} 103 104void SkTypefaceCache::PurgeAll() { 105 SkAutoMutexAcquire ama(gMutex); 106 Get().purgeAll(); 107} 108 109/////////////////////////////////////////////////////////////////////////////// 110 111#ifdef SK_DEBUG 112static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) { 113 SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n", 114 face, face->uniqueID(), style, face->getRefCnt()); 115 return false; 116} 117#endif 118 119void SkTypefaceCache::Dump() { 120#ifdef SK_DEBUG 121 SkAutoMutexAcquire ama(gMutex); 122 (void)Get().findByProc(DumpProc, NULL); 123#endif 124} 125 126