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, 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->getRefCnt() == 1) || 73 (!strong && face->weak_expired())) 74 { 75 if (strong) { 76 face->unref(); 77 } else { 78 face->weak_unref(); 79 } 80 fArray.remove(i); 81 --count; 82 if (--numToPurge == 0) { 83 return; 84 } 85 } else { 86 ++i; 87 } 88 } 89 } 90 91 void SkTypefaceCache::purgeAll() { 92 this->purge(fArray.count()); 93 } 94 95 /////////////////////////////////////////////////////////////////////////////// 96 97 SkTypefaceCache& SkTypefaceCache::Get() { 98 static SkTypefaceCache gCache; 99 return gCache; 100 } 101 102 SkFontID SkTypefaceCache::NewFontID() { 103 static int32_t gFontID; 104 return sk_atomic_inc(&gFontID) + 1; 105 } 106 107 SK_DECLARE_STATIC_MUTEX(gMutex); 108 109 void SkTypefaceCache::Add(SkTypeface* face, 110 SkTypeface::Style requestedStyle, 111 bool strong) { 112 SkAutoMutexAcquire ama(gMutex); 113 Get().add(face, requestedStyle, strong); 114 } 115 116 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) { 117 SkAutoMutexAcquire ama(gMutex); 118 return Get().findByID(fontID); 119 } 120 121 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { 122 SkAutoMutexAcquire ama(gMutex); 123 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx); 124 return typeface; 125 } 126 127 void SkTypefaceCache::PurgeAll() { 128 SkAutoMutexAcquire ama(gMutex); 129 Get().purgeAll(); 130 } 131 132 /////////////////////////////////////////////////////////////////////////////// 133 134 #ifdef SK_DEBUG 135 static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) { 136 SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n", 137 face, face->uniqueID(), style, face->getRefCnt()); 138 return false; 139 } 140 #endif 141 142 void SkTypefaceCache::Dump() { 143 #ifdef SK_DEBUG 144 SkAutoMutexAcquire ama(gMutex); 145 (void)Get().findByProcAndRef(DumpProc, NULL); 146 #endif 147 } 148