| 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 |