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