OLD | NEW |
(Empty) | |
| 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_indirect.h" |
| 9 |
| 10 #include "SkDataTable.h" |
| 11 #include "SkFontStyle.h" |
| 12 #include "SkOnce.h" |
| 13 #include "SkStream.h" |
| 14 #include "SkTSearch.h" |
| 15 #include "SkTypeface.h" |
| 16 |
| 17 class SkData; |
| 18 class SkString; |
| 19 |
| 20 class SkStyleSet_Indirect : public SkFontStyleSet { |
| 21 public: |
| 22 /** Takes ownership of the SkRemotableFontIdentitySet. */ |
| 23 SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex, |
| 24 SkRemotableFontIdentitySet* data) |
| 25 : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data) |
| 26 { } |
| 27 |
| 28 virtual int count() SK_OVERRIDE { return fData->count(); } |
| 29 |
| 30 virtual void getStyle(int index, SkFontStyle* fs, SkString* style) SK_OVERRI
DE { |
| 31 if (fs) { |
| 32 *fs = fData->at(index).fFontStyle; |
| 33 } |
| 34 if (style) { |
| 35 // TODO: is this useful? Current locale? |
| 36 style->reset(); |
| 37 } |
| 38 } |
| 39 |
| 40 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { |
| 41 return fOwner->createTypefaceFromFontId(fData->at(index)); |
| 42 } |
| 43 |
| 44 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { |
| 45 if (fFamilyIndex >= 0) { |
| 46 SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pa
ttern); |
| 47 return fOwner->createTypefaceFromFontId(id); |
| 48 } |
| 49 |
| 50 // If this SkStyleSet was created via onMatchFamily we would need a call
like |
| 51 // fOwner->fProxy->matchNameStyle(fFamilyName, pattern); |
| 52 // but would not activate fonts (only consider fonts which would come ba
ck from matchName). |
| 53 |
| 54 // CSS policy sounds good. |
| 55 struct Score { |
| 56 int score; |
| 57 int index; |
| 58 }; |
| 59 |
| 60 // Width has the greatest priority. |
| 61 // If the value of pattern.width is 5 (normal) or less, |
| 62 // narrower width values are checked first, then wider values. |
| 63 // If the value of pattern.width is greater than 5 (normal), |
| 64 // wider values are checked first, followed by narrower values. |
| 65 |
| 66 // Italic/Oblique has the next highest priority. |
| 67 // If italic requested and there is some italic font, use it. |
| 68 // If oblique requested and there is some oblique font, use it. |
| 69 // If italic requested and there is some oblique font, use it. |
| 70 // If oblique requested and there is some italic font, use it. |
| 71 |
| 72 // Exact match. |
| 73 // If pattern.weight < 400, weights below pattern.weight are checked |
| 74 // in descending order followed by weights above pattern.weight |
| 75 // in ascending order until a match is found. |
| 76 // If pattern.weight > 500, weights above pattern.weight are checked |
| 77 // in ascending order followed by weights below pattern.weight |
| 78 // in descending order until a match is found. |
| 79 // If pattern.weight is 400, 500 is checked first |
| 80 // and then the rule for pattern.weight < 400 is used. |
| 81 // If pattern.weight is 500, 400 is checked first |
| 82 // and then the rule for pattern.weight < 400 is used |
| 83 |
| 84 Score maxScore = { 0, 0 }; |
| 85 for (int i = 0; i < fData->count(); ++i) { |
| 86 const SkFontStyle& current = fData->at(i).fFontStyle; |
| 87 Score currentScore = { 0, i }; |
| 88 |
| 89 // CSS stretch. (This is the width.) |
| 90 // This has the highest priority. |
| 91 if (pattern.width() <= SkFontStyle::kNormal_Width) { |
| 92 if (current.width() <= pattern.width()) { |
| 93 currentScore.score += 10 - pattern.width() + current.width()
; |
| 94 } else { |
| 95 currentScore.score += 10 - current.width(); |
| 96 } |
| 97 } else { |
| 98 if (current.width() > pattern.width()) { |
| 99 currentScore.score += 10 + pattern.width() - current.width()
; |
| 100 } else { |
| 101 currentScore.score += current.width(); |
| 102 } |
| 103 } |
| 104 currentScore.score *= 1002; |
| 105 |
| 106 // CSS style (italic/oblique) |
| 107 // Being italic trumps all valid weights which are not italic. |
| 108 // Note that newer specs differentiate between italic and oblique. |
| 109 if (pattern.isItalic() && current.isItalic()) { |
| 110 currentScore.score += 1001; |
| 111 } |
| 112 |
| 113 // Synthetics (weight/style) [no stretch synthetic?] |
| 114 |
| 115 // The 'closer' to the target weight, the higher the score. |
| 116 // 1000 is the 'heaviest' recognized weight |
| 117 if (pattern.weight() == current.weight()) { |
| 118 currentScore.score += 1000; |
| 119 } else if (pattern.weight() <= 500) { |
| 120 if (pattern.weight() >= 400 && pattern.weight() < 450) { |
| 121 if (current.weight() >= 450 && current.weight() <= 500) { |
| 122 // Artificially boost the 500 weight. |
| 123 // TODO: determine correct number to use. |
| 124 currentScore.score += 500; |
| 125 } |
| 126 } |
| 127 if (current.weight() <= pattern.weight()) { |
| 128 currentScore.score += 1000 - pattern.weight() + current.weig
ht(); |
| 129 } else { |
| 130 currentScore.score += 1000 - current.weight(); |
| 131 } |
| 132 } else if (pattern.weight() > 500) { |
| 133 if (current.weight() > pattern.weight()) { |
| 134 currentScore.score += 1000 + pattern.weight() - current.weig
ht(); |
| 135 } else { |
| 136 currentScore.score += current.weight(); |
| 137 } |
| 138 } |
| 139 |
| 140 if (currentScore.score > maxScore.score) { |
| 141 maxScore = currentScore; |
| 142 } |
| 143 } |
| 144 |
| 145 return this->createTypeface(maxScore.index); |
| 146 } |
| 147 private: |
| 148 SkAutoTUnref<const SkFontMgr_Indirect> fOwner; |
| 149 int fFamilyIndex; |
| 150 SkAutoTUnref<SkRemotableFontIdentitySet> fData; |
| 151 }; |
| 152 |
| 153 void SkFontMgr_Indirect::set_up_family_names(const SkFontMgr_Indirect* self) { |
| 154 self->fFamilyNames.reset(self->fProxy->getFamilyNames()); |
| 155 } |
| 156 |
| 157 int SkFontMgr_Indirect::onCountFamilies() const { |
| 158 SkOnce(&fOnce, SkFontMgr_Indirect::set_up_family_names, this); |
| 159 return fFamilyNames->count(); |
| 160 } |
| 161 |
| 162 void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const
{ |
| 163 SkOnce(&fOnce, SkFontMgr_Indirect::set_up_family_names, this); |
| 164 if (index >= fFamilyNames->count()) { |
| 165 familyName->reset(); |
| 166 return; |
| 167 } |
| 168 familyName->set(fFamilyNames->atStr(index)); |
| 169 } |
| 170 |
| 171 SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const { |
| 172 SkRemotableFontIdentitySet* set = fProxy->getIndex(index); |
| 173 if (NULL == set) { |
| 174 return NULL; |
| 175 } |
| 176 return SkNEW_ARGS(SkStyleSet_Indirect, (this, index, set)); |
| 177 } |
| 178 |
| 179 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const
{ |
| 180 return SkNEW_ARGS(SkStyleSet_Indirect, (this, -1, fProxy->matchName(familyNa
me))); |
| 181 } |
| 182 |
| 183 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& i
d) const { |
| 184 if (id.fDataId == SkFontIdentity::kInvalidDataId) { |
| 185 return NULL; |
| 186 } |
| 187 |
| 188 SkAutoMutexAcquire ama(fDataCacheMutex); |
| 189 |
| 190 SkAutoTUnref<SkTypeface> dataTypeface; |
| 191 int dataTypefaceIndex = 0; |
| 192 for (int i = 0; i < fDataCache.count(); ++i) { |
| 193 const DataEntry& entry = fDataCache[i]; |
| 194 if (entry.fDataId == id.fDataId) { |
| 195 if (entry.fTtcIndex == id.fTtcIndex && |
| 196 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) |
| 197 { |
| 198 return entry.fTypeface; |
| 199 } |
| 200 if (dataTypeface.get() == NULL && |
| 201 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) |
| 202 { |
| 203 dataTypeface.reset(entry.fTypeface); |
| 204 dataTypefaceIndex = entry.fTtcIndex; |
| 205 } |
| 206 } |
| 207 |
| 208 if (entry.fTypeface->weak_expired()) { |
| 209 fDataCache.removeShuffle(i); |
| 210 --i; |
| 211 } |
| 212 } |
| 213 |
| 214 // No exact match, but did find a data match. |
| 215 if (dataTypeface.get() != NULL) { |
| 216 SkAutoTUnref<SkStream> stream(dataTypeface->openStream(NULL)); |
| 217 if (stream.get() != NULL) { |
| 218 return fImpl->createFromStream(stream.get(), dataTypefaceIndex); |
| 219 } |
| 220 } |
| 221 |
| 222 // No data match, request data and add entry. |
| 223 SkAutoTUnref<SkStreamAsset> stream(fProxy->getData(id.fDataId)); |
| 224 if (stream.get() == NULL) { |
| 225 return NULL; |
| 226 } |
| 227 |
| 228 SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream, id.fTtcInd
ex)); |
| 229 if (typeface.get() == NULL) { |
| 230 return NULL; |
| 231 } |
| 232 |
| 233 DataEntry& newEntry = fDataCache.push_back(); |
| 234 typeface->weak_ref(); |
| 235 newEntry.fDataId = id.fDataId; |
| 236 newEntry.fTtcIndex = id.fTtcIndex; |
| 237 newEntry.fTypeface = typeface.get(); // weak reference passed to new entry. |
| 238 |
| 239 return typeface.detach(); |
| 240 } |
| 241 |
| 242 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[], |
| 243 const SkFontStyle& fontStyle)
const { |
| 244 SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle); |
| 245 return this->createTypefaceFromFontId(id); |
| 246 } |
| 247 |
| 248 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyNam
e[], |
| 249 const SkFontStyle& s
tyle, |
| 250 const char bpc47[], |
| 251 uint32_t character)
const { |
| 252 SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bpc47
, character); |
| 253 return this->createTypefaceFromFontId(id); |
| 254 } |
| 255 |
| 256 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember, |
| 257 const SkFontStyle& fontStyle) c
onst { |
| 258 SkString familyName; |
| 259 familyMember->getFamilyName(&familyName); |
| 260 return this->matchFamilyStyle(familyName.c_str(), fontStyle); |
| 261 } |
| 262 |
| 263 SkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStream* stream, int ttcInde
x) const { |
| 264 return fImpl->createFromStream(stream, ttcIndex); |
| 265 } |
| 266 |
| 267 SkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex
) const { |
| 268 return fImpl->createFromFile(path, ttcIndex); |
| 269 } |
| 270 |
| 271 SkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) con
st { |
| 272 return fImpl->createFromData(data, ttcIndex); |
| 273 } |
| 274 |
| 275 SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[], |
| 276 unsigned styleBits) const
{ |
| 277 bool bold = SkToBool(styleBits & SkTypeface::kBold); |
| 278 bool italic = SkToBool(styleBits & SkTypeface::kItalic); |
| 279 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight |
| 280 : SkFontStyle::kNormal_Weight, |
| 281 SkFontStyle::kNormal_Width, |
| 282 italic ? SkFontStyle::kItalic_Slant |
| 283 : SkFontStyle::kUpright_Slant); |
| 284 |
| 285 SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style)); |
| 286 |
| 287 if (NULL == face.get()) { |
| 288 face.reset(this->matchFamilyStyle(NULL, style)); |
| 289 } |
| 290 |
| 291 if (NULL == face.get()) { |
| 292 SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style); |
| 293 face.reset(this->createTypefaceFromFontId(fontId)); |
| 294 } |
| 295 |
| 296 return face.detach(); |
| 297 } |
OLD | NEW |