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 16 void 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 27 SkTypeface* 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 39 SkTypeface* 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 51 void 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 69 void SkTypefaceCache::purgeAll() { 70 this->purge(fArray.count()); 71 } 72 73 /////////////////////////////////////////////////////////////////////////////// 74 75 SkTypefaceCache& SkTypefaceCache::Get() { 76 static SkTypefaceCache gCache; 77 return gCache; 78 } 79 80 SkFontID SkTypefaceCache::NewFontID() { 81 static int32_t gFontID; 82 return sk_atomic_inc(&gFontID) + 1; 83 } 84 85 SK_DECLARE_STATIC_MUTEX(gMutex); 86 87 void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) { 88 SkAutoMutexAcquire ama(gMutex); 89 Get().add(face, requestedStyle); 90 } 91 92 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) { 93 SkAutoMutexAcquire ama(gMutex); 94 return Get().findByID(fontID); 95 } 96 97 SkTypeface* 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 104 void SkTypefaceCache::PurgeAll() { 105 SkAutoMutexAcquire ama(gMutex); 106 Get().purgeAll(); 107 } 108 109 /////////////////////////////////////////////////////////////////////////////// 110 111 #ifdef SK_DEBUG 112 static 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 119 void SkTypefaceCache::Dump() { 120 #ifdef SK_DEBUG 121 SkAutoMutexAcquire ama(gMutex); 122 (void)Get().findByProc(DumpProc, NULL); 123 #endif 124 } 125 126