1/* 2 * Copyright 2014 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 "SkFontMgr.h" 9#include "SkFontMgr_indirect.h" 10#include "SkFontStyle.h" 11#include "SkMutex.h" 12#include "SkOnce.h" 13#include "SkRefCnt.h" 14#include "SkRemotableFontMgr.h" 15#include "SkStream.h" 16#include "SkString.h" 17#include "SkTArray.h" 18#include "SkTypeface.h" 19#include "SkTypes.h" 20#include "SkTemplates.h" 21 22class SkData; 23 24class SkStyleSet_Indirect : public SkFontStyleSet { 25public: 26 /** Takes ownership of the SkRemotableFontIdentitySet. */ 27 SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex, 28 SkRemotableFontIdentitySet* data) 29 : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data) 30 { } 31 32 int count() override { return fData->count(); } 33 34 void getStyle(int index, SkFontStyle* fs, SkString* style) override { 35 if (fs) { 36 *fs = fData->at(index).fFontStyle; 37 } 38 if (style) { 39 // TODO: is this useful? Current locale? 40 style->reset(); 41 } 42 } 43 44 SkTypeface* createTypeface(int index) override { 45 return fOwner->createTypefaceFromFontId(fData->at(index)); 46 } 47 48 SkTypeface* matchStyle(const SkFontStyle& pattern) override { 49 if (fFamilyIndex >= 0) { 50 SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern); 51 return fOwner->createTypefaceFromFontId(id); 52 } 53 54 return this->matchStyleCSS3(pattern); 55 } 56private: 57 sk_sp<const SkFontMgr_Indirect> fOwner; 58 int fFamilyIndex; 59 sk_sp<SkRemotableFontIdentitySet> fData; 60}; 61 62int SkFontMgr_Indirect::onCountFamilies() const { 63 return 0; 64} 65 66void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const { 67 SkFAIL("Not implemented"); 68} 69 70SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const { 71 SkFAIL("Not implemented"); 72 return nullptr; 73} 74 75SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const { 76 return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName)); 77} 78 79SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const { 80 if (id.fDataId == SkFontIdentity::kInvalidDataId) { 81 return nullptr; 82 } 83 84 SkAutoMutexAcquire ama(fDataCacheMutex); 85 86 sk_sp<SkTypeface> dataTypeface; 87 int dataTypefaceIndex = 0; 88 for (int i = 0; i < fDataCache.count(); ++i) { 89 const DataEntry& entry = fDataCache[i]; 90 if (entry.fDataId == id.fDataId) { 91 if (entry.fTtcIndex == id.fTtcIndex && 92 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) 93 { 94 return entry.fTypeface; 95 } 96 if (dataTypeface.get() == nullptr && 97 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) 98 { 99 dataTypeface.reset(entry.fTypeface); 100 dataTypefaceIndex = entry.fTtcIndex; 101 } 102 } 103 104 if (entry.fTypeface->weak_expired()) { 105 fDataCache.removeShuffle(i); 106 --i; 107 } 108 } 109 110 // No exact match, but did find a data match. 111 if (dataTypeface.get() != nullptr) { 112 std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr)); 113 if (stream.get() != nullptr) { 114 return fImpl->createFromStream(stream.release(), dataTypefaceIndex); 115 } 116 } 117 118 // No data match, request data and add entry. 119 std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId)); 120 if (stream.get() == nullptr) { 121 return nullptr; 122 } 123 124 sk_sp<SkTypeface> typeface(fImpl->createFromStream(stream.release(), id.fTtcIndex)); 125 if (typeface.get() == nullptr) { 126 return nullptr; 127 } 128 129 DataEntry& newEntry = fDataCache.push_back(); 130 typeface->weak_ref(); 131 newEntry.fDataId = id.fDataId; 132 newEntry.fTtcIndex = id.fTtcIndex; 133 newEntry.fTypeface = typeface.get(); // weak reference passed to new entry. 134 135 return typeface.release(); 136} 137 138SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[], 139 const SkFontStyle& fontStyle) const { 140 SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle); 141 return this->createTypefaceFromFontId(id); 142} 143 144SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[], 145 const SkFontStyle& style, 146 const char* bcp47[], 147 int bcp47Count, 148 SkUnichar character) const { 149 SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47, 150 bcp47Count, character); 151 return this->createTypefaceFromFontId(id); 152} 153 154SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember, 155 const SkFontStyle& fontStyle) const { 156 SkString familyName; 157 familyMember->getFamilyName(&familyName); 158 return this->matchFamilyStyle(familyName.c_str(), fontStyle); 159} 160 161SkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const { 162 return fImpl->createFromStream(stream, ttcIndex); 163} 164 165SkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex) const { 166 return fImpl->createFromFile(path, ttcIndex); 167} 168 169SkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) const { 170 return fImpl->createFromData(data, ttcIndex); 171} 172 173SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[], 174 SkFontStyle style) const { 175 sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style)); 176 177 if (nullptr == face.get()) { 178 face.reset(this->matchFamilyStyle(nullptr, style)); 179 } 180 181 if (nullptr == face.get()) { 182 SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style); 183 face.reset(this->createTypefaceFromFontId(fontId)); 184 } 185 186 return face.release(); 187} 188