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 | #include "include/private/SkMutex.h" |
9 | #include "src/core/SkTypefaceCache.h" |
10 | #include <atomic> |
11 | |
12 | #define TYPEFACE_CACHE_LIMIT 1024 |
13 | |
14 | SkTypefaceCache::SkTypefaceCache() {} |
15 | |
16 | void SkTypefaceCache::add(sk_sp<SkTypeface> face) { |
17 | if (fTypefaces.count() >= TYPEFACE_CACHE_LIMIT) { |
18 | this->purge(TYPEFACE_CACHE_LIMIT >> 2); |
19 | } |
20 | |
21 | fTypefaces.emplace_back(std::move(face)); |
22 | } |
23 | |
24 | sk_sp<SkTypeface> SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const { |
25 | for (const sk_sp<SkTypeface>& typeface : fTypefaces) { |
26 | if (proc(typeface.get(), ctx)) { |
27 | return typeface; |
28 | } |
29 | } |
30 | return nullptr; |
31 | } |
32 | |
33 | void SkTypefaceCache::purge(int numToPurge) { |
34 | int count = fTypefaces.count(); |
35 | int i = 0; |
36 | while (i < count) { |
37 | if (fTypefaces[i]->unique()) { |
38 | fTypefaces.removeShuffle(i); |
39 | --count; |
40 | if (--numToPurge == 0) { |
41 | return; |
42 | } |
43 | } else { |
44 | ++i; |
45 | } |
46 | } |
47 | } |
48 | |
49 | void SkTypefaceCache::purgeAll() { |
50 | this->purge(fTypefaces.count()); |
51 | } |
52 | |
53 | /////////////////////////////////////////////////////////////////////////////// |
54 | |
55 | SkTypefaceCache& SkTypefaceCache::Get() { |
56 | static SkTypefaceCache gCache; |
57 | return gCache; |
58 | } |
59 | |
60 | SkFontID SkTypefaceCache::NewFontID() { |
61 | static std::atomic<int32_t> nextID{1}; |
62 | return nextID++; |
63 | } |
64 | |
65 | static SkMutex& typeface_cache_mutex() { |
66 | static SkMutex& mutex = *(new SkMutex); |
67 | return mutex; |
68 | } |
69 | |
70 | void SkTypefaceCache::Add(sk_sp<SkTypeface> face) { |
71 | SkAutoMutexExclusive ama(typeface_cache_mutex()); |
72 | Get().add(std::move(face)); |
73 | } |
74 | |
75 | sk_sp<SkTypeface> SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) { |
76 | SkAutoMutexExclusive ama(typeface_cache_mutex()); |
77 | return Get().findByProcAndRef(proc, ctx); |
78 | } |
79 | |
80 | void SkTypefaceCache::PurgeAll() { |
81 | SkAutoMutexExclusive ama(typeface_cache_mutex()); |
82 | Get().purgeAll(); |
83 | } |
84 | |
85 | /////////////////////////////////////////////////////////////////////////////// |
86 | |
87 | #ifdef SK_DEBUG |
88 | static bool DumpProc(SkTypeface* face, void* ctx) { |
89 | SkString n; |
90 | face->getFamilyName(&n); |
91 | SkFontStyle s = face->fontStyle(); |
92 | SkFontID id = face->uniqueID(); |
93 | SkDebugf("SkTypefaceCache: face %p fontID %d weight %d width %d style %d name %s\n" , |
94 | face, id, s.weight(), s.width(), s.slant(), n.c_str()); |
95 | return false; |
96 | } |
97 | #endif |
98 | |
99 | void SkTypefaceCache::Dump() { |
100 | #ifdef SK_DEBUG |
101 | (void)Get().findByProcAndRef(DumpProc, nullptr); |
102 | #endif |
103 | } |
104 | |