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 "SkAtomics.h" 13 #include "SkMutex.h" 14 15 #define TYPEFACE_CACHE_LIMIT 1024 16 17 SkTypefaceCache::SkTypefaceCache() {} 18 19 SkTypefaceCache::~SkTypefaceCache() { 20 const Rec* curr = fArray.begin(); 21 const Rec* stop = fArray.end(); 22 while (curr < stop) { 23 curr->fFace->unref(); 24 curr += 1; 25 } 26 } 27 28 void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) { 29 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) { 30 this->purge(TYPEFACE_CACHE_LIMIT >> 2); 31 } 32 33 Rec* rec = fArray.append(); 34 rec->fFace = SkRef(face); 35 rec->fRequestedStyle = requestedStyle; 36 } 37 38 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const { 39 const Rec* curr = fArray.begin(); 40 const Rec* stop = fArray.end(); 41 while (curr < stop) { 42 SkTypeface* currFace = curr->fFace; 43 if (proc(currFace, curr->fRequestedStyle, ctx)) { 44 return SkRef(currFace); 45 } 46 curr += 1; 47 } 48 return nullptr; 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 (face->unique()) { 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, const SkFontStyle& requestedStyle) { 88 SkAutoMutexAcquire ama(gMutex); 89 Get().add(face, requestedStyle); 90 } 91 92 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { 93 SkAutoMutexAcquire ama(gMutex); 94 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx); 95 return typeface; 96 } 97 98 void SkTypefaceCache::PurgeAll() { 99 SkAutoMutexAcquire ama(gMutex); 100 Get().purgeAll(); 101 } 102 103 /////////////////////////////////////////////////////////////////////////////// 104 105 #ifdef SK_DEBUG 106 static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) { 107 SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n", 108 face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt()); 109 return false; 110 } 111 #endif 112 113 void SkTypefaceCache::Dump() { 114 #ifdef SK_DEBUG 115 SkAutoMutexAcquire ama(gMutex); 116 (void)Get().findByProcAndRef(DumpProc, nullptr); 117 #endif 118 } 119