OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2013 The Android Open Source Project | 3 * Copyright 2013 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkFontConfigInterface.h" | 9 #include "SkFontConfigInterface.h" |
10 #include "SkTypeface_android.h" | 10 #include "SkTypeface_android.h" |
11 | 11 |
12 #include "SkFontConfigParser_android.h" | 12 #include "SkFontConfigParser_android.h" |
13 #include "SkFontConfigTypeface.h" | 13 #include "SkFontConfigTypeface.h" |
14 #include "SkFontMgr.h" | 14 #include "SkFontMgr.h" |
15 #include "SkGlyphCache.h" | 15 #include "SkGlyphCache.h" |
16 #include "SkPaint.h" | 16 #include "SkPaint.h" |
17 #include "SkPaintOptionsAndroid.h" | |
18 #include "SkString.h" | 17 #include "SkString.h" |
19 #include "SkStream.h" | 18 #include "SkStream.h" |
20 #include "SkThread.h" | 19 #include "SkThread.h" |
21 #include "SkTypefaceCache.h" | 20 #include "SkTypefaceCache.h" |
22 #include "SkTArray.h" | 21 #include "SkTArray.h" |
23 #include "SkTDict.h" | 22 #include "SkTDict.h" |
24 #include "SkTSearch.h" | 23 #include "SkTSearch.h" |
25 | 24 |
26 #include <stdio.h> | 25 #include <stdio.h> |
27 #include <string.h> | 26 #include <string.h> |
(...skipping 10 matching lines...) Expand all Loading... |
38 | 37 |
39 /////////////////////////////////////////////////////////////////////////////// | 38 /////////////////////////////////////////////////////////////////////////////// |
40 | 39 |
41 // For test only. | 40 // For test only. |
42 static const char* gTestMainConfigFile = NULL; | 41 static const char* gTestMainConfigFile = NULL; |
43 static const char* gTestFallbackConfigFile = NULL; | 42 static const char* gTestFallbackConfigFile = NULL; |
44 static const char* gTestFontFilePrefix = NULL; | 43 static const char* gTestFontFilePrefix = NULL; |
45 | 44 |
46 /////////////////////////////////////////////////////////////////////////////// | 45 /////////////////////////////////////////////////////////////////////////////// |
47 | 46 |
| 47 typedef int32_t FontRecID; |
| 48 #define INVALID_FONT_REC_ID -1 |
| 49 |
| 50 typedef int32_t FamilyRecID; |
| 51 #define INVALID_FAMILY_REC_ID -1 |
| 52 |
48 // used to record our notion of the pre-existing fonts | 53 // used to record our notion of the pre-existing fonts |
49 struct FontRec { | 54 struct FontRec { |
50 SkRefPtr<SkTypeface> fTypeface; | 55 SkRefPtr<SkTypeface> fTypeface; |
51 SkString fFileName; | 56 SkString fFileName; |
52 SkTypeface::Style fStyle; | 57 SkTypeface::Style fStyle; |
53 SkPaintOptionsAndroid fPaintOptions; | 58 SkPaintOptionsAndroid fPaintOptions; |
54 bool fIsFallbackFont; | 59 bool fIsFallbackFont; |
55 bool fIsValid; | 60 bool fIsValid; |
| 61 FamilyRecID fFamilyRecID; |
56 }; | 62 }; |
57 | 63 |
58 typedef int32_t FontRecID; | |
59 #define INVALID_FONT_REC_ID -1 | |
60 | |
61 struct FamilyRec { | 64 struct FamilyRec { |
62 FamilyRec() { | 65 FamilyRec() { |
63 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID)); | 66 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID)); |
64 } | 67 } |
65 | 68 |
66 static const int FONT_STYLE_COUNT = 4; | 69 static const int FONT_STYLE_COUNT = 4; |
67 FontRecID fFontRecID[FONT_STYLE_COUNT]; | 70 FontRecID fFontRecID[FONT_STYLE_COUNT]; |
68 }; | 71 }; |
69 | 72 |
70 typedef int32_t FamilyRecID; | |
71 #define INVALID_FAMILY_REC_ID -1 | |
72 | 73 |
73 typedef SkTDArray<FontRecID> FallbackFontList; | 74 typedef SkTDArray<FontRecID> FallbackFontList; |
74 | 75 |
75 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface { | 76 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface { |
76 public: | 77 public: |
77 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies); | 78 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies); |
78 virtual ~SkFontConfigInterfaceAndroid(); | 79 virtual ~SkFontConfigInterfaceAndroid(); |
79 | 80 |
80 virtual bool matchFamilyName(const char familyName[], | 81 virtual bool matchFamilyName(const char familyName[], |
81 SkTypeface::Style requested, | 82 SkTypeface::Style requested, |
(...skipping 16 matching lines...) Expand all Loading... |
98 /** | 99 /** |
99 * | 100 * |
100 */ | 101 */ |
101 SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style, | 102 SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style, |
102 SkPaintOptionsAndroid::FontVariant fontVarian
t); | 103 SkPaintOptionsAndroid::FontVariant fontVarian
t); |
103 SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, | 104 SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, |
104 const SkPaintOptionsAndroid& options); | 105 const SkPaintOptionsAndroid& options); |
105 | 106 |
106 private: | 107 private: |
107 void addFallbackFont(FontRecID fontRecID); | 108 void addFallbackFont(FontRecID fontRecID); |
108 FallbackFontList* findFallbackFontList(const SkLanguage& lang); | 109 SkTypeface* getTypefaceForFontRec(FontRecID fontRecID); |
| 110 FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOrigin
al = true); |
109 | 111 |
110 SkTArray<FontRec> fFonts; | 112 SkTArray<FontRec> fFonts; |
111 SkTArray<FamilyRec> fFontFamilies; | 113 SkTArray<FamilyRec> fFontFamilies; |
112 SkTDict<FamilyRecID> fFamilyNameDict; | 114 SkTDict<FamilyRecID> fFamilyNameDict; |
113 FamilyRecID fDefaultFamilyRecID; | 115 FamilyRecID fDefaultFamilyRecID; |
114 | 116 |
115 // (SkLanguage)<->(fallback chain index) translation | 117 // (SkLanguage)<->(fallback chain index) translation |
116 SkTDict<FallbackFontList*> fFallbackFontDict; | 118 SkTDict<FallbackFontList*> fFallbackFontDict; |
| 119 SkTDict<FallbackFontList*> fFallbackFontAliasDict; |
117 FallbackFontList fDefaultFallbackList; | 120 FallbackFontList fDefaultFallbackList; |
118 }; | 121 }; |
119 | 122 |
120 /////////////////////////////////////////////////////////////////////////////// | 123 /////////////////////////////////////////////////////////////////////////////// |
121 | 124 |
122 static SkFontConfigInterfaceAndroid* getSingletonInterface() { | 125 static SkFontConfigInterfaceAndroid* getSingletonInterface() { |
123 SK_DECLARE_STATIC_MUTEX(gMutex); | 126 SK_DECLARE_STATIC_MUTEX(gMutex); |
124 static SkFontConfigInterfaceAndroid* gFontConfigInterface; | 127 static SkFontConfigInterfaceAndroid* gFontConfigInterface; |
125 | 128 |
126 SkAutoMutexAcquire ac(gMutex); | 129 SkAutoMutexAcquire ac(gMutex); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 bool find_name_and_attributes(SkStream* stream, SkString* name, | 185 bool find_name_and_attributes(SkStream* stream, SkString* name, |
183 SkTypeface::Style* style, bool* isFixedWidth); | 186 SkTypeface::Style* style, bool* isFixedWidth); |
184 | 187 |
185 /////////////////////////////////////////////////////////////////////////////// | 188 /////////////////////////////////////////////////////////////////////////////// |
186 | 189 |
187 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
>& fontFamilies) : | 190 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
>& fontFamilies) : |
188 fFonts(fontFamilies.count()), | 191 fFonts(fontFamilies.count()), |
189 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT), | 192 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT), |
190 fFamilyNameDict(1024), | 193 fFamilyNameDict(1024), |
191 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID), | 194 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID), |
192 fFallbackFontDict(128) { | 195 fFallbackFontDict(128), |
| 196 fFallbackFontAliasDict(128) { |
193 | 197 |
194 for (int i = 0; i < fontFamilies.count(); ++i) { | 198 for (int i = 0; i < fontFamilies.count(); ++i) { |
195 FontFamily* family = fontFamilies[i]; | 199 FontFamily* family = fontFamilies[i]; |
196 | 200 |
197 // defer initializing the familyRec until we can be sure that at least | 201 // defer initializing the familyRec until we can be sure that at least |
198 // one of it's children contains a valid font file | 202 // one of it's children contains a valid font file |
199 FamilyRec* familyRec = NULL; | 203 FamilyRec* familyRec = NULL; |
200 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; | 204 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; |
201 | 205 |
202 for (int j = 0; j < family->fFontFiles.count(); ++j) { | 206 for (int j = 0; j < family->fFontFiles.count(); ++j) { |
203 SkString filename; | 207 SkString filename; |
204 get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName); | 208 get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName); |
205 | 209 |
206 if (has_font(fFonts, filename)) { | 210 if (has_font(fFonts, filename)) { |
207 SkDebugf("---- system font and fallback font files specify a dup
licate " | 211 SkDebugf("---- system font and fallback font files specify a dup
licate " |
208 "font %s, skipping the second occurrence", filename.c_st
r()); | 212 "font %s, skipping the second occurrence", filename.c_st
r()); |
209 continue; | 213 continue; |
210 } | 214 } |
211 | 215 |
212 FontRec& fontRec = fFonts.push_back(); | 216 FontRec& fontRec = fFonts.push_back(); |
213 fontRec.fFileName = filename; | 217 fontRec.fFileName = filename; |
214 fontRec.fStyle = SkTypeface::kNormal; | 218 fontRec.fStyle = SkTypeface::kNormal; |
215 fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions; | 219 fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions; |
216 fontRec.fIsFallbackFont = family->fIsFallbackFont; | 220 fontRec.fIsFallbackFont = family->fIsFallbackFont; |
217 fontRec.fIsValid = false; | 221 fontRec.fIsValid = false; |
| 222 fontRec.fFamilyRecID = familyRecID; |
218 | 223 |
219 const FontRecID fontRecID = fFonts.count() - 1; | 224 const FontRecID fontRecID = fFonts.count() - 1; |
220 | 225 |
221 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()
)); | 226 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()
)); |
222 if (stream.get() != NULL) { | 227 if (stream.get() != NULL) { |
223 bool isFixedWidth; | 228 bool isFixedWidth; |
224 SkString name; | 229 SkString name; |
225 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name, | 230 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name, |
226 &fontRec.fStyle, &is
FixedWidth); | 231 &fontRec.fStyle, &is
FixedWidth); |
227 } else { | 232 } else { |
228 if (!fontRec.fIsFallbackFont) { | 233 if (!fontRec.fIsFallbackFont) { |
229 SkDebugf("---- failed to open <%s> as a font\n", filename.c_
str()); | 234 SkDebugf("---- failed to open <%s> as a font\n", filename.c_
str()); |
230 } | 235 } |
231 } | 236 } |
232 | 237 |
233 if (fontRec.fIsValid) { | 238 if (fontRec.fIsValid) { |
234 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s", | 239 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s", |
235 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen
ame.c_str())); | 240 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen
ame.c_str())); |
236 } else { | 241 } else { |
237 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVAL
ID)", | 242 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVAL
ID)", |
238 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen
ame.c_str())); | 243 i, fFonts.count() - 1, fontRec.fIsFallbackFont, filen
ame.c_str())); |
239 continue; | 244 continue; |
240 } | 245 } |
241 | 246 |
242 // create a familyRec now that we know that at least one font in | 247 // create a familyRec now that we know that at least one font in |
243 // the family is valid | 248 // the family is valid |
244 if (familyRec == NULL) { | 249 if (familyRec == NULL) { |
245 familyRec = &fFontFamilies.push_back(); | 250 familyRec = &fFontFamilies.push_back(); |
246 familyRecID = fFontFamilies.count() - 1; | 251 familyRecID = fFontFamilies.count() - 1; |
| 252 fontRec.fFamilyRecID = familyRecID; |
247 } | 253 } |
248 | 254 |
249 // add this font to the current familyRec | 255 // add this font to the current familyRec |
250 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) { | 256 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) { |
251 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)
", | 257 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)
", |
252 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle
], | 258 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle
], |
253 fontRecID)); | 259 fontRecID)); |
254 } | 260 } |
255 familyRec->fFontRecID[fontRec.fStyle] = fontRecID; | 261 familyRec->fFontRecID[fontRec.fStyle] = fontRecID; |
256 | 262 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), | 453 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), |
448 sizes.begin(), names.count()); | 454 sizes.begin(), names.count()); |
449 } | 455 } |
450 | 456 |
451 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[], | 457 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[], |
452 SkString* outFamilyName, | 458 SkString* outFamilyName, |
453 SkTArray<FontIdentity>*) { | 459 SkTArray<FontIdentity>*) { |
454 return false; | 460 return false; |
455 } | 461 } |
456 | 462 |
457 static SkTypeface* get_typeface_for_rec(FontRec& fontRec) { | 463 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) { |
| 464 const FontRecID* fontRecID = (const FontRecID*)ctx; |
| 465 FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID; |
| 466 return currFontRecID == *fontRecID; |
| 467 } |
| 468 |
| 469 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRe
cID) { |
| 470 FontRec& fontRec = fFonts[fontRecID]; |
458 SkTypeface* face = fontRec.fTypeface.get(); | 471 SkTypeface* face = fontRec.fTypeface.get(); |
459 if (!face) { | 472 if (!face) { |
460 // TODO look for it in the typeface cache | 473 // look for it in the typeface cache |
| 474 face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID); |
461 | 475 |
462 // if it is not in the cache then create it | 476 // if it is not in the cache then create it |
463 face = SkTypeface::CreateFromFile(fontRec.fFileName.c_str()); | 477 if (!face) { |
| 478 const char* familyName = NULL; |
| 479 SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &family
Name)); |
| 480 SkASSERT(familyName); |
| 481 face = SkTypeface::CreateFromName(familyName, fontRec.fStyle); |
| 482 } |
464 | 483 |
465 // store the result for subsequent lookups | 484 // store the result for subsequent lookups |
466 fontRec.fTypeface = face; | 485 fontRec.fTypeface = face; |
467 } | 486 } |
468 SkASSERT(face); | 487 SkASSERT(face); |
469 return face; | 488 return face; |
470 } | 489 } |
471 | 490 |
472 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, S
kString* name) { | 491 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, S
kString* name) { |
473 for (int i = 0; i < fDefaultFallbackList.count(); i++) { | 492 for (int i = 0; i < fDefaultFallbackList.count(); i++) { |
474 FontRecID fontRecID = fDefaultFallbackList[i]; | 493 FontRecID fontRecID = fDefaultFallbackList[i]; |
475 SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]); | 494 SkTypeface* face = this->getTypefaceForFontRec(fontRecID); |
476 | 495 |
477 SkPaint paint; | 496 SkPaint paint; |
478 paint.setTypeface(face); | 497 paint.setTypeface(face); |
479 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); | 498 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); |
480 | 499 |
481 uint16_t glyphID; | 500 uint16_t glyphID; |
482 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); | 501 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); |
483 if (glyphID != 0) { | 502 if (glyphID != 0) { |
484 name->set(fFonts[fontRecID].fFileName); | 503 name->set(fFonts[fontRecID].fFileName); |
485 return true; | 504 return true; |
486 } | 505 } |
487 } | 506 } |
488 return false; | 507 return false; |
489 } | 508 } |
490 | 509 |
491 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni, | 510 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni, |
492 SkTypeface::Style s
tyle, | 511 SkTypeface::Style s
tyle, |
493 SkPaintOptionsAndro
id::FontVariant fontVariant) { | 512 SkPaintOptionsAndro
id::FontVariant fontVariant) { |
494 FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], st
yle); | 513 FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], st
yle); |
495 SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]); | 514 SkTypeface* face = this->getTypefaceForFontRec(fontRecID); |
496 | 515 |
497 SkPaintOptionsAndroid paintOptions; | 516 SkPaintOptionsAndroid paintOptions; |
498 paintOptions.setFontVariant(fontVariant); | 517 paintOptions.setFontVariant(fontVariant); |
499 paintOptions.setUseFontFallbacks(true); | 518 paintOptions.setUseFontFallbacks(true); |
500 | 519 |
501 SkPaint paint; | 520 SkPaint paint; |
502 paint.setTypeface(face); | 521 paint.setTypeface(face); |
503 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); | 522 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); |
504 paint.setPaintOptionsAndroid(paintOptions); | 523 paint.setPaintOptionsAndroid(paintOptions); |
505 | 524 |
506 SkAutoGlyphCache autoCache(paint, NULL, NULL); | 525 SkAutoGlyphCache autoCache(paint, NULL, NULL); |
507 SkGlyphCache* cache = autoCache.getCache(); | 526 SkGlyphCache* cache = autoCache.getCache(); |
508 | 527 |
509 SkScalerContext* ctx = cache->getScalerContext(); | 528 SkScalerContext* ctx = cache->getScalerContext(); |
510 if (ctx) { | 529 if (ctx) { |
511 SkFontID fontID = ctx->findTypefaceIdForChar(uni); | 530 SkFontID fontID = ctx->findTypefaceIdForChar(uni); |
512 return SkTypefaceCache::FindByID(fontID); | 531 return SkTypefaceCache::FindByID(fontID); |
513 } | 532 } |
514 return NULL; | 533 return NULL; |
515 } | 534 } |
516 | 535 |
517 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLan
guage& lang) { | 536 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLan
guage& lang, |
| 537 bool isOrig
inal) { |
518 const SkString& langTag = lang.getTag(); | 538 const SkString& langTag = lang.getTag(); |
519 if (langTag.isEmpty()) { | 539 if (langTag.isEmpty()) { |
520 return &fDefaultFallbackList; | 540 return &fDefaultFallbackList; |
521 } | 541 } |
522 | 542 |
523 FallbackFontList* fallbackFontList; | 543 FallbackFontList* fallbackFontList; |
524 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontLis
t)) { | 544 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontLis
t) || |
| 545 fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFo
ntList)) { |
525 return fallbackFontList; | 546 return fallbackFontList; |
526 } | 547 } |
527 | 548 |
528 // attempt a recursive fuzzy match | 549 // attempt a recursive fuzzy match |
529 // TODO we could cache the intermediate parent so that we don't have to do | |
530 // the recursion again. | |
531 SkLanguage parent = lang.getParent(); | 550 SkLanguage parent = lang.getParent(); |
532 return findFallbackFontList(parent); | 551 fallbackFontList = findFallbackFontList(parent, false); |
| 552 |
| 553 // cache the original lang so we don't have to do the recursion again. |
| 554 if (isOriginal) { |
| 555 DEBUG_FONT(("---- Created fallback list alias for \"%s\"", langTag.c_st
r())); |
| 556 fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList); |
| 557 } |
| 558 return fallbackFontList; |
533 } | 559 } |
534 | 560 |
535 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
D, | 561 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
D, |
536 SkFontID origFontI
D, | 562 SkFontID origFontI
D, |
537 const SkPaintOptio
nsAndroid& opts) { | 563 const SkPaintOptio
nsAndroid& opts) { |
538 // Skia does not support font fallback by default. This enables clients such | 564 // Skia does not support font fallback by default. This enables clients such |
539 // as WebKit to customize their font selection. In any case, clients can use | 565 // as WebKit to customize their font selection. In any case, clients can use |
540 // GetFallbackFamilyNameForChar() to get the fallback font for individual | 566 // GetFallbackFamilyNameForChar() to get the fallback font for individual |
541 // characters. | 567 // characters. |
542 if (!opts.isUsingFontFallbacks()) { | 568 if (!opts.isUsingFontFallbacks()) { |
543 return NULL; | 569 return NULL; |
544 } | 570 } |
545 | 571 |
546 const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID); | 572 const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID); |
| 573 SkASSERT(currTypeface != 0); |
547 | 574 |
548 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguag
e()); | 575 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguag
e()); |
549 SkASSERT(currentFallbackList); | 576 SkASSERT(currentFallbackList); |
550 | 577 |
551 SkASSERT(currTypeface != 0); | |
552 | |
553 // we must convert currTypeface into a FontRecID | 578 // we must convert currTypeface into a FontRecID |
554 FontRecID currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity()
.fID; | 579 FontRecID currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity()
.fID; |
| 580 SkASSERT(INVALID_FONT_REC_ID != currFontRecID); |
555 | 581 |
556 // TODO lookup the index next font in the chain | 582 // TODO lookup the index next font in the chain |
557 int currFallbackFontIndex = currentFallbackList->find(currFontRecID); | 583 int currFallbackFontIndex = currentFallbackList->find(currFontRecID); |
558 int nextFallbackFontIndex = currFallbackFontIndex + 1; | 584 int nextFallbackFontIndex = currFallbackFontIndex + 1; |
559 SkASSERT(-1 == nextFallbackFontIndex); | |
560 | 585 |
561 if(nextFallbackFontIndex >= currentFallbackList->count() && -1 == currFallba
ckFontIndex) { | 586 if(nextFallbackFontIndex >= currentFallbackList->count()) { |
562 return NULL; | 587 return NULL; |
563 } | 588 } |
564 | 589 |
565 // If a rec object is set to prefer "kDefault_Variant" it means they have no
preference | 590 // If a rec object is set to prefer "kDefault_Variant" it means they have no
preference |
566 // In this case, we set the value to "kCompact_Variant" | 591 // In this case, we set the value to "kCompact_Variant" |
567 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant(); | 592 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant(); |
568 if (variant == SkPaintOptionsAndroid::kDefault_Variant) { | 593 if (variant == SkPaintOptionsAndroid::kDefault_Variant) { |
569 variant = SkPaintOptionsAndroid::kCompact_Variant; | 594 variant = SkPaintOptionsAndroid::kCompact_Variant; |
570 } | 595 } |
571 | 596 |
572 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant
; | 597 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant
; |
573 | 598 |
574 SkTypeface* nextLogicalTypeface = 0; | 599 SkTypeface* nextLogicalTypeface = 0; |
575 while (nextFallbackFontIndex < currentFallbackList->count()) { | 600 while (nextFallbackFontIndex < currentFallbackList->count()) { |
576 FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex); | 601 FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex); |
577 if (fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants)
{ | 602 if ((fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants
) != 0) { |
578 nextLogicalTypeface = get_typeface_for_rec(fFonts[fontRecID]); | 603 nextLogicalTypeface = this->getTypefaceForFontRec(fontRecID); |
579 break; | 604 break; |
580 } | 605 } |
581 nextFallbackFontIndex++; | 606 nextFallbackFontIndex++; |
582 } | 607 } |
583 | 608 |
584 DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%
d, " | 609 DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%
d, " |
585 "lang=%s, variant=%d, nextFallbackIndex=%d => nextLogicalTypefac
e=%d", | 610 "lang=%s, variant=%d, nextFallbackIndex[%d,%d] => nextLogicalTyp
eface=%d", |
586 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag
().c_str(), | 611 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag
().c_str(), |
587 variant, nextFallbackFontIndex, | 612 variant, nextFallbackFontIndex, currentFallbackList->getAt(nextF
allbackFontIndex), |
588 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0)); | 613 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0)); |
589 return SkSafeRef(nextLogicalTypeface); | 614 return SkSafeRef(nextLogicalTypeface); |
590 } | 615 } |
591 | 616 |
592 /////////////////////////////////////////////////////////////////////////////// | 617 /////////////////////////////////////////////////////////////////////////////// |
593 | 618 |
594 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { | 619 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { |
595 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); | 620 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); |
596 return fontConfig->getFallbackFamilyNameForChar(uni, name); | 621 return fontConfig->getFallbackFamilyNameForChar(uni, name); |
597 } | 622 } |
(...skipping 12 matching lines...) Expand all Loading... |
610 | 635 |
611 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontI
D, | 636 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontI
D, |
612 const SkPaintOptionsAndroid& options) { | 637 const SkPaintOptionsAndroid& options) { |
613 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); | 638 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); |
614 return fontConfig->nextLogicalTypeface(currFontID, origFontID, options); | 639 return fontConfig->nextLogicalTypeface(currFontID, origFontID, options); |
615 | 640 |
616 } | 641 } |
617 | 642 |
618 /////////////////////////////////////////////////////////////////////////////// | 643 /////////////////////////////////////////////////////////////////////////////// |
619 | 644 |
| 645 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
| 646 |
| 647 struct HB_UnicodeMapping { |
| 648 // TODO: when the WebView no longer needs harfbuzz_old, remove |
| 649 HB_Script script_old; |
| 650 hb_script_t script; |
| 651 const SkUnichar unicode; |
| 652 }; |
| 653 |
| 654 /* |
| 655 * The following scripts are not complex fonts and we do not expect them to be p
arsed by this table |
| 656 * HB_SCRIPT_COMMON, |
| 657 * HB_SCRIPT_GREEK, |
| 658 * HB_SCRIPT_CYRILLIC, |
| 659 * HB_SCRIPT_HANGUL |
| 660 * HB_SCRIPT_INHERITED |
| 661 */ |
| 662 |
| 663 /* Harfbuzz (old) is missing a number of scripts in its table. For these, |
| 664 * we include a value which can never happen. We won't get complex script |
| 665 * shaping in these cases, but the library wouldn't know how to shape |
| 666 * them anyway. */ |
| 667 #define HB_Script_Unknown HB_ScriptCount |
| 668 |
| 669 static HB_UnicodeMapping HB_UnicodeMappingArray[] = { |
| 670 {HB_Script_Armenian, HB_SCRIPT_ARMENIAN, 0x0531}, |
| 671 {HB_Script_Hebrew, HB_SCRIPT_HEBREW, 0x0591}, |
| 672 {HB_Script_Arabic, HB_SCRIPT_ARABIC, 0x0600}, |
| 673 {HB_Script_Syriac, HB_SCRIPT_SYRIAC, 0x0710}, |
| 674 {HB_Script_Thaana, HB_SCRIPT_THAANA, 0x0780}, |
| 675 {HB_Script_Nko, HB_SCRIPT_NKO, 0x07C0}, |
| 676 {HB_Script_Devanagari, HB_SCRIPT_DEVANAGARI, 0x0901}, |
| 677 {HB_Script_Bengali, HB_SCRIPT_BENGALI, 0x0981}, |
| 678 {HB_Script_Gurmukhi, HB_SCRIPT_GURMUKHI, 0x0A10}, |
| 679 {HB_Script_Gujarati, HB_SCRIPT_GUJARATI, 0x0A90}, |
| 680 {HB_Script_Oriya, HB_SCRIPT_ORIYA, 0x0B10}, |
| 681 {HB_Script_Tamil, HB_SCRIPT_TAMIL, 0x0B82}, |
| 682 {HB_Script_Telugu, HB_SCRIPT_TELUGU, 0x0C10}, |
| 683 {HB_Script_Kannada, HB_SCRIPT_KANNADA, 0x0C90}, |
| 684 {HB_Script_Malayalam, HB_SCRIPT_MALAYALAM, 0x0D10}, |
| 685 {HB_Script_Sinhala, HB_SCRIPT_SINHALA, 0x0D90}, |
| 686 {HB_Script_Thai, HB_SCRIPT_THAI, 0x0E01}, |
| 687 {HB_Script_Lao, HB_SCRIPT_LAO, 0x0E81}, |
| 688 {HB_Script_Tibetan, HB_SCRIPT_TIBETAN, 0x0F00}, |
| 689 {HB_Script_Myanmar, HB_SCRIPT_MYANMAR, 0x1000}, |
| 690 {HB_Script_Georgian, HB_SCRIPT_GEORGIAN, 0x10A0}, |
| 691 {HB_Script_Unknown, HB_SCRIPT_ETHIOPIC, 0x1200}, |
| 692 {HB_Script_Unknown, HB_SCRIPT_CHEROKEE, 0x13A0}, |
| 693 {HB_Script_Ogham, HB_SCRIPT_OGHAM, 0x1680}, |
| 694 {HB_Script_Runic, HB_SCRIPT_RUNIC, 0x16A0}, |
| 695 {HB_Script_Khmer, HB_SCRIPT_KHMER, 0x1780}, |
| 696 {HB_Script_Unknown, HB_SCRIPT_TAI_LE, 0x1950}, |
| 697 {HB_Script_Unknown, HB_SCRIPT_NEW_TAI_LUE, 0x1980}, |
| 698 {HB_Script_Unknown, HB_SCRIPT_TAI_THAM, 0x1A20}, |
| 699 {HB_Script_Unknown, HB_SCRIPT_CHAM, 0xAA00}, |
| 700 }; |
| 701 |
| 702 static hb_script_t getHBScriptFromHBScriptOld(HB_Script script_old) { |
| 703 hb_script_t script = HB_SCRIPT_INVALID; |
| 704 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMa
pping); |
| 705 for (int i = 0; i < numSupportedFonts; i++) { |
| 706 if (script_old == HB_UnicodeMappingArray[i].script_old) { |
| 707 script = HB_UnicodeMappingArray[i].script; |
| 708 break; |
| 709 } |
| 710 } |
| 711 return script; |
| 712 } |
| 713 |
| 714 // returns 0 for "Not Found" |
| 715 static SkUnichar getUnicodeFromHBScript(hb_script_t script) { |
| 716 SkUnichar unichar = 0; |
| 717 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMa
pping); |
| 718 for (int i = 0; i < numSupportedFonts; i++) { |
| 719 if (script == HB_UnicodeMappingArray[i].script) { |
| 720 unichar = HB_UnicodeMappingArray[i].unicode; |
| 721 break; |
| 722 } |
| 723 } |
| 724 return unichar; |
| 725 } |
| 726 |
| 727 struct TypefaceLookupStruct { |
| 728 hb_script_t script; |
| 729 SkTypeface::Style style; |
| 730 SkPaintOptionsAndroid::FontVariant fontVariant; |
| 731 SkTypeface* typeface; |
| 732 }; |
| 733 |
| 734 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex); // This is the mutex for gTypefac
eTable |
| 735 static SkTDArray<TypefaceLookupStruct> gTypefaceTable; // This is protected by
gTypefaceTableMutex |
| 736 |
| 737 static int typefaceLookupCompare(const TypefaceLookupStruct& first, |
| 738 const TypefaceLookupStruct& second) { |
| 739 if (first.script != second.script) { |
| 740 return (first.script > second.script) ? 1 : -1; |
| 741 } |
| 742 if (first.style != second.style) { |
| 743 return (first.style > second.style) ? 1 : -1; |
| 744 } |
| 745 if (first.fontVariant != second.fontVariant) { |
| 746 return (first.fontVariant > second.fontVariant) ? 1 : -1; |
| 747 } |
| 748 return 0; |
| 749 } |
| 750 |
| 751 SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style st
yle, |
| 752 SkPaintOptionsAndroid::FontVariant fontV
ariant) { |
| 753 SkAutoMutexAcquire ac(gTypefaceTableMutex); |
| 754 |
| 755 TypefaceLookupStruct key; |
| 756 key.script = script; |
| 757 key.style = style; |
| 758 key.fontVariant = fontVariant; |
| 759 |
| 760 int index = SkTSearch<TypefaceLookupStruct>( |
| 761 (const TypefaceLookupStruct*) gTypefaceTable.begin(), |
| 762 gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct), |
| 763 typefaceLookupCompare); |
| 764 |
| 765 SkTypeface* retTypeface = NULL; |
| 766 if (index >= 0) { |
| 767 retTypeface = gTypefaceTable[index].typeface; |
| 768 } |
| 769 else { |
| 770 SkUnichar unichar = getUnicodeFromHBScript(script); |
| 771 if (!unichar) { |
| 772 return NULL; |
| 773 } |
| 774 |
| 775 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); |
| 776 retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant
); |
| 777 |
| 778 // add to the lookup table |
| 779 key.typeface = retTypeface; |
| 780 *gTypefaceTable.insert(~index) = key; |
| 781 } |
| 782 |
| 783 // we ref(), the caller is expected to unref when they are done |
| 784 return SkSafeRef(retTypeface); |
| 785 } |
| 786 |
| 787 SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style, |
| 788 SkPaintOptionsAndroid::FontVariant fontVar
iant) { |
| 789 return SkCreateTypefaceForScriptNG(getHBScriptFromHBScriptOld(script), style
, fontVariant); |
| 790 } |
| 791 |
| 792 #endif |
| 793 |
| 794 /////////////////////////////////////////////////////////////////////////////// |
| 795 |
620 SkFontMgr* SkFontMgr::Factory() { | 796 SkFontMgr* SkFontMgr::Factory() { |
621 return NULL; | 797 return NULL; |
622 } | 798 } |
OLD | NEW |