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