1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9
10 #include "SkTypefaceCache.h"
11 #include "SkAtomics.h"
12 #include "SkMutex.h"
13
14 #define TYPEFACE_CACHE_LIMIT 1024
15
SkTypefaceCache()16 SkTypefaceCache::SkTypefaceCache() {}
17
add(SkTypeface * face)18 void SkTypefaceCache::add(SkTypeface* face) {
19 if (fTypefaces.count() >= TYPEFACE_CACHE_LIMIT) {
20 this->purge(TYPEFACE_CACHE_LIMIT >> 2);
21 }
22
23 fTypefaces.emplace_back(SkRef(face));
24 }
25
findByProcAndRef(FindProc proc,void * ctx) const26 SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
27 for (const sk_sp<SkTypeface>& typeface : fTypefaces) {
28 if (proc(typeface.get(), ctx)) {
29 return SkRef(typeface.get());
30 }
31 }
32 return nullptr;
33 }
34
purge(int numToPurge)35 void SkTypefaceCache::purge(int numToPurge) {
36 int count = fTypefaces.count();
37 int i = 0;
38 while (i < count) {
39 if (fTypefaces[i]->unique()) {
40 fTypefaces.removeShuffle(i);
41 --count;
42 if (--numToPurge == 0) {
43 return;
44 }
45 } else {
46 ++i;
47 }
48 }
49 }
50
purgeAll()51 void SkTypefaceCache::purgeAll() {
52 this->purge(fTypefaces.count());
53 }
54
55 ///////////////////////////////////////////////////////////////////////////////
56
Get()57 SkTypefaceCache& SkTypefaceCache::Get() {
58 static SkTypefaceCache gCache;
59 return gCache;
60 }
61
NewFontID()62 SkFontID SkTypefaceCache::NewFontID() {
63 static int32_t gFontID;
64 return sk_atomic_inc(&gFontID) + 1;
65 }
66
67 SK_DECLARE_STATIC_MUTEX(gMutex);
68
Add(SkTypeface * face)69 void SkTypefaceCache::Add(SkTypeface* face) {
70 SkAutoMutexAcquire ama(gMutex);
71 Get().add(face);
72 }
73
FindByProcAndRef(FindProc proc,void * ctx)74 SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
75 SkAutoMutexAcquire ama(gMutex);
76 return Get().findByProcAndRef(proc, ctx);
77 }
78
PurgeAll()79 void SkTypefaceCache::PurgeAll() {
80 SkAutoMutexAcquire ama(gMutex);
81 Get().purgeAll();
82 }
83
84 ///////////////////////////////////////////////////////////////////////////////
85
86 #ifdef SK_DEBUG
DumpProc(SkTypeface * face,void * ctx)87 static bool DumpProc(SkTypeface* face, void* ctx) {
88 SkString n;
89 face->getFamilyName(&n);
90 SkFontStyle s = face->fontStyle();
91 SkFontID id = face->uniqueID();
92 SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d refcnt %d name %s\n",
93 face, id, s.weight(), s.width(), s.slant(), face->getRefCnt(), n.c_str());
94 return false;
95 }
96 #endif
97
Dump()98 void SkTypefaceCache::Dump() {
99 #ifdef SK_DEBUG
100 (void)Get().findByProcAndRef(DumpProc, nullptr);
101 #endif
102 }
103