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 1024 15 16 SkTypefaceCache::SkTypefaceCache() {} 17 18 SkTypefaceCache::~SkTypefaceCache() { 19 const Rec* curr = fArray.begin(); 20 const Rec* stop = fArray.end(); 21 while (curr < stop) { 22 curr->fFace->unref(); 23 curr += 1; 24 } 25 } 26 27 void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) { 28 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) { 29 this->purge(TYPEFACE_CACHE_LIMIT >> 2); 30 } 31 32 Rec* rec = fArray.append(); 33 rec->fFace = SkRef(face); 34 rec->fRequestedStyle = requestedStyle; 35 } 36 37 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const { 38 const Rec* curr = fArray.begin(); 39 const Rec* stop = fArray.end(); 40 while (curr < stop) { 41 SkTypeface* currFace = curr->fFace; 42 if (proc(currFace, curr->fRequestedStyle, ctx)) { 43 return SkRef(currFace); 44 } 45 curr += 1; 46 } 47 return NULL; 48 } 49 50 void SkTypefaceCache::purge(int numToPurge) { 51 int count = fArray.count(); 52 int i = 0; 53 while (i < count) { 54 SkTypeface* face = fArray[i].fFace; 55 if (face->unique()) { 56 face->unref(); 57 fArray.remove(i); 58 --count; 59 if (--numToPurge == 0) { 60 return; 61 } 62 } else { 63 ++i; 64 } 65 } 66 } 67 68 void SkTypefaceCache::purgeAll() { 69 this->purge(fArray.count()); 70 } 71 72 /////////////////////////////////////////////////////////////////////////////// 73 74 SkTypefaceCache& SkTypefaceCache::Get() { 75 static SkTypefaceCache gCache; 76 return gCache; 77 } 78 79 SkFontID SkTypefaceCache::NewFontID() { 80 static int32_t gFontID; 81 return sk_atomic_inc(&gFontID) + 1; 82 } 83 84 SK_DECLARE_STATIC_MUTEX(gMutex); 85 86 void SkTypefaceCache::Add(SkTypeface* face, const SkFontStyle& requestedStyle) { 87 SkAutoMutexAcquire ama(gMutex); 88 Get().add(face, requestedStyle); 89 } 90 91 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { 92 SkAutoMutexAcquire ama(gMutex); 93 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx); 94 return typeface; 95 } 96 97 void SkTypefaceCache::PurgeAll() { 98 SkAutoMutexAcquire ama(gMutex); 99 Get().purgeAll(); 100 } 101 102 /////////////////////////////////////////////////////////////////////////////// 103 104 #ifdef SK_DEBUG 105 static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) { 106 SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n", 107 face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt()); 108 return false; 109 } 110 #endif 111 112 void SkTypefaceCache::Dump() { 113 #ifdef SK_DEBUG 114 SkAutoMutexAcquire ama(gMutex); 115 (void)Get().findByProcAndRef(DumpProc, NULL); 116 #endif 117 } 118