OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkFontConfigParser_android.h" | 8 #include "SkFontConfigParser_android.h" |
9 #include "SkFontDescriptor.h" | 9 #include "SkFontDescriptor.h" |
10 #include "SkFontHost_FreeType_common.h" | 10 #include "SkFontHost_FreeType_common.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 private: | 52 private: |
53 typedef SkTypeface_FreeType INHERITED; | 53 typedef SkTypeface_FreeType INHERITED; |
54 }; | 54 }; |
55 | 55 |
56 class SkTypeface_AndroidSystem : public SkTypeface_Android { | 56 class SkTypeface_AndroidSystem : public SkTypeface_Android { |
57 public: | 57 public: |
58 SkTypeface_AndroidSystem(const SkString pathName, | 58 SkTypeface_AndroidSystem(const SkString pathName, |
59 int index, | 59 int index, |
60 Style style, | 60 Style style, |
61 bool isFixedPitch, | 61 bool isFixedPitch, |
62 const SkString familyName) | 62 const SkString familyName, |
63 const SkLanguage& lang, | |
64 SkPaintOptionsAndroid::FontVariant variant) | |
63 : INHERITED(index, style, isFixedPitch, familyName) | 65 : INHERITED(index, style, isFixedPitch, familyName) |
64 , fPathName(pathName) { } | 66 , fPathName(pathName) |
67 , fLang(lang) | |
68 , fVariant(variant) { } | |
65 | 69 |
66 virtual void onGetFontDescriptor(SkFontDescriptor* desc, | 70 virtual void onGetFontDescriptor(SkFontDescriptor* desc, |
67 bool* serialize) const SK_OVERRIDE { | 71 bool* serialize) const SK_OVERRIDE { |
68 SkASSERT(desc); | 72 SkASSERT(desc); |
69 SkASSERT(serialize); | 73 SkASSERT(serialize); |
70 desc->setFamilyName(fFamilyName.c_str()); | 74 desc->setFamilyName(fFamilyName.c_str()); |
71 desc->setFontFileName(fPathName.c_str()); | 75 desc->setFontFileName(fPathName.c_str()); |
72 *serialize = false; | 76 *serialize = false; |
73 } | 77 } |
74 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | 78 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
75 *ttcIndex = fIndex; | 79 *ttcIndex = fIndex; |
76 return SkStream::NewFromFile(fPathName.c_str()); | 80 return SkStream::NewFromFile(fPathName.c_str()); |
77 } | 81 } |
78 | 82 |
79 private: | 83 const SkString fPathName; |
80 SkString fPathName; | 84 const SkLanguage fLang; |
85 const SkPaintOptionsAndroid::FontVariant fVariant; | |
81 | 86 |
82 typedef SkTypeface_Android INHERITED; | 87 typedef SkTypeface_Android INHERITED; |
83 }; | 88 }; |
84 | 89 |
85 class SkTypeface_AndroidStream : public SkTypeface_Android { | 90 class SkTypeface_AndroidStream : public SkTypeface_Android { |
86 public: | 91 public: |
87 SkTypeface_AndroidStream(SkStream* stream, | 92 SkTypeface_AndroidStream(SkStream* stream, |
88 int index, | 93 int index, |
89 Style style, | 94 Style style, |
90 bool isFixedPitch, | 95 bool isFixedPitch, |
(...skipping 22 matching lines...) Expand all Loading... | |
113 }; | 118 }; |
114 | 119 |
115 void get_path_for_sys_fonts(SkString* full, const SkString& name) { | 120 void get_path_for_sys_fonts(SkString* full, const SkString& name) { |
116 full->set(getenv("ANDROID_ROOT")); | 121 full->set(getenv("ANDROID_ROOT")); |
117 full->append(SK_FONT_FILE_PREFIX); | 122 full->append(SK_FONT_FILE_PREFIX); |
118 full->append(name); | 123 full->append(name); |
119 } | 124 } |
120 | 125 |
121 class SkFontStyleSet_Android : public SkFontStyleSet { | 126 class SkFontStyleSet_Android : public SkFontStyleSet { |
122 public: | 127 public: |
123 explicit SkFontStyleSet_Android(FontFamily* family) { | 128 explicit SkFontStyleSet_Android(const FontFamily& family) { |
129 const SkString* cannonicalFamilyName = NULL; | |
130 if (family.fNames.count() > 0) { | |
131 cannonicalFamilyName = &family.fNames[0]; | |
132 } | |
124 // TODO? make this lazy | 133 // TODO? make this lazy |
125 for (int i = 0; i < family->fFontFiles.count(); ++i) { | 134 for (int i = 0; i < family.fFontFiles.count(); ++i) { |
126 const SkString& fileName = family->fFontFiles[i].fFileName; | 135 const FontFileInfo& fontFile = family.fFontFiles[i]; |
127 | 136 |
128 SkString pathName; | 137 SkString pathName; |
129 get_path_for_sys_fonts(&pathName, fileName); | 138 get_path_for_sys_fonts(&pathName, fontFile.fFileName); |
130 | 139 |
131 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str() )); | 140 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str() )); |
132 if (!stream.get()) { | 141 if (!stream.get()) { |
133 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, fileN ame.c_str())); | 142 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathN ame.c_str())); |
134 continue; | 143 continue; |
135 } | 144 } |
136 | 145 |
137 const int ttcIndex = family->fFontFiles[i].fIndex; | 146 const int ttcIndex = fontFile.fIndex; |
138 SkString fontName; | 147 SkString familyName; |
139 SkTypeface::Style style; | 148 SkTypeface::Style style; |
140 bool isFixedWidth; | 149 bool isFixedWidth; |
141 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, | 150 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, |
142 &fontName, &style, &isFixedWidth) ) { | 151 &familyName, &style, &isFixedWidt h)) { |
143 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, fileNam e.c_str())); | 152 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathNam e.c_str())); |
144 continue; | 153 continue; |
145 } | 154 } |
146 | 155 |
156 const SkLanguage& lang = fontFile.fPaintOptions.getLanguage(); | |
157 SkPaintOptionsAndroid::FontVariant variant = fontFile.fPaintOptions. getFontVariant(); | |
158 | |
159 // The first specified family name overrides the family name found i n the font. | |
160 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return | |
161 // all of the specified family names in addition to the names found in the font. | |
162 if (cannonicalFamilyName != NULL) { | |
163 familyName = *cannonicalFamilyName; | |
164 } | |
165 | |
147 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, | 166 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, |
148 (pathName, ttcIndex, | 167 (pathName, ttcIndex, |
149 style, isFixedWidth, fontName) )); | 168 style, isFixedWidth, familyNam e, |
169 lang, variant))); | |
150 } | 170 } |
151 } | 171 } |
152 | 172 |
153 virtual int count() SK_OVERRIDE { | 173 virtual int count() SK_OVERRIDE { |
154 return fStyles.count(); | 174 return fStyles.count(); |
155 } | 175 } |
156 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE { | 176 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE { |
157 if (index < 0 || fStyles.count() <= index) { | 177 if (index < 0 || fStyles.count() <= index) { |
158 return; | 178 return; |
159 } | 179 } |
160 if (style) { | 180 if (style) { |
161 *style = this->style(index); | 181 *style = this->style(index); |
162 } | 182 } |
163 if (name) { | 183 if (name) { |
164 name->reset(); | 184 name->reset(); |
165 } | 185 } |
166 } | 186 } |
167 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { | 187 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE { |
168 if (index < 0 || fStyles.count() <= index) { | 188 if (index < 0 || fStyles.count() <= index) { |
169 return NULL; | 189 return NULL; |
170 } | 190 } |
171 return SkRef(fStyles[index].get()); | 191 return SkRef(fStyles[index].get()); |
172 } | 192 } |
173 | 193 |
174 /** Find the typeface in this style set that most closely matches the given pattern. | 194 /** Find the typeface in this style set that most closely matches the given pattern. |
175 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); | 195 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); |
176 * this simpler version using match_score() passes all our tests. | 196 * this simpler version using match_score() passes all our tests. |
177 */ | 197 */ |
178 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { | 198 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_ OVERRIDE { |
179 if (0 == fStyles.count()) { | 199 if (0 == fStyles.count()) { |
180 return NULL; | 200 return NULL; |
181 } | 201 } |
182 SkTypeface* closest = fStyles[0]; | 202 SkTypeface_AndroidSystem* closest = fStyles[0]; |
183 int minScore = std::numeric_limits<int>::max(); | 203 int minScore = std::numeric_limits<int>::max(); |
184 for (int i = 0; i < fStyles.count(); ++i) { | 204 for (int i = 0; i < fStyles.count(); ++i) { |
185 SkFontStyle style = this->style(i); | 205 SkFontStyle style = this->style(i); |
186 int score = match_score(pattern, style); | 206 int score = match_score(pattern, style); |
187 if (score < minScore) { | 207 if (score < minScore) { |
188 closest = fStyles[i]; | 208 closest = fStyles[i]; |
189 minScore = score; | 209 minScore = score; |
190 } | 210 } |
191 } | 211 } |
192 return SkRef(closest); | 212 return SkRef(closest); |
(...skipping 13 matching lines...) Expand all Loading... | |
206 return SkFontStyle::kUpright_Slant; | 226 return SkFontStyle::kUpright_Slant; |
207 } | 227 } |
208 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) { | 228 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) { |
209 int score = 0; | 229 int score = 0; |
210 score += abs((pattern.width() - candidate.width()) * 100); | 230 score += abs((pattern.width() - candidate.width()) * 100); |
211 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000); | 231 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000); |
212 score += abs(pattern.weight() - candidate.weight()); | 232 score += abs(pattern.weight() - candidate.weight()); |
213 return score; | 233 return score; |
214 } | 234 } |
215 | 235 |
216 SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles; | 236 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles; |
217 | 237 |
218 friend struct NameToFamily; | 238 friend struct NameToFamily; |
219 friend class SkFontMgr_Android; | 239 friend class SkFontMgr_Android; |
220 | 240 |
221 typedef SkFontStyleSet INHERITED; | 241 typedef SkFontStyleSet INHERITED; |
222 }; | 242 }; |
223 | 243 |
224 /** On Android a single family can have many names, but our API assumes unique n ames. | 244 /** On Android a single family can have many names, but our API assumes unique n ames. |
225 * Map names to the back end so that all names for a given family refer to the same | 245 * Map names to the back end so that all names for a given family refer to the same |
226 * (non-replicated) set of typefaces. | 246 * (non-replicated) set of typefaces. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { | 286 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { |
267 if (!familyName) { | 287 if (!familyName) { |
268 return NULL; | 288 return NULL; |
269 } | 289 } |
270 SkAutoAsciiToLC tolc(familyName); | 290 SkAutoAsciiToLC tolc(familyName); |
271 for (int i = 0; i < fNameToFamilyMap.count(); ++i) { | 291 for (int i = 0; i < fNameToFamilyMap.count(); ++i) { |
272 if (fNameToFamilyMap[i].name.equals(tolc.lc())) { | 292 if (fNameToFamilyMap[i].name.equals(tolc.lc())) { |
273 return SkRef(fNameToFamilyMap[i].styleSet); | 293 return SkRef(fNameToFamilyMap[i].styleSet); |
274 } | 294 } |
275 } | 295 } |
296 // TODO: eventually we should not need to name fallback families. | |
297 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) { | |
298 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) { | |
299 return SkRef(fFallbackNameToFamilyMap[i].styleSet); | |
300 } | |
301 } | |
276 return NULL; | 302 return NULL; |
277 } | 303 } |
278 | 304 |
279 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | 305 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], |
280 const SkFontStyle& style) const SK_OV ERRIDE { | 306 const SkFontStyle& style) const SK_OV ERRIDE { |
281 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); | 307 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); |
282 return sset->matchStyle(style); | 308 return sset->matchStyle(style); |
283 } | 309 } |
284 | 310 |
285 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, | 311 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, |
286 const SkFontStyle& style) const SK_OVER RIDE { | 312 const SkFontStyle& style) const SK_OVER RIDE { |
287 for (int i = 0; i < fFontStyleSets.count(); ++i) { | 313 for (int i = 0; i < fFontStyleSets.count(); ++i) { |
288 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) { | 314 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) { |
289 if (fFontStyleSets[i]->fStyles[j] == typeface) { | 315 if (fFontStyleSets[i]->fStyles[j] == typeface) { |
290 return fFontStyleSets[i]->matchStyle(style); | 316 return fFontStyleSets[i]->matchStyle(style); |
291 } | 317 } |
292 } | 318 } |
293 } | 319 } |
294 return NULL; | 320 return NULL; |
295 } | 321 } |
296 | 322 |
323 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], | |
324 const SkFontStyle& style, | |
325 const char bpc47[], | |
326 uint32_t character) const SK _OVERRIDE | |
327 { | |
328 // If the familyName maps to a family, then match the style and get the variant. | |
329 // Otherwise "elegant" unless the family name ends in "compact". | |
330 bool isCompact = false; | |
331 if (familyName) { | |
332 size_t familyNameLen = strlen(familyName); | |
333 static const char compactLiteral[] = "compact"; | |
334 static const size_t compactLiteralLen = SK_ARRAY_COUNT(compactLitera l); | |
335 if (compactLiteralLen <= familyNameLen) { | |
djsollen
2014/08/01 20:24:04
should this be < or would a font with the name "co
bungeman-skia
2014/08/04 19:24:20
So, when I wrote this I was under the impression f
| |
336 const char* familyNameEnd = familyName + familyNameLen - compact LiteralLen; | |
337 isCompact = SkToBool(strcmp(familyNameEnd, compactLiteral)); | |
338 } | |
339 } | |
340 | |
341 uint32_t ignoredVariantMask = SkPaintOptionsAndroid::kCompact_Variant; | |
342 if (isCompact) { | |
343 ignoredVariantMask = ~SkPaintOptionsAndroid::kCompact_Variant; | |
344 } | |
345 | |
346 for (int i = 0; i < 2; ++i, ignoredVariantMask = ~ignoredVariantMask) { | |
djsollen
2014/08/01 20:24:04
document that the second time through the loop loo
bungeman-skia
2014/08/04 19:24:20
Changed the logic to make this more obvious and ad
| |
347 SkLanguage lang(bpc47); | |
348 do { | |
349 const SkString& langTag = lang.getTag(); | |
350 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) { | |
351 SkFontStyleSet_Android* family = fFallbackNameToFamilyMap[i] .styleSet; | |
352 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchSty le(style)); | |
353 | |
354 if (!langTag.isEmpty() && langTag != face->fLang.getTag()) { | |
355 continue; | |
356 } | |
357 | |
358 if (SkToBool(face->fVariant & ignoredVariantMask)) { | |
359 continue; | |
360 } | |
361 | |
362 SkPaint paint; | |
363 paint.setTypeface(face); | |
364 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
365 | |
366 uint16_t glyphID; | |
367 paint.textToGlyphs(&character, sizeof(character), &glyphID); | |
368 if (glyphID != 0) { | |
369 return face.detach(); | |
370 } | |
371 } | |
372 } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true) ); | |
djsollen
2014/08/01 20:24:04
At first glance it is not clear that the last run
bungeman-skia
2014/08/04 19:24:20
Documented.
| |
373 } | |
374 return NULL; | |
375 } | |
376 | |
297 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE { | 377 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE { |
298 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); | 378 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); |
299 return this->createFromStream(stream, ttcIndex); | 379 return this->createFromStream(stream, ttcIndex); |
300 } | 380 } |
301 | 381 |
302 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { | 382 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { |
303 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 383 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
304 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; | 384 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; |
305 } | 385 } |
306 | 386 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 } | 420 } |
341 | 421 |
342 | 422 |
343 private: | 423 private: |
344 | 424 |
345 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets; | 425 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets; |
346 SkFontStyleSet* fDefaultFamily; | 426 SkFontStyleSet* fDefaultFamily; |
347 SkTypeface* fDefaultTypeface; | 427 SkTypeface* fDefaultTypeface; |
348 | 428 |
349 SkTDArray<NameToFamily> fNameToFamilyMap; | 429 SkTDArray<NameToFamily> fNameToFamilyMap; |
430 SkTDArray<NameToFamily> fFallbackNameToFamilyMap; | |
350 | 431 |
351 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { | 432 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { |
352 for (int i = 0; i < families.count(); i++) { | 433 for (int i = 0; i < families.count(); i++) { |
353 fFontStyleSets.push_back().reset( | 434 FontFamily& family = *families[i]; |
354 SkNEW_ARGS(SkFontStyleSet_Android, (families[i]))); | 435 |
355 for (int j = 0; j < families[i]->fNames.count(); j++) { | 436 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap; |
356 NameToFamily* nextEntry = fNameToFamilyMap.append(); | 437 if (family.fIsFallbackFont) { |
357 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->f Names[j])); | 438 nameToFamily = &fFallbackNameToFamilyMap; |
358 nextEntry->styleSet = fFontStyleSets.back().get(); | 439 |
440 if (0 == family.fNames.count()) { | |
441 SkString& fallbackName = family.fNames.push_back(); | |
442 fallbackName.printf("%.2x##fallback", i); | |
443 } | |
444 } | |
445 | |
446 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family)); | |
447 if (0 == newSet->count()) { | |
448 SkDELETE(newSet); | |
449 continue; | |
450 } | |
451 fFontStyleSets.push_back().reset(newSet); | |
452 | |
453 for (int j = 0; j < family.fNames.count(); j++) { | |
454 NameToFamily* nextEntry = nameToFamily->append(); | |
455 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[ j])); | |
456 nextEntry->styleSet = newSet; | |
359 } | 457 } |
360 } | 458 } |
361 } | 459 } |
362 | 460 |
363 void findDefaultFont() { | 461 void findDefaultFont() { |
364 SkASSERT(!fFontStyleSets.empty()); | 462 SkASSERT(!fFontStyleSets.empty()); |
365 | 463 |
366 static const char* gDefaultNames[] = { "sans-serif" }; | 464 static const char* gDefaultNames[] = { "sans-serif" }; |
367 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { | 465 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { |
368 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); | 466 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); |
(...skipping 17 matching lines...) Expand all Loading... | |
386 } | 484 } |
387 | 485 |
388 typedef SkFontMgr INHERITED; | 486 typedef SkFontMgr INHERITED; |
389 }; | 487 }; |
390 | 488 |
391 /////////////////////////////////////////////////////////////////////////////// | 489 /////////////////////////////////////////////////////////////////////////////// |
392 | 490 |
393 SkFontMgr* SkFontMgr::Factory() { | 491 SkFontMgr* SkFontMgr::Factory() { |
394 return SkNEW(SkFontMgr_Android); | 492 return SkNEW(SkFontMgr_Android); |
395 } | 493 } |
OLD | NEW |