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 void SkTypefaceCache::add(SkTypeface* face, 17 SkTypeface::Style requestedStyle, 18 bool strong) { 19 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) { 20 this->purge(TYPEFACE_CACHE_LIMIT >> 2); 21 } 22 23 Rec* rec = fArray.append(); 24 rec->fFace = face; 25 rec->fRequestedStyle = requestedStyle; 26 rec->fStrong = strong; 27 if (strong) { 28 face->ref(); 29 } else { 30 face->weak_ref(); 31 } 32 } 33 34 SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const { 35 const Rec* curr = fArray.begin(); 36 const Rec* stop = fArray.end(); 37 while (curr < stop) { 38 if (curr->fFace->uniqueID() == fontID) { 39 return curr->fFace; 40 } 41 curr += 1; 42 } 43 return NULL; 44 } 45 46 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const { 47 const Rec* curr = fArray.begin(); 48 const Rec* stop = fArray.end(); 49 while (curr < stop) { 50 SkTypeface* currFace = curr->fFace; 51 if (proc(currFace, curr->fRequestedStyle, ctx)) { 52 if (curr->fStrong) { 53 currFace->ref(); 54 return currFace; 55 } else if (currFace->try_ref()) { 56 return currFace; 57 } else { 58 //remove currFace from fArray? 59 } 60 } 61 curr += 1; 62 } 63 return NULL; 64 } 65 66 void SkTypefaceCache::purge(int numToPurge) { 67 int count = fArray.count(); 68 int i = 0; 69 while (i < count) { 70 SkTypeface* face = fArray[i].fFace; 71 bool strong = fArray[i].fStrong; 72 if ((strong && face->unique()) || (!strong && face->weak_expired())) { 73 if (strong) { 74 face->unref(); 75 } else { 76 face->weak_unref(); 77 } 78 fArray.remove(i); 79 --count; 80 if (--numToPurge == 0) { 81 return; 82 } 83 } else { 84 ++i; 85 } 86 } 87 } 88 89 void SkTypefaceCache::purgeAll() { 90 this->purge(fArray.count()); 91 } 92 93 /////////////////////////////////////////////////////////////////////////////// 94 95 SkTypefaceCache& SkTypefaceCache::Get() { 96 static SkTypefaceCache gCache; 97 return gCache; 98 } 99 100 SkFontID SkTypefaceCache::NewFontID() { 101 static int32_t gFontID; 102 return sk_atomic_inc(&gFontID) + 1; 103 } 104 105 SK_DECLARE_STATIC_MUTEX(gMutex); 106 107 void SkTypefaceCache::Add(SkTypeface* face, 108 SkTypeface::Style requestedStyle, 109 bool strong) { 110 SkAutoMutexAcquire ama(gMutex); 111 Get().add(face, requestedStyle, strong); 112 } 113 114 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) { 115 SkAutoMutexAcquire ama(gMutex); 116 return Get().findByID(fontID); 117 } 118 119 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { 120 SkAutoMutexAcquire ama(gMutex); 121 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx); 122 return typeface; 123 } 124 125 void SkTypefaceCache::PurgeAll() { 126 SkAutoMutexAcquire ama(gMutex); 127 Get().purgeAll(); 128 } 129 130 /////////////////////////////////////////////////////////////////////////////// 131 132 #ifdef SK_DEBUG 133 static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) { 134 SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n", 135 face, face->uniqueID(), style, face->getRefCnt()); 136 return false; 137 } 138 #endif 139 140 void SkTypefaceCache::Dump() { 141 #ifdef SK_DEBUG 142 SkAutoMutexAcquire ama(gMutex); 143 (void)Get().findByProcAndRef(DumpProc, NULL); 144 #endif 145 } 146