OLD | NEW |
---|---|
(Empty) | |
1 | |
2 /* | |
3 * Copyright 2013 The Android Open Source Project | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 | |
9 #include "SkFontConfigInterface.h" | |
10 #include "SkTypeface_android.h" | |
11 | |
12 #include "SkFontConfigParser_android.h" | |
13 #include "SkFontConfigTypeface.h" | |
14 #include "SkFontHost_FreeType_common.h" | |
15 #include "SkFontMgr.h" | |
16 #include "SkGlyphCache.h" | |
17 #include "SkPaint.h" | |
18 #include "SkString.h" | |
19 #include "SkStream.h" | |
20 #include "SkThread.h" | |
21 #include "SkTypefaceCache.h" | |
22 #include "SkTArray.h" | |
23 #include "SkTDict.h" | |
24 #include "SkTSearch.h" | |
25 | |
26 #include <stdio.h> | |
27 #include <string.h> | |
28 | |
29 #ifndef SK_DEBUG_FONTS | |
30 #define SK_DEBUG_FONTS 0 | |
31 #endif | |
32 | |
33 #if SK_DEBUG_FONTS | |
34 #define DEBUG_FONT(args) SkDebugf args | |
35 #else | |
36 #define DEBUG_FONT(args) | |
37 #endif | |
38 | |
39 /////////////////////////////////////////////////////////////////////////////// | |
40 | |
41 // For test only. | |
42 static const char* gTestMainConfigFile = NULL; | |
43 static const char* gTestFallbackConfigFile = NULL; | |
44 static const char* gTestFontFilePrefix = NULL; | |
45 | |
46 /////////////////////////////////////////////////////////////////////////////// | |
47 | |
48 typedef int32_t FontRecID; | |
49 #define INVALID_FONT_REC_ID -1 | |
50 | |
51 typedef int32_t FamilyRecID; | |
52 #define INVALID_FAMILY_REC_ID -1 | |
53 | |
54 // used to record our notion of the pre-existing fonts | |
55 struct FontRec { | |
56 SkAutoTUnref<SkTypeface> fTypeface; | |
57 SkString fFileName; | |
58 SkTypeface::Style fStyle; | |
59 bool fIsValid; | |
60 FamilyRecID fFamilyRecID; | |
61 }; | |
62 | |
63 struct FamilyRec { | |
64 FamilyRec() { | |
65 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID)); | |
66 } | |
67 | |
68 static const int FONT_STYLE_COUNT = 4; | |
69 FontRecID fFontRecID[FONT_STYLE_COUNT]; | |
70 bool fIsFallbackFont; | |
71 SkString fFallbackName; | |
72 SkPaintOptionsAndroid fPaintOptions; | |
73 }; | |
74 | |
75 | |
76 typedef SkTDArray<FamilyRecID> FallbackFontList; | |
77 | |
78 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface { | |
79 public: | |
80 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies); | |
81 virtual ~SkFontConfigInterfaceAndroid(); | |
82 | |
83 virtual bool matchFamilyName(const char familyName[], | |
84 SkTypeface::Style requested, | |
85 FontIdentity* outFontIdentifier, | |
86 SkString* outFamilyName, | |
87 SkTypeface::Style* outStyle) SK_OVERRIDE; | |
88 virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE; | |
89 | |
90 // new APIs | |
91 virtual SkDataTable* getFamilyNames() SK_OVERRIDE; | |
92 virtual bool matchFamilySet(const char inFamilyName[], | |
93 SkString* outFamilyName, | |
94 SkTArray<FontIdentity>*) SK_OVERRIDE; | |
95 | |
96 /** | |
97 * Get the family name of the font in the default fallback font list that | |
98 * contains the specified chararacter. if no font is found, returns false. | |
99 */ | |
100 bool getFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name); | |
101 | |
102 private: | |
103 void addFallbackFamily(FamilyRecID fontRecID); | |
104 SkTypeface* getTypefaceForFontRec(FontRecID fontRecID); | |
105 FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOrigin al = true); | |
106 | |
107 SkTArray<FontRec, true> fFonts; | |
108 SkTArray<FamilyRec, true> fFontFamilies; | |
109 SkTDict<FamilyRecID> fFamilyNameDict; | |
110 FamilyRecID fDefaultFamilyRecID; | |
111 | |
112 // (SkLanguage)<->(fallback chain index) translation | |
113 SkTDict<FallbackFontList*> fFallbackFontDict; | |
114 SkTDict<FallbackFontList*> fFallbackFontAliasDict; | |
115 FallbackFontList fDefaultFallbackList; | |
116 | |
117 // fallback info for current locale | |
118 SkString fCachedLocale; | |
119 FallbackFontList* fLocaleFallbackFontList; | |
120 }; | |
121 | |
122 /////////////////////////////////////////////////////////////////////////////// | |
123 | |
124 SK_DECLARE_STATIC_MUTEX(gGetSingletonInterfaceMutex); | |
125 static SkFontConfigInterfaceAndroid* getSingletonInterface() { | |
126 static SkFontConfigInterfaceAndroid* gFontConfigInterface; | |
127 | |
128 SkAutoMutexAcquire ac(gGetSingletonInterfaceMutex); | |
129 if (NULL == gFontConfigInterface) { | |
130 // load info from a configuration file that we can use to populate the | |
131 // system/fallback font structures | |
132 SkTDArray<FontFamily*> fontFamilies; | |
133 if (!gTestMainConfigFile) { | |
134 SkFontConfigParser::GetFontFamilies(fontFamilies); | |
135 } else { | |
136 SkFontConfigParser::GetTestFontFamilies(fontFamilies, gTestMainConfi gFile, | |
137 gTestFallbackConfigFile); | |
138 } | |
139 | |
140 gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies); | |
141 | |
142 // cleanup the data we received from the parser | |
143 fontFamilies.deleteAll(); | |
144 } | |
145 return gFontConfigInterface; | |
146 } | |
147 | |
148 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase Mutex*) { | |
149 // Doesn't need passed-in mutex because getSingletonInterface() uses one | |
150 return getSingletonInterface(); | |
151 } | |
152 | |
153 /////////////////////////////////////////////////////////////////////////////// | |
154 | |
155 static bool has_font(const SkTArray<FontRec, true>& array, const SkString& filen ame) { | |
156 for (int i = 0; i < array.count(); i++) { | |
157 if (array[i].fFileName == filename) { | |
158 return true; | |
159 } | |
160 } | |
161 return false; | |
162 } | |
163 | |
164 #ifndef SK_FONT_FILE_PREFIX | |
165 #define SK_FONT_FILE_PREFIX "/fonts/" | |
166 #endif | |
167 | |
168 static void get_path_for_sys_fonts(SkString* full, const SkString& name) { | |
169 if (gTestFontFilePrefix) { | |
170 full->set(gTestFontFilePrefix); | |
171 } else { | |
172 full->set(getenv("ANDROID_ROOT")); | |
173 full->append(SK_FONT_FILE_PREFIX); | |
174 } | |
175 full->append(name); | |
176 } | |
177 | |
178 static void insert_into_name_dict(SkTDict<FamilyRecID>& familyNameDict, | |
179 const char* name, FamilyRecID familyRecID) { | |
180 SkAutoAsciiToLC tolc(name); | |
181 if (familyNameDict.find(tolc.lc())) { | |
182 SkDebugf("---- system font attempting to use a the same name [%s] for" | |
183 "multiple families. skipping subsequent occurrences", tolc.lc() ); | |
184 } else { | |
185 familyNameDict.set(tolc.lc(), familyRecID); | |
186 } | |
187 } | |
188 | |
189 /////////////////////////////////////////////////////////////////////////////// | |
190 | |
191 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily* >& fontFamilies) : | |
192 fFonts(fontFamilies.count()), | |
193 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT), | |
194 fFamilyNameDict(1024), | |
195 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID), | |
196 fFallbackFontDict(128), | |
197 fFallbackFontAliasDict(128), | |
198 fLocaleFallbackFontList(NULL) { | |
199 | |
200 for (int i = 0; i < fontFamilies.count(); ++i) { | |
201 FontFamily* family = fontFamilies[i]; | |
202 | |
203 // defer initializing the familyRec until we can be sure that at least | |
204 // one of it's children contains a valid font file | |
205 FamilyRec* familyRec = NULL; | |
206 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; | |
207 | |
208 for (int j = 0; j < family->fFonts.count(); ++j) { | |
209 SkString filename; | |
210 get_path_for_sys_fonts(&filename, family->fFonts[j].fFileName); | |
211 | |
212 if (has_font(fFonts, filename)) { | |
213 DEBUG_FONT(("---- system font and fallback font files specify a duplicate " | |
214 "font %s, skipping the second occurrence", filename.c_st r())); | |
215 } | |
216 | |
217 FontRec& fontRec = fFonts.push_back(); | |
218 fontRec.fFileName = filename; | |
219 fontRec.fStyle = SkTypeface::kNormal; | |
220 fontRec.fIsValid = false; | |
221 fontRec.fFamilyRecID = familyRecID; | |
222 | |
223 const FontRecID fontRecID = fFonts.count() - 1; | |
224 | |
225 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str() )); | |
226 if (stream.get() != NULL) { | |
227 bool isFixedWidth; | |
228 SkString name; | |
229 fontRec.fIsValid = SkTypeface_FreeType::ScanFont(stream.get(), 0 , | |
230 &name, &fontRec .fStyle, | |
231 &isFixedWidth); | |
232 } else { | |
233 if (!family->fIsFallbackFont) { | |
234 SkDebugf("---- failed to open <%s> as a font\n", filename.c_ str()); | |
235 } | |
236 } | |
237 | |
238 if (fontRec.fIsValid) { | |
239 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s", | |
240 i, fFonts.count() - 1, family->fIsFallbackFont, filen ame.c_str())); | |
241 } else { | |
242 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVAL ID)", | |
243 i, fFonts.count() - 1, family->fIsFallbackFont, filen ame.c_str())); | |
244 continue; | |
245 } | |
246 | |
247 // create a familyRec now that we know that at least one font in | |
248 // the family is valid | |
249 if (familyRec == NULL) { | |
250 familyRec = &fFontFamilies.push_back(); | |
251 familyRecID = fFontFamilies.count() - 1; | |
252 fontRec.fFamilyRecID = familyRecID; | |
253 | |
254 familyRec->fIsFallbackFont = family->fIsFallbackFont; | |
255 familyRec->fPaintOptions = family->fFonts[j].fPaintOptions; | |
256 | |
257 } else if (familyRec->fPaintOptions != family->fFonts[j].fPaintOptio ns) { | |
258 SkDebugf("Every font file within a family must have identical" | |
259 "language and variant attributes"); | |
260 sk_throw(); | |
261 } | |
262 | |
263 // add this font to the current familyRec | |
264 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) { | |
265 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d) ", | |
266 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle ], | |
267 fontRecID)); | |
268 } | |
269 familyRec->fFontRecID[fontRec.fStyle] = fontRecID; | |
270 } | |
271 | |
272 if (familyRec) { | |
273 if (familyRec->fIsFallbackFont) { | |
274 // add the font to the appropriate fallback chains and also inse rt a | |
275 // unique name into the familyNameDict for internal usage | |
276 addFallbackFamily(familyRecID); | |
277 } else { | |
278 // add the names that map to this family to the dictionary for e asy lookup | |
279 const SkTArray<SkString>& names = family->fNames; | |
280 if (names.empty()) { | |
281 SkDEBUGFAIL("ERROR: non-fallback font with no name"); | |
282 continue; | |
283 } | |
284 | |
285 for (int i = 0; i < names.count(); i++) { | |
286 insert_into_name_dict(fFamilyNameDict, names[i].c_str(), fam ilyRecID); | |
287 } | |
288 } | |
289 } | |
290 } | |
291 | |
292 DEBUG_FONT(("---- We have %d system fonts", fFonts.count())); | |
293 | |
294 if (fFontFamilies.count() > 0) { | |
295 fDefaultFamilyRecID = 0; | |
296 } | |
297 | |
298 // scans the default fallback font chain, adding every entry to every other | |
299 // fallback font chain to which it does not belong. this results in every | |
300 // language-specific fallback font chain having all of its fallback fonts at | |
301 // the front of the chain, and everything else at the end. | |
302 FallbackFontList* fallbackList; | |
303 SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict); | |
304 const char* fallbackLang = iter.next(&fallbackList); | |
305 while(fallbackLang != NULL) { | |
306 for (int i = 0; i < fDefaultFallbackList.count(); i++) { | |
307 FamilyRecID familyRecID = fDefaultFallbackList[i]; | |
308 const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions. getLanguage().getTag(); | |
309 if (strcmp(fallbackLang, fontLang.c_str()) != 0) { | |
310 fallbackList->push(familyRecID); | |
311 } | |
312 } | |
313 // move to the next fallback list in the dictionary | |
314 fallbackLang = iter.next(&fallbackList); | |
315 } | |
316 } | |
317 | |
318 SkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() { | |
319 // iterate through and cleanup fFallbackFontDict | |
320 SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict); | |
321 FallbackFontList* fallbackList; | |
322 while(iter.next(&fallbackList) != NULL) { | |
323 SkDELETE(fallbackList); | |
324 } | |
325 } | |
326 | |
327 void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) { | |
328 SkASSERT(familyRecID < fFontFamilies.count()); | |
329 FamilyRec& familyRec = fFontFamilies[familyRecID]; | |
330 SkASSERT(familyRec.fIsFallbackFont); | |
331 | |
332 // add the fallback family to the name dictionary. This is | |
333 // needed by getFallbackFamilyNameForChar() so that fallback | |
334 // families can be identified by a unique name. The unique | |
335 // identifier that we've chosen is the familyID in hex (e.g. '0F##fallback') . | |
336 familyRec.fFallbackName.printf("%.2x##fallback", familyRecID); | |
337 insert_into_name_dict(fFamilyNameDict, familyRec.fFallbackName.c_str(), fami lyRecID); | |
338 | |
339 // add to the default fallback list | |
340 fDefaultFallbackList.push(familyRecID); | |
341 | |
342 // stop here if it is the default language tag | |
343 const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag() ; | |
344 if (languageTag.isEmpty()) { | |
345 return; | |
346 } | |
347 | |
348 // add to the appropriate language's custom fallback list | |
349 FallbackFontList* customList = NULL; | |
350 if (!fFallbackFontDict.find(languageTag.c_str(), &customList)) { | |
351 DEBUG_FONT(("---- Created fallback list for \"%s\"", languageTag.c_str( ))); | |
352 customList = SkNEW(FallbackFontList); | |
353 fFallbackFontDict.set(languageTag.c_str(), customList); | |
354 } | |
355 SkASSERT(customList != NULL); | |
356 customList->push(familyRecID); | |
357 } | |
358 | |
359 | |
360 static FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style styl e) { | |
361 | |
362 const FontRecID* fontRecIDs = family.fFontRecID; | |
363 | |
364 if (fontRecIDs[style] != INVALID_FONT_REC_ID) { // exact match | |
365 return fontRecIDs[style]; | |
366 } | |
367 // look for a matching bold | |
368 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); | |
369 if (fontRecIDs[style] != INVALID_FONT_REC_ID) { | |
370 return fontRecIDs[style]; | |
371 } | |
372 // look for the plain | |
373 if (fontRecIDs[SkTypeface::kNormal] != INVALID_FONT_REC_ID) { | |
374 return fontRecIDs[SkTypeface::kNormal]; | |
375 } | |
376 // look for anything | |
377 for (int i = 0; i < FamilyRec::FONT_STYLE_COUNT; i++) { | |
378 if (fontRecIDs[i] != INVALID_FONT_REC_ID) { | |
379 return fontRecIDs[i]; | |
380 } | |
381 } | |
382 // should never get here, since the fontRecID list should not be empty | |
383 SkDEBUGFAIL("No valid fonts exist for this family"); | |
384 return -1; | |
385 } | |
386 | |
387 bool SkFontConfigInterfaceAndroid::matchFamilyName(const char familyName[], | |
388 SkTypeface::Style style, | |
389 FontIdentity* outFontIdentifi er, | |
390 SkString* outFamilyName, | |
391 SkTypeface::Style* outStyle) { | |
392 // clip to legal style bits | |
393 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); | |
394 | |
395 bool exactNameMatch = false; | |
396 | |
397 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; | |
398 if (NULL != familyName) { | |
399 SkAutoAsciiToLC tolc(familyName); | |
400 if (fFamilyNameDict.find(tolc.lc(), &familyRecID)) { | |
401 exactNameMatch = true; | |
402 } | |
403 } else { | |
404 familyRecID = fDefaultFamilyRecID; | |
405 | |
406 } | |
407 | |
408 // If no matching family name is found then return false. This allows client s | |
409 // to be able to search for other fonts instead of forcing them to use the | |
410 // default font. | |
411 if (INVALID_FAMILY_REC_ID == familyRecID) { | |
412 return false; | |
413 } | |
414 | |
415 FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style); | |
416 FontRec& fontRec = fFonts[fontRecID]; | |
417 | |
418 if (NULL != outFontIdentifier) { | |
419 outFontIdentifier->fID = fontRecID; | |
420 outFontIdentifier->fTTCIndex = 0; | |
421 outFontIdentifier->fString.set(fontRec.fFileName); | |
422 // outFontIdentifier->fStyle = fontRec.fStyle; | |
423 } | |
424 | |
425 if (NULL != outFamilyName) { | |
426 if (exactNameMatch) { | |
427 outFamilyName->set(familyName); | |
428 } else { | |
429 // find familyName from list of names | |
430 const char* familyName = NULL; | |
431 SkAssertResult(fFamilyNameDict.findKey(familyRecID, &familyName)); | |
432 SkASSERT(familyName); | |
433 outFamilyName->set(familyName); | |
434 } | |
435 } | |
436 | |
437 if (NULL != outStyle) { | |
438 *outStyle = fontRec.fStyle; | |
439 } | |
440 | |
441 return true; | |
442 } | |
443 | |
444 SkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) { | |
445 return SkStream::NewFromFile(identity.fString.c_str()); | |
446 } | |
447 | |
448 SkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() { | |
449 SkTDArray<const char*> names; | |
450 SkTDArray<size_t> sizes; | |
451 | |
452 SkTDict<FamilyRecID>::Iter iter(fFamilyNameDict); | |
453 const char* familyName = iter.next(NULL); | |
454 while(familyName != NULL) { | |
455 *names.append() = familyName; | |
456 *sizes.append() = strlen(familyName) + 1; | |
457 | |
458 // move to the next familyName in the dictionary | |
459 familyName = iter.next(NULL); | |
460 } | |
461 | |
462 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), | |
463 sizes.begin(), names.count()); | |
464 } | |
465 | |
466 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[], | |
467 SkString* outFamilyName, | |
468 SkTArray<FontIdentity>*) { | |
469 return false; | |
470 } | |
471 | |
472 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) { | |
473 const FontRecID* fontRecID = (const FontRecID*)ctx; | |
474 FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID; | |
475 return currFontRecID == *fontRecID; | |
476 } | |
477 | |
478 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRe cID) { | |
479 FontRec& fontRec = fFonts[fontRecID]; | |
480 SkTypeface* face = fontRec.fTypeface.get(); | |
481 if (!face) { | |
482 // look for it in the typeface cache | |
483 face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID); | |
484 | |
485 // if it is not in the cache then create it | |
486 if (!face) { | |
487 const char* familyName = NULL; | |
488 SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &family Name)); | |
489 SkASSERT(familyName); | |
490 face = SkTypeface::CreateFromName(familyName, fontRec.fStyle); | |
491 } | |
492 | |
493 // store the result for subsequent lookups | |
494 fontRec.fTypeface.reset(face); | |
495 } | |
496 SkASSERT(face); | |
497 return face; | |
498 } | |
499 | |
500 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, | |
501 const char* lang , | |
502 SkString* name) { | |
503 const SkString locale(lang); | |
504 if (NULL == fLocaleFallbackFontList || locale != fCachedLocale) { | |
505 fCachedLocale = locale; | |
506 fLocaleFallbackFontList = this->findFallbackFontList(locale); | |
507 } | |
508 FallbackFontList* fallbackFontList = fLocaleFallbackFontList; | |
509 | |
510 for (int i = 0; i < fallbackFontList->count(); i++) { | |
511 FamilyRecID familyRecID = fallbackFontList->getAt(i); | |
512 | |
513 // if it is not one of the accepted variants then move to the next famil y | |
514 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | | |
515 SkPaintOptionsAndroid::kElegant_Variant; | |
516 if (!(fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & accept edVariants)) { | |
517 continue; | |
518 } | |
519 | |
520 FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkType face::kNormal); | |
521 SkTypeface* face = this->getTypefaceForFontRec(fontRecID); | |
522 | |
523 SkPaint paint; | |
524 paint.setTypeface(face); | |
525 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
526 | |
527 uint16_t glyphID; | |
528 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); | |
529 if (glyphID != 0) { | |
530 name->set(fFontFamilies[familyRecID].fFallbackName); | |
531 return true; | |
532 } | |
533 } | |
534 return false; | |
535 } | |
536 | |
537 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLan guage& lang, | |
538 bool isOrig inal) { | |
539 const SkString& langTag = lang.getTag(); | |
540 if (langTag.isEmpty()) { | |
541 return &fDefaultFallbackList; | |
542 } | |
543 | |
544 FallbackFontList* fallbackFontList; | |
545 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontLis t) || | |
546 fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFo ntList)) { | |
547 return fallbackFontList; | |
548 } | |
549 | |
550 // attempt a recursive fuzzy match | |
551 SkLanguage parent = lang.getParent(); | |
552 fallbackFontList = findFallbackFontList(parent, false); | |
553 | |
554 // cache the original lang so we don't have to do the recursion again. | |
555 if (isOriginal) { | |
556 DEBUG_FONT(("---- Created fallback list alias for \"%s\"", langTag.c_st r())); | |
557 fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList); | |
558 } | |
559 return fallbackFontList; | |
560 } | |
561 | |
562 /////////////////////////////////////////////////////////////////////////////// | |
563 | |
564 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* n ame) { | |
565 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); | |
566 return fontConfig->getFallbackFamilyNameForChar(uni, lang, name); | |
567 } | |
568 | |
569 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, | |
bungeman-skia
2014/08/11 20:11:40
This and the following one (SkGetTestFontConfigura
| |
570 const char* fontsdir) { | |
571 gTestMainConfigFile = mainconf; | |
572 gTestFallbackConfigFile = fallbackconf; | |
573 gTestFontFilePrefix = fontsdir; | |
574 SkASSERT(gTestMainConfigFile); | |
575 SkASSERT(gTestFallbackConfigFile); | |
576 SkASSERT(gTestFontFilePrefix); | |
577 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s", | |
578 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix) ); | |
579 } | |
580 | |
581 void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf , | |
582 const char** fontsdir) { | |
583 *mainconf = gTestMainConfigFile; | |
584 *fallbackconf = gTestFallbackConfigFile; | |
585 *fontsdir = gTestFontFilePrefix; | |
586 } | |
OLD | NEW |