blob: f864e1c9dc5105b4961eacd0253c48c7a18a67d8 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.com2f3dc9d2011-05-02 17:33:45 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.com2f3dc9d2011-05-02 17:33:45 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.com2f3dc9d2011-05-02 17:33:45 +000011#include "SkTypefaceCache.h"
12#include "SkThread.h"
13
reed@google.come9bbc812013-03-27 20:29:18 +000014#define TYPEFACE_CACHE_LIMIT 1024
reed@google.com2f3dc9d2011-05-02 17:33:45 +000015
reed@google.com03b87812013-08-13 14:59:17 +000016SkTypefaceCache::SkTypefaceCache() {}
17
18SkTypefaceCache::~SkTypefaceCache() {
19 const Rec* curr = fArray.begin();
20 const Rec* stop = fArray.end();
21 while (curr < stop) {
22 if (curr->fStrong) {
23 curr->fFace->unref();
24 } else {
25 curr->fFace->weak_unref();
26 }
27 curr += 1;
28 }
29}
30
bungeman@google.coma02bc152012-05-16 18:21:56 +000031void SkTypefaceCache::add(SkTypeface* face,
32 SkTypeface::Style requestedStyle,
33 bool strong) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +000034 if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
35 this->purge(TYPEFACE_CACHE_LIMIT >> 2);
36 }
37
38 Rec* rec = fArray.append();
39 rec->fFace = face;
40 rec->fRequestedStyle = requestedStyle;
bungeman@google.coma02bc152012-05-16 18:21:56 +000041 rec->fStrong = strong;
42 if (strong) {
43 face->ref();
44 } else {
45 face->weak_ref();
46 }
reed@google.com2f3dc9d2011-05-02 17:33:45 +000047}
48
49SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
50 const Rec* curr = fArray.begin();
51 const Rec* stop = fArray.end();
52 while (curr < stop) {
53 if (curr->fFace->uniqueID() == fontID) {
54 return curr->fFace;
55 }
56 curr += 1;
57 }
58 return NULL;
59}
60
bungeman@google.coma02bc152012-05-16 18:21:56 +000061SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
reed@google.com2f3dc9d2011-05-02 17:33:45 +000062 const Rec* curr = fArray.begin();
63 const Rec* stop = fArray.end();
64 while (curr < stop) {
bungeman@google.coma02bc152012-05-16 18:21:56 +000065 SkTypeface* currFace = curr->fFace;
66 if (proc(currFace, curr->fRequestedStyle, ctx)) {
67 if (curr->fStrong) {
68 currFace->ref();
69 return currFace;
70 } else if (currFace->try_ref()) {
71 return currFace;
72 } else {
73 //remove currFace from fArray?
74 }
reed@google.com2f3dc9d2011-05-02 17:33:45 +000075 }
76 curr += 1;
77 }
78 return NULL;
79}
80
81void SkTypefaceCache::purge(int numToPurge) {
82 int count = fArray.count();
83 int i = 0;
84 while (i < count) {
85 SkTypeface* face = fArray[i].fFace;
bungeman@google.coma02bc152012-05-16 18:21:56 +000086 bool strong = fArray[i].fStrong;
bungeman@google.comf64c6842013-07-19 23:18:52 +000087 if ((strong && face->unique()) || (!strong && face->weak_expired())) {
bungeman@google.coma02bc152012-05-16 18:21:56 +000088 if (strong) {
89 face->unref();
90 } else {
91 face->weak_unref();
92 }
reed@google.com2f3dc9d2011-05-02 17:33:45 +000093 fArray.remove(i);
94 --count;
95 if (--numToPurge == 0) {
96 return;
97 }
98 } else {
99 ++i;
100 }
101 }
102}
103
reed@google.comd40da642011-10-20 13:18:37 +0000104void SkTypefaceCache::purgeAll() {
105 this->purge(fArray.count());
reed@google.comd40da642011-10-20 13:18:37 +0000106}
107
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000108///////////////////////////////////////////////////////////////////////////////
109
110SkTypefaceCache& SkTypefaceCache::Get() {
111 static SkTypefaceCache gCache;
112 return gCache;
113}
114
115SkFontID SkTypefaceCache::NewFontID() {
116 static int32_t gFontID;
117 return sk_atomic_inc(&gFontID) + 1;
118}
119
digit@google.com1771cbf2012-01-26 21:26:40 +0000120SK_DECLARE_STATIC_MUTEX(gMutex);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000121
bungeman@google.coma02bc152012-05-16 18:21:56 +0000122void SkTypefaceCache::Add(SkTypeface* face,
123 SkTypeface::Style requestedStyle,
124 bool strong) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000125 SkAutoMutexAcquire ama(gMutex);
bungeman@google.coma02bc152012-05-16 18:21:56 +0000126 Get().add(face, requestedStyle, strong);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000127}
128
129SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
130 SkAutoMutexAcquire ama(gMutex);
131 return Get().findByID(fontID);
132}
133
bungeman@google.comee51d1a2012-02-16 12:40:48 +0000134SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000135 SkAutoMutexAcquire ama(gMutex);
bungeman@google.coma02bc152012-05-16 18:21:56 +0000136 SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
bungeman@google.comee51d1a2012-02-16 12:40:48 +0000137 return typeface;
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000138}
139
reed@google.comd40da642011-10-20 13:18:37 +0000140void SkTypefaceCache::PurgeAll() {
bungeman@google.comee51d1a2012-02-16 12:40:48 +0000141 SkAutoMutexAcquire ama(gMutex);
reed@google.comd40da642011-10-20 13:18:37 +0000142 Get().purgeAll();
143}
144
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000145///////////////////////////////////////////////////////////////////////////////
146
147#ifdef SK_DEBUG
148static bool DumpProc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
149 SkDebugf("SkTypefaceCache: face %p fontID %d style %d refcnt %d\n",
150 face, face->uniqueID(), style, face->getRefCnt());
151 return false;
152}
153#endif
154
155void SkTypefaceCache::Dump() {
156#ifdef SK_DEBUG
157 SkAutoMutexAcquire ama(gMutex);
bungeman@google.coma02bc152012-05-16 18:21:56 +0000158 (void)Get().findByProcAndRef(DumpProc, NULL);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000159#endif
160}