1 /*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18 #include "SkTypefaceCache.h"
19 #include "SkThread.h"
20
21 #define TYPEFACE_CACHE_LIMIT 128
22
add(SkTypeface * face,SkTypeface::Style requestedStyle)23 void SkTypefaceCache::add(SkTypeface* face, SkTypeface::Style requestedStyle) {
24 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
25 this->purge(TYPEFACE_CACHE_LIMIT >> 2);
26 }
27
28 Rec* rec = fArray.append();
29 rec->fFace = face;
30 rec->fRequestedStyle = requestedStyle;
31 face->ref();
32 }
33
findByID(SkFontID fontID) const34 SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
35 const Rec* curr = fArray.begin();
36 const Rec* stop = fArray.end();
37 while (curr < stop) {
38 if (curr->fFace->uniqueID() == fontID) {
39 return curr->fFace;
40 }
41 curr += 1;
42 }
43 return NULL;
44 }
45
findByProc(FindProc proc,void * ctx) const46 SkTypeface* SkTypefaceCache::findByProc(FindProc proc, void* ctx) const {
47 const Rec* curr = fArray.begin();
48 const Rec* stop = fArray.end();
49 while (curr < stop) {
50 if (proc(curr->fFace, curr->fRequestedStyle, ctx)) {
51 return curr->fFace;
52 }
53 curr += 1;
54 }
55 return NULL;
56 }
57
purge(int numToPurge)58 void SkTypefaceCache::purge(int numToPurge) {
59 int count = fArray.count();
60 int i = 0;
61 while (i < count) {
62 SkTypeface* face = fArray[i].fFace;
63 if (1 == face->getRefCnt()) {
64 face->unref();
65 fArray.remove(i);
66 --count;
67 if (--numToPurge == 0) {
68 return;
69 }
70 } else {
71 ++i;
72 }
73 }
74 }
75
76 ///////////////////////////////////////////////////////////////////////////////
77
Get()78 SkTypefaceCache& SkTypefaceCache::Get() {
79 static SkTypefaceCache gCache;
80 return gCache;
81 }
82
NewFontID()83 SkFontID SkTypefaceCache::NewFontID() {
84 static int32_t gFontID;
85 return sk_atomic_inc(&gFontID) + 1;
86 }
87
88 static SkMutex gMutex;
89
Add(SkTypeface * face,SkTypeface::Style requestedStyle)90 void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) {
91 SkAutoMutexAcquire ama(gMutex);
92 Get().add(face, requestedStyle);
93 }
94
FindByID(SkFontID fontID)95 SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
96 SkAutoMutexAcquire ama(gMutex);
97 return Get().findByID(fontID);
98 }
99
FindByProc(FindProc proc,void * ctx)100 SkTypeface* SkTypefaceCache::FindByProc(FindProc proc, void* ctx) {
101 SkAutoMutexAcquire ama(gMutex);
102 return Get().findByProc(proc, ctx);
103 }
104
105 ///////////////////////////////////////////////////////////////////////////////
106
107 #ifdef SK_DEBUG
DumpProc(SkTypeface * face,SkTypeface::Style style,void * ctx)108 static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
109 SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
110 face, face->uniqueID(), style, face->getRefCnt());
111 return false;
112 }
113 #endif
114
Dump()115 void SkTypefaceCache::Dump() {
116 #ifdef SK_DEBUG
117 SkAutoMutexAcquire ama(gMutex);
118 (void)Get().findByProc(DumpProc, NULL);
119 #endif
120 }
121
122