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
SkTypefaceCache()17 SkTypefaceCache::SkTypefaceCache() {}
18
~SkTypefaceCache()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
add(SkTypeface * face,const SkFontStyle & requestedStyle)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
findByProcAndRef(FindProc proc,void * ctx) const38 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
purge(int numToPurge)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
purgeAll()69 void SkTypefaceCache::purgeAll() {
70 this->purge(fArray.count());
71 }
72
73 ///////////////////////////////////////////////////////////////////////////////
74
Get()75 SkTypefaceCache& SkTypefaceCache::Get() {
76 static SkTypefaceCache gCache;
77 return gCache;
78 }
79
NewFontID()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
Add(SkTypeface * face,const SkFontStyle & requestedStyle)87 void SkTypefaceCache::Add(SkTypeface* face, const SkFontStyle& requestedStyle) {
88 SkAutoMutexAcquire ama(gMutex);
89 Get().add(face, requestedStyle);
90 }
91
FindByProcAndRef(FindProc proc,void * ctx)92 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
93 SkAutoMutexAcquire ama(gMutex);
94 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
95 return typeface;
96 }
97
PurgeAll()98 void SkTypefaceCache::PurgeAll() {
99 SkAutoMutexAcquire ama(gMutex);
100 Get().purgeAll();
101 }
102
103 ///////////////////////////////////////////////////////////////////////////////
104
105 #ifdef SK_DEBUG
DumpProc(SkTypeface * face,const SkFontStyle & s,void * ctx)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
Dump()113 void SkTypefaceCache::Dump() {
114 #ifdef SK_DEBUG
115 SkAutoMutexAcquire ama(gMutex);
116 (void)Get().findByProcAndRef(DumpProc, nullptr);
117 #endif
118 }
119