OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2008 Google Inc. | 2 * Copyright 2008 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkFontConfigInterface.h" | 8 #include "SkFontConfigInterface.h" |
9 #include "SkFontConfigTypeface.h" | 9 #include "SkFontMgr.h" |
10 #include "SkFontDescriptor.h" | 10 #include "SkMutex.h" |
11 #include "SkStream.h" | 11 #include "SkRefCnt.h" |
12 #include "SkTemplates.h" | |
13 #include "SkTypeface.h" | |
14 #include "SkTypefaceCache.h" | |
15 #include "SkResourceCache.h" | |
16 | |
17 /////////////////////////////////////////////////////////////////////////////// | |
18 /////////////////////////////////////////////////////////////////////////////// | |
19 | 12 |
20 SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex); | 13 SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex); |
21 static SkFontConfigInterface* gFontConfigInterface; | 14 static SkFontConfigInterface* gFontConfigInterface; |
22 | 15 |
23 SkFontConfigInterface* SkFontConfigInterface::RefGlobal() { | 16 SkFontConfigInterface* SkFontConfigInterface::RefGlobal() { |
24 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); | 17 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
25 | 18 |
26 return SkSafeRef(gFontConfigInterface); | 19 return SkSafeRef(gFontConfigInterface); |
27 } | 20 } |
28 | 21 |
29 SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* f
c) { | 22 SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* f
c) { |
30 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); | 23 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
31 | 24 |
32 SkRefCnt_SafeAssign(gFontConfigInterface, fc); | 25 SkRefCnt_SafeAssign(gFontConfigInterface, fc); |
33 return fc; | 26 return fc; |
34 } | 27 } |
35 | 28 |
36 /////////////////////////////////////////////////////////////////////////////// | 29 /////////////////////////////////////////////////////////////////////////////// |
37 /////////////////////////////////////////////////////////////////////////////// | |
38 | |
39 // convenience function to create the direct interface if none is installed. | |
40 extern SkFontConfigInterface* SkCreateDirectFontConfigInterface(); | |
41 | |
42 static SkFontConfigInterface* RefFCI() { | |
43 for (;;) { | |
44 SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal(); | |
45 if (fci) { | |
46 return fci; | |
47 } | |
48 fci = SkFontConfigInterface::GetSingletonDirectInterface(&gFontConfigInt
erfaceMutex); | |
49 SkFontConfigInterface::SetGlobal(fci); | |
50 } | |
51 } | |
52 | |
53 // export this to SkFontMgr_fontconfig.cpp until this file just goes away. | |
54 SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); | |
55 SkFontConfigInterface* SkFontHost_fontconfig_ref_global() { | |
56 return RefFCI(); | |
57 } | |
58 | |
59 /////////////////////////////////////////////////////////////////////////////// | |
60 | 30 |
61 static bool find_by_FontIdentity(SkTypeface* cachedTypeface, void* ctx) { | 31 static SkFontConfigInterface* init_FCI() { |
62 typedef SkFontConfigInterface::FontIdentity FontIdentity; | 32 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
63 FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cach
edTypeface); | |
64 FontIdentity* identity = static_cast<FontIdentity*>(ctx); | |
65 | 33 |
66 return cachedFCTypeface->getIdentity() == *identity; | 34 if (gFontConfigInterface) { |
| 35 return SkRef(gFontConfigInterface); |
| 36 } |
| 37 gFontConfigInterface = SkRef(SkFontConfigInterface::GetSingletonDirectInterf
ace()); |
| 38 return gFontConfigInterface; |
67 } | 39 } |
68 | 40 |
69 SK_DECLARE_STATIC_MUTEX(gSkFontHostRequestCacheMutex); | 41 SkFontMgr* SkFontMgr::Factory() { |
70 class SkFontHostRequestCache { | 42 SkFontConfigInterface* fci = init_FCI(); |
71 | 43 return fci ? SkFontMgr_New_FCI(fci) : nullptr; |
72 // The value of maxSize here is a compromise between cache hits and cache si
ze. | |
73 // See https://crbug.com/424082#63 for reason for current size. | |
74 static const size_t gMaxSize = 1 << 15; | |
75 | |
76 static SkFontHostRequestCache& Get() { | |
77 gSkFontHostRequestCacheMutex.assertHeld(); | |
78 static SkFontHostRequestCache gCache(gMaxSize); | |
79 return gCache; | |
80 } | |
81 | |
82 public: | |
83 struct Request : public SkResourceCache::Key { | |
84 private: | |
85 Request(const char* name, size_t nameLen, const SkFontStyle& style) : fS
tyle(style) { | |
86 /** Pointer to just after the last field of this class. */ | |
87 char* content = const_cast<char*>(SkTAfter<const char>(&this->fStyle
)); | |
88 | |
89 // No holes. | |
90 SkASSERT(SkTAddOffset<char>(this, sizeof(SkResourceCache::Key) + key
Size) == content); | |
91 | |
92 // Has a size divisible by size of uint32_t. | |
93 SkASSERT((content - reinterpret_cast<char*>(this)) % sizeof(uint32_t
) == 0); | |
94 | |
95 size_t contentLen = SkAlign4(nameLen); | |
96 sk_careful_memcpy(content, name, nameLen); | |
97 sk_bzero(content + nameLen, contentLen - nameLen); | |
98 this->init(&gSkFontHostRequestCacheMutex, 0, keySize + contentLen); | |
99 } | |
100 const SkFontStyle fStyle; | |
101 /** The sum of the sizes of the fields of this class. */ | |
102 static const size_t keySize = sizeof(fStyle); | |
103 | |
104 public: | |
105 static Request* Create(const char* name, const SkFontStyle& style) { | |
106 size_t nameLen = name ? strlen(name) : 0; | |
107 size_t contentLen = SkAlign4(nameLen); | |
108 char* storage = new char[sizeof(Request) + contentLen]; | |
109 return new (storage) Request(name, nameLen, style); | |
110 } | |
111 void operator delete(void* storage) { | |
112 delete[] reinterpret_cast<char*>(storage); | |
113 } | |
114 }; | |
115 | |
116 | |
117 private: | |
118 struct Result : public SkResourceCache::Rec { | |
119 Result(Request* request, SkTypeface* typeface) | |
120 : fRequest(request) | |
121 , fFace(SkSafeRef(typeface)) {} | |
122 Result(Result&&) = default; | |
123 Result& operator=(Result&&) = default; | |
124 | |
125 const Key& getKey() const override { return *fRequest; } | |
126 size_t bytesUsed() const override { return fRequest->size() + sizeof(fFa
ce); } | |
127 const char* getCategory() const override { return "request_cache"; } | |
128 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { r
eturn nullptr; } | |
129 | |
130 SkAutoTDelete<Request> fRequest; | |
131 SkAutoTUnref<SkTypeface> fFace; | |
132 }; | |
133 | |
134 SkResourceCache fCachedResults; | |
135 | |
136 public: | |
137 SkFontHostRequestCache(size_t maxSize) : fCachedResults(maxSize) {} | |
138 | |
139 /** Takes ownership of request. It will be deleted when no longer needed. */ | |
140 void add(SkTypeface* face, Request* request) { | |
141 fCachedResults.add(new Result(request, face)); | |
142 } | |
143 /** Does not take ownership of request. */ | |
144 SkTypeface* findAndRef(Request* request) { | |
145 SkTypeface* face = nullptr; | |
146 fCachedResults.find(*request, [](const SkResourceCache::Rec& rec, void*
context) -> bool { | |
147 const Result& result = static_cast<const Result&>(rec); | |
148 SkTypeface** face = static_cast<SkTypeface**>(context); | |
149 | |
150 *face = result.fFace; | |
151 return true; | |
152 }, &face); | |
153 return SkSafeRef(face); | |
154 } | |
155 | |
156 /** Takes ownership of request. It will be deleted when no longer needed. */ | |
157 static void Add(SkTypeface* face, Request* request) { | |
158 SkAutoMutexAcquire ama(gSkFontHostRequestCacheMutex); | |
159 Get().add(face, request); | |
160 } | |
161 | |
162 /** Does not take ownership of request. */ | |
163 static SkTypeface* FindAndRef(Request* request) { | |
164 SkAutoMutexAcquire ama(gSkFontHostRequestCacheMutex); | |
165 return Get().findAndRef(request); | |
166 } | |
167 }; | |
168 | |
169 SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char requestedFamilyN
ame[], | |
170 SkFontStyle requestedStyle) | |
171 { | |
172 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); | |
173 if (nullptr == fci.get()) { | |
174 return nullptr; | |
175 } | |
176 | |
177 // Check if this request is already in the request cache. | |
178 using Request = SkFontHostRequestCache::Request; | |
179 SkAutoTDelete<Request> request(Request::Create(requestedFamilyName, requeste
dStyle)); | |
180 SkTypeface* face = SkFontHostRequestCache::FindAndRef(request); | |
181 if (face) { | |
182 return face; | |
183 } | |
184 | |
185 SkFontConfigInterface::FontIdentity identity; | |
186 SkString outFamilyName; | |
187 SkFontStyle outStyle; | |
188 if (!fci->matchFamilyName(requestedFamilyName, requestedStyle, | |
189 &identity, &outFamilyName, &outStyle)) | |
190 { | |
191 return nullptr; | |
192 } | |
193 | |
194 // Check if a typeface with this FontIdentity is already in the FontIdentity
cache. | |
195 face = SkTypefaceCache::FindByProcAndRef(find_by_FontIdentity, &identity); | |
196 if (!face) { | |
197 face = FontConfigTypeface::Create(outStyle, identity, outFamilyName); | |
198 // Add this FontIdentity to the FontIdentity cache. | |
199 SkTypefaceCache::Add(face); | |
200 } | |
201 // Add this request to the request cache. | |
202 SkFontHostRequestCache::Add(face, request.release()); | |
203 | |
204 return face; | |
205 } | 44 } |
206 | |
207 /////////////////////////////////////////////////////////////////////////////// | |
208 | |
209 SkStreamAsset* FontConfigTypeface::onOpenStream(int* ttcIndex) const { | |
210 SkStreamAsset* stream = this->getLocalStream(); | |
211 if (stream) { | |
212 // TODO: should have been provided by CreateFromStream() | |
213 *ttcIndex = 0; | |
214 return stream->duplicate(); | |
215 } | |
216 | |
217 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); | |
218 if (nullptr == fci.get()) { | |
219 return nullptr; | |
220 } | |
221 | |
222 *ttcIndex = this->getIdentity().fTTCIndex; | |
223 return fci->openStream(this->getIdentity()); | |
224 } | |
225 | |
226 void FontConfigTypeface::onGetFamilyName(SkString* familyName) const { | |
227 *familyName = fFamilyName; | |
228 } | |
229 | |
230 void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | |
231 bool* isLocalStream) const { | |
232 SkString name; | |
233 this->getFamilyName(&name); | |
234 desc->setFamilyName(name.c_str()); | |
235 *isLocalStream = SkToBool(this->getLocalStream()); | |
236 } | |
OLD | NEW |