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