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