1 /* 2 * Copyright 2013 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 "SkFontConfigInterface.h" 9 #include "SkFontConfigTypeface.h" 10 #include "SkFontDescriptor.h" 11 #include "SkFontMgr.h" 12 #include "SkFontMgr_FontConfigInterface.h" 13 #include "SkFontStyle.h" 14 #include "SkMakeUnique.h" 15 #include "SkMutex.h" 16 #include "SkString.h" 17 #include "SkTypeface.h" 18 #include "SkTypefaceCache.h" 19 #include "SkResourceCache.h" 20 #include <new> 21 22 SkStreamAsset* SkTypeface_FCI::onOpenStream(int* ttcIndex) const { 23 *ttcIndex = this->getIdentity().fTTCIndex; 24 25 if (fFontData) { 26 SkStreamAsset* stream = fFontData->getStream(); 27 if (!stream) { 28 return nullptr; 29 } 30 return stream->duplicate().release(); 31 } 32 33 return fFCI->openStream(this->getIdentity()); 34 } 35 36 std::unique_ptr<SkFontData> SkTypeface_FCI::onMakeFontData() const { 37 if (fFontData) { 38 return skstd::make_unique<SkFontData>(*fFontData); 39 } 40 41 const SkFontConfigInterface::FontIdentity& id = this->getIdentity(); 42 return skstd::make_unique<SkFontData>(std::unique_ptr<SkStreamAsset>(fFCI->openStream(id)), 43 id.fTTCIndex, nullptr, 0); 44 } 45 46 void SkTypeface_FCI::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocalStream) const { 47 SkString name; 48 this->getFamilyName(&name); 49 desc->setFamilyName(name.c_str()); 50 desc->setStyle(this->fontStyle()); 51 *isLocalStream = SkToBool(fFontData); 52 } 53 54 /////////////////////////////////////////////////////////////////////////////// 55 56 class SkFontStyleSet_FCI : public SkFontStyleSet { 57 public: 58 SkFontStyleSet_FCI() {} 59 60 int count() override { return 0; } 61 void getStyle(int index, SkFontStyle*, SkString* style) override { SkASSERT(false); } 62 SkTypeface* createTypeface(int index) override { SkASSERT(false); return nullptr; } 63 SkTypeface* matchStyle(const SkFontStyle& pattern) override { return nullptr; } 64 }; 65 66 /////////////////////////////////////////////////////////////////////////////// 67 68 class SkFontRequestCache { 69 public: 70 struct Request : public SkResourceCache::Key { 71 private: 72 Request(const char* name, size_t nameLen, const SkFontStyle& style) : fStyle(style) { 73 /** Pointer to just after the last field of this class. */ 74 char* content = const_cast<char*>(SkTAfter<const char>(&this->fStyle)); 75 76 // No holes. 77 SkASSERT(SkTAddOffset<char>(this, sizeof(SkResourceCache::Key) + keySize) == content); 78 79 // Has a size divisible by size of uint32_t. 80 SkASSERT((content - reinterpret_cast<char*>(this)) % sizeof(uint32_t) == 0); 81 82 size_t contentLen = SkAlign4(nameLen); 83 sk_careful_memcpy(content, name, nameLen); 84 sk_bzero(content + nameLen, contentLen - nameLen); 85 this->init(nullptr, 0, keySize + contentLen); 86 } 87 const SkFontStyle fStyle; 88 /** The sum of the sizes of the fields of this class. */ 89 static const size_t keySize = sizeof(fStyle); 90 91 public: 92 static Request* Create(const char* name, const SkFontStyle& style) { 93 size_t nameLen = name ? strlen(name) : 0; 94 size_t contentLen = SkAlign4(nameLen); 95 char* storage = new char[sizeof(Request) + contentLen]; 96 return new (storage) Request(name, nameLen, style); 97 } 98 void operator delete(void* storage) { 99 delete[] reinterpret_cast<char*>(storage); 100 } 101 }; 102 103 104 private: 105 struct Result : public SkResourceCache::Rec { 106 Result(Request* request, SkTypeface* typeface) 107 : fRequest(request) 108 , fFace(SkSafeRef(typeface)) {} 109 Result(Result&&) = default; 110 Result& operator=(Result&&) = default; 111 112 const Key& getKey() const override { return *fRequest; } 113 size_t bytesUsed() const override { return fRequest->size() + sizeof(fFace); } 114 const char* getCategory() const override { return "request_cache"; } 115 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; } 116 117 std::unique_ptr<Request> fRequest; 118 sk_sp<SkTypeface> fFace; 119 }; 120 121 SkResourceCache fCachedResults; 122 123 public: 124 SkFontRequestCache(size_t maxSize) : fCachedResults(maxSize) {} 125 126 /** Takes ownership of request. It will be deleted when no longer needed. */ 127 void add(SkTypeface* face, Request* request) { 128 fCachedResults.add(new Result(request, face)); 129 } 130 /** Does not take ownership of request. */ 131 SkTypeface* findAndRef(Request* request) { 132 SkTypeface* face = nullptr; 133 fCachedResults.find(*request, [](const SkResourceCache::Rec& rec, void* context) -> bool { 134 const Result& result = static_cast<const Result&>(rec); 135 SkTypeface** face = static_cast<SkTypeface**>(context); 136 137 *face = result.fFace.get(); 138 return true; 139 }, &face); 140 return SkSafeRef(face); 141 } 142 }; 143 144 /////////////////////////////////////////////////////////////////////////////// 145 146 static bool find_by_FontIdentity(SkTypeface* cachedTypeface, void* ctx) { 147 typedef SkFontConfigInterface::FontIdentity FontIdentity; 148 SkTypeface_FCI* cachedFCTypeface = static_cast<SkTypeface_FCI*>(cachedTypeface); 149 FontIdentity* identity = static_cast<FontIdentity*>(ctx); 150 151 return cachedFCTypeface->getIdentity() == *identity; 152 } 153 154 /////////////////////////////////////////////////////////////////////////////// 155 156 class SkFontMgr_FCI : public SkFontMgr { 157 sk_sp<SkFontConfigInterface> fFCI; 158 SkTypeface_FreeType::Scanner fScanner; 159 160 mutable SkMutex fMutex; 161 mutable SkTypefaceCache fTFCache; 162 163 // The value of maxSize here is a compromise between cache hits and cache size. 164 // See https://crbug.com/424082#63 for reason for current size. 165 static const size_t kMaxSize = 1 << 15; 166 mutable SkFontRequestCache fCache; 167 168 public: 169 SkFontMgr_FCI(sk_sp<SkFontConfigInterface> fci) 170 : fFCI(std::move(fci)) 171 , fCache(kMaxSize) 172 {} 173 174 protected: 175 int onCountFamilies() const override { 176 SK_ABORT("Not implemented."); 177 return 0; 178 } 179 180 void onGetFamilyName(int index, SkString* familyName) const override { 181 SK_ABORT("Not implemented."); 182 } 183 184 SkFontStyleSet* onCreateStyleSet(int index) const override { 185 SK_ABORT("Not implemented."); 186 return nullptr; 187 } 188 189 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { 190 SK_ABORT("Not implemented."); 191 return new SkFontStyleSet_FCI(); 192 } 193 194 SkTypeface* onMatchFamilyStyle(const char requestedFamilyName[], 195 const SkFontStyle& requestedStyle) const override 196 { 197 SkAutoMutexAcquire ama(fMutex); 198 199 SkFontConfigInterface::FontIdentity identity; 200 SkString outFamilyName; 201 SkFontStyle outStyle; 202 if (!fFCI->matchFamilyName(requestedFamilyName, requestedStyle, 203 &identity, &outFamilyName, &outStyle)) 204 { 205 return nullptr; 206 } 207 208 // Check if a typeface with this FontIdentity is already in the FontIdentity cache. 209 SkTypeface* face = fTFCache.findByProcAndRef(find_by_FontIdentity, &identity); 210 if (!face) { 211 face = SkTypeface_FCI::Create(fFCI, identity, std::move(outFamilyName), outStyle); 212 // Add this FontIdentity to the FontIdentity cache. 213 fTFCache.add(face); 214 } 215 return face; 216 } 217 218 SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 219 const char* bcp47[], int bcp47Count, 220 SkUnichar character) const override { 221 SK_ABORT("Not implemented."); 222 return nullptr; 223 } 224 225 SkTypeface* onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const override { 226 SK_ABORT("Not implemented."); 227 return nullptr; 228 } 229 230 sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override { 231 return this->onMakeFromStreamIndex(SkMemoryStream::Make(std::move(data)), ttcIndex); 232 } 233 234 sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream, 235 int ttcIndex) const override { 236 const size_t length = stream->getLength(); 237 if (!length) { 238 return nullptr; 239 } 240 if (length >= 1024 * 1024 * 1024) { 241 return nullptr; // don't accept too large fonts (>= 1GB) for safety. 242 } 243 244 // TODO should the caller give us the style or should we get it from freetype? 245 SkString name; 246 SkFontStyle style; 247 bool isFixedPitch = false; 248 if (!fScanner.scanFont(stream.get(), 0, &name, &style, &isFixedPitch, nullptr)) { 249 return nullptr; 250 } 251 252 auto fontData = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0); 253 return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name), 254 style, isFixedPitch)); 255 } 256 257 sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream, 258 const SkFontArguments& args) const override { 259 using Scanner = SkTypeface_FreeType::Scanner; 260 const size_t length = stream->getLength(); 261 if (!length) { 262 return nullptr; 263 } 264 if (length >= 1024 * 1024 * 1024) { 265 return nullptr; // don't accept too large fonts (>= 1GB) for safety. 266 } 267 268 bool isFixedPitch; 269 SkFontStyle style; 270 SkString name; 271 Scanner::AxisDefinitions axisDefinitions; 272 if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(), 273 &name, &style, &isFixedPitch, &axisDefinitions)) 274 { 275 return nullptr; 276 } 277 278 SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count()); 279 Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(), 280 axisValues, name); 281 282 auto fontData = skstd::make_unique<SkFontData>(std::move(stream), 283 args.getCollectionIndex(), 284 axisValues.get(), 285 axisDefinitions.count()); 286 return sk_sp<SkTypeface>(SkTypeface_FCI::Create(std::move(fontData), std::move(name), 287 style, isFixedPitch)); 288 } 289 290 sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override { 291 std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path); 292 return stream ? this->makeFromStream(std::move(stream), ttcIndex) : nullptr; 293 } 294 295 sk_sp<SkTypeface> onLegacyMakeTypeface(const char requestedFamilyName[], 296 SkFontStyle requestedStyle) const override 297 { 298 SkAutoMutexAcquire ama(fMutex); 299 300 // Check if this request is already in the request cache. 301 using Request = SkFontRequestCache::Request; 302 std::unique_ptr<Request> request(Request::Create(requestedFamilyName, requestedStyle)); 303 SkTypeface* face = fCache.findAndRef(request.get()); 304 if (face) { 305 return sk_sp<SkTypeface>(face); 306 } 307 308 SkFontConfigInterface::FontIdentity identity; 309 SkString outFamilyName; 310 SkFontStyle outStyle; 311 if (!fFCI->matchFamilyName(requestedFamilyName, requestedStyle, 312 &identity, &outFamilyName, &outStyle)) 313 { 314 return nullptr; 315 } 316 317 // Check if a typeface with this FontIdentity is already in the FontIdentity cache. 318 face = fTFCache.findByProcAndRef(find_by_FontIdentity, &identity); 319 if (!face) { 320 face = SkTypeface_FCI::Create(fFCI, identity, std::move(outFamilyName), outStyle); 321 // Add this FontIdentity to the FontIdentity cache. 322 fTFCache.add(face); 323 } 324 // Add this request to the request cache. 325 fCache.add(face, request.release()); 326 327 return sk_sp<SkTypeface>(face); 328 } 329 }; 330 331 SK_API sk_sp<SkFontMgr> SkFontMgr_New_FCI(sk_sp<SkFontConfigInterface> fci) { 332 SkASSERT(fci); 333 return sk_make_sp<SkFontMgr_FCI>(std::move(fci)); 334 } 335