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
16SkTypefaceCache::SkTypefaceCache() {}
17
18void 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
26SkTypeface* 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
35void 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
51void SkTypefaceCache::purgeAll() {
52    this->purge(fTypefaces.count());
53}
54
55///////////////////////////////////////////////////////////////////////////////
56
57SkTypefaceCache& SkTypefaceCache::Get() {
58    static SkTypefaceCache gCache;
59    return gCache;
60}
61
62SkFontID SkTypefaceCache::NewFontID() {
63    static int32_t gFontID;
64    return sk_atomic_inc(&gFontID) + 1;
65}
66
67SK_DECLARE_STATIC_MUTEX(gMutex);
68
69void SkTypefaceCache::Add(SkTypeface* face) {
70    SkAutoMutexAcquire ama(gMutex);
71    Get().add(face);
72}
73
74SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
75    SkAutoMutexAcquire ama(gMutex);
76    return Get().findByProcAndRef(proc, ctx);
77}
78
79void SkTypefaceCache::PurgeAll() {
80    SkAutoMutexAcquire ama(gMutex);
81    Get().purgeAll();
82}
83
84///////////////////////////////////////////////////////////////////////////////
85
86#ifdef SK_DEBUG
87static 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
98void SkTypefaceCache::Dump() {
99#ifdef SK_DEBUG
100    (void)Get().findByProcAndRef(DumpProc, nullptr);
101#endif
102}
103