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
SkTypefaceCache()16 SkTypefaceCache::SkTypefaceCache() {}
17
~SkTypefaceCache()18 SkTypefaceCache::~SkTypefaceCache() {
19 const Rec* curr = fArray.begin();
20 const Rec* stop = fArray.end();
21 while (curr < stop) {
22 curr->fFace->unref();
23 curr += 1;
24 }
25 }
26
add(SkTypeface * face,const SkFontStyle & requestedStyle)27 void SkTypefaceCache::add(SkTypeface* face, const SkFontStyle& requestedStyle) {
28 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
29 this->purge(TYPEFACE_CACHE_LIMIT >> 2);
30 }
31
32 Rec* rec = fArray.append();
33 rec->fFace = SkRef(face);
34 rec->fRequestedStyle = requestedStyle;
35 }
36
findByProcAndRef(FindProc proc,void * ctx) const37 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
38 const Rec* curr = fArray.begin();
39 const Rec* stop = fArray.end();
40 while (curr < stop) {
41 SkTypeface* currFace = curr->fFace;
42 if (proc(currFace, curr->fRequestedStyle, ctx)) {
43 return SkRef(currFace);
44 }
45 curr += 1;
46 }
47 return NULL;
48 }
49
purge(int numToPurge)50 void SkTypefaceCache::purge(int numToPurge) {
51 int count = fArray.count();
52 int i = 0;
53 while (i < count) {
54 SkTypeface* face = fArray[i].fFace;
55 if (face->unique()) {
56 face->unref();
57 fArray.remove(i);
58 --count;
59 if (--numToPurge == 0) {
60 return;
61 }
62 } else {
63 ++i;
64 }
65 }
66 }
67
purgeAll()68 void SkTypefaceCache::purgeAll() {
69 this->purge(fArray.count());
70 }
71
72 ///////////////////////////////////////////////////////////////////////////////
73
Get()74 SkTypefaceCache& SkTypefaceCache::Get() {
75 static SkTypefaceCache gCache;
76 return gCache;
77 }
78
NewFontID()79 SkFontID SkTypefaceCache::NewFontID() {
80 static int32_t gFontID;
81 return sk_atomic_inc(&gFontID) + 1;
82 }
83
84 SK_DECLARE_STATIC_MUTEX(gMutex);
85
Add(SkTypeface * face,const SkFontStyle & requestedStyle)86 void SkTypefaceCache::Add(SkTypeface* face, const SkFontStyle& requestedStyle) {
87 SkAutoMutexAcquire ama(gMutex);
88 Get().add(face, requestedStyle);
89 }
90
FindByProcAndRef(FindProc proc,void * ctx)91 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
92 SkAutoMutexAcquire ama(gMutex);
93 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
94 return typeface;
95 }
96
PurgeAll()97 void SkTypefaceCache::PurgeAll() {
98 SkAutoMutexAcquire ama(gMutex);
99 Get().purgeAll();
100 }
101
102 ///////////////////////////////////////////////////////////////////////////////
103
104 #ifdef SK_DEBUG
DumpProc(SkTypeface * face,const SkFontStyle & s,void * ctx)105 static bool DumpProc(SkTypeface* face, const SkFontStyle& s, void* ctx) {
106 SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d\n",
107 face, face->uniqueID(), s.weight(), s.width(), s.slant(), face->getRefCnt());
108 return false;
109 }
110 #endif
111
Dump()112 void SkTypefaceCache::Dump() {
113 #ifdef SK_DEBUG
114 SkAutoMutexAcquire ama(gMutex);
115 (void)Get().findByProcAndRef(DumpProc, NULL);
116 #endif
117 }
118