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 "SkFontMgr.h" 15 #include "SkGlyphCache.h" 16 #include "SkPaint.h" 17 #include "SkString.h" 18 #include "SkStream.h" 19 #include "SkThread.h" 20 #include "SkTypefaceCache.h" 21 #include "SkTArray.h" 22 #include "SkTDict.h" 23 #include "SkTSearch.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 28 #ifndef SK_DEBUG_FONTS 29 #define SK_DEBUG_FONTS 0 30 #endif 31 32 #if SK_DEBUG_FONTS 33 #define DEBUG_FONT(args) SkDebugf args 34 #else 35 #define DEBUG_FONT(args) 36 #endif 37 38 /////////////////////////////////////////////////////////////////////////////// 39 40 // For test only. 41 static const char* gTestMainConfigFile = NULL; 42 static const char* gTestFallbackConfigFile = NULL; 43 static const char* gTestFontFilePrefix = NULL; 44 45 /////////////////////////////////////////////////////////////////////////////// 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 53 // used to record our notion of the pre-existing fonts 54 struct FontRec { 55 SkRefPtr<SkTypeface> fTypeface; 56 SkString fFileName; 57 SkTypeface::Style fStyle; 58 bool fIsValid; 59 FamilyRecID fFamilyRecID; 60 }; 61 62 struct FamilyRec { 63 FamilyRec() { 64 memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID)); 65 } 66 67 static const int FONT_STYLE_COUNT = 4; 68 FontRecID fFontRecID[FONT_STYLE_COUNT]; 69 bool fIsFallbackFont; 70 SkPaintOptionsAndroid fPaintOptions; 71 }; 72 73 74 typedef SkTDArray<FamilyRecID> FallbackFontList; 75 76 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface { 77 public: 78 SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies); 79 virtual ~SkFontConfigInterfaceAndroid(); 80 81 virtual bool matchFamilyName(const char familyName[], 82 SkTypeface::Style requested, 83 FontIdentity* outFontIdentifier, 84 SkString* outFamilyName, 85 SkTypeface::Style* outStyle) SK_OVERRIDE; 86 virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE; 87 88 // new APIs 89 virtual SkDataTable* getFamilyNames() SK_OVERRIDE; 90 virtual bool matchFamilySet(const char inFamilyName[], 91 SkString* outFamilyName, 92 SkTArray<FontIdentity>*) SK_OVERRIDE; 93 94 /** 95 * Get the family name of the font in the default fallback font list that 96 * contains the specified chararacter. if no font is found, returns false. 97 */ 98 bool getFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name); 99 /** 100 * 101 */ 102 SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style, 103 SkPaintOptionsAndroid::FontVariant fontVariant); 104 SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, 105 const SkPaintOptionsAndroid& options); 106 SkTypeface* getTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface, 107 const SkPaintOptionsAndroid& options, 108 int* lowerBounds, int* upperBounds); 109 110 private: 111 void addFallbackFamily(FamilyRecID fontRecID); 112 SkTypeface* getTypefaceForFontRec(FontRecID fontRecID); 113 FallbackFontList* getCurrentLocaleFallbackFontList(); 114 FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true); 115 116 SkTArray<FontRec> fFonts; 117 SkTArray<FamilyRec> fFontFamilies; 118 SkTDict<FamilyRecID> fFamilyNameDict; 119 FamilyRecID fDefaultFamilyRecID; 120 121 // (SkLanguage)<->(fallback chain index) translation 122 SkTDict<FallbackFontList*> fFallbackFontDict; 123 SkTDict<FallbackFontList*> fFallbackFontAliasDict; 124 FallbackFontList fDefaultFallbackList; 125 126 // fallback info for current locale 127 SkString fCachedLocale; 128 FallbackFontList* fLocaleFallbackFontList; 129 }; 130 131 /////////////////////////////////////////////////////////////////////////////// 132 133 static SkFontConfigInterfaceAndroid* getSingletonInterface() { 134 SK_DECLARE_STATIC_MUTEX(gMutex); 135 static SkFontConfigInterfaceAndroid* gFontConfigInterface; 136 137 SkAutoMutexAcquire ac(gMutex); 138 if (NULL == gFontConfigInterface) { 139 // load info from a configuration file that we can use to populate the 140 // system/fallback font structures 141 SkTDArray<FontFamily*> fontFamilies; 142 if (!gTestMainConfigFile) { 143 SkFontConfigParser::GetFontFamilies(fontFamilies); 144 } else { 145 SkFontConfigParser::GetTestFontFamilies(fontFamilies, gTestMainConfigFile, 146 gTestFallbackConfigFile); 147 } 148 149 gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies); 150 151 // cleanup the data we received from the parser 152 fontFamilies.deleteAll(); 153 } 154 return gFontConfigInterface; 155 } 156 157 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() { 158 return getSingletonInterface(); 159 } 160 161 /////////////////////////////////////////////////////////////////////////////// 162 163 static bool has_font(const SkTArray<FontRec>& array, const SkString& filename) { 164 for (int i = 0; i < array.count(); i++) { 165 if (array[i].fFileName == filename) { 166 return true; 167 } 168 } 169 return false; 170 } 171 172 #ifndef SK_FONT_FILE_PREFIX 173 #define SK_FONT_FILE_PREFIX "/fonts/" 174 #endif 175 176 static void get_path_for_sys_fonts(SkString* full, const char name[]) { 177 if (gTestFontFilePrefix) { 178 full->set(gTestFontFilePrefix); 179 } else { 180 full->set(getenv("ANDROID_ROOT")); 181 full->append(SK_FONT_FILE_PREFIX); 182 } 183 full->append(name); 184 } 185 186 static void insert_into_name_dict(SkTDict<FamilyRecID>& familyNameDict, 187 const char* name, FamilyRecID familyRecID) { 188 SkAutoAsciiToLC tolc(name); 189 if (familyNameDict.find(tolc.lc())) { 190 SkDebugf("---- system font attempting to use a the same name [%s] for" 191 "multiple families. skipping subsequent occurrences", tolc.lc()); 192 } else { 193 familyNameDict.set(tolc.lc(), familyRecID); 194 } 195 } 196 197 // Defined in SkFontHost_FreeType.cpp 198 bool find_name_and_attributes(SkStream* stream, SkString* name, 199 SkTypeface::Style* style, bool* isFixedWidth); 200 201 /////////////////////////////////////////////////////////////////////////////// 202 203 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies) : 204 fFonts(fontFamilies.count()), 205 fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT), 206 fFamilyNameDict(1024), 207 fDefaultFamilyRecID(INVALID_FAMILY_REC_ID), 208 fFallbackFontDict(128), 209 fFallbackFontAliasDict(128), 210 fLocaleFallbackFontList(NULL) { 211 212 for (int i = 0; i < fontFamilies.count(); ++i) { 213 FontFamily* family = fontFamilies[i]; 214 215 // defer initializing the familyRec until we can be sure that at least 216 // one of it's children contains a valid font file 217 FamilyRec* familyRec = NULL; 218 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; 219 220 for (int j = 0; j < family->fFontFiles.count(); ++j) { 221 SkString filename; 222 get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName); 223 224 if (has_font(fFonts, filename)) { 225 SkDebugf("---- system font and fallback font files specify a duplicate " 226 "font %s, skipping the second occurrence", filename.c_str()); 227 continue; 228 } 229 230 FontRec& fontRec = fFonts.push_back(); 231 fontRec.fFileName = filename; 232 fontRec.fStyle = SkTypeface::kNormal; 233 fontRec.fIsValid = false; 234 fontRec.fFamilyRecID = familyRecID; 235 236 const FontRecID fontRecID = fFonts.count() - 1; 237 238 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str())); 239 if (stream.get() != NULL) { 240 bool isFixedWidth; 241 SkString name; 242 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name, 243 &fontRec.fStyle, &isFixedWidth); 244 } else { 245 if (!family->fIsFallbackFont) { 246 SkDebugf("---- failed to open <%s> as a font\n", filename.c_str()); 247 } 248 } 249 250 if (fontRec.fIsValid) { 251 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s", 252 i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str())); 253 } else { 254 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVALID)", 255 i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str())); 256 continue; 257 } 258 259 // create a familyRec now that we know that at least one font in 260 // the family is valid 261 if (familyRec == NULL) { 262 familyRec = &fFontFamilies.push_back(); 263 familyRecID = fFontFamilies.count() - 1; 264 fontRec.fFamilyRecID = familyRecID; 265 266 familyRec->fIsFallbackFont = family->fIsFallbackFont; 267 familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions; 268 269 // if this is a fallback font then add it to the appropriate fallback chains 270 if (familyRec->fIsFallbackFont) { 271 addFallbackFamily(familyRecID); 272 } 273 } else if (familyRec->fPaintOptions != family->fFontFiles[j]->fPaintOptions) { 274 SkDebugf("Every font file within a family must have identical" 275 "language and variant attributes"); 276 sk_throw(); 277 } 278 279 // add this font to the current familyRec 280 if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) { 281 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)", 282 fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle], 283 fontRecID)); 284 } 285 familyRec->fFontRecID[fontRec.fStyle] = fontRecID; 286 287 // add the fallback file name to the name dictionary. This is needed 288 // by getFallbackFamilyNameForChar() so that fallback families can be 289 // requested by the filenames of the fonts they contain. 290 if (familyRec && familyRec->fIsFallbackFont) { 291 insert_into_name_dict(fFamilyNameDict, fontRec.fFileName.c_str(), familyRecID); 292 } 293 } 294 295 // add the names that map to this family to the dictionary for easy lookup 296 if (familyRec && !familyRec->fIsFallbackFont) { 297 SkTDArray<const char*> names = family->fNames; 298 if (names.isEmpty()) { 299 SkDEBUGFAIL("ERROR: non-fallback font with no name"); 300 continue; 301 } 302 303 for (int i = 0; i < names.count(); i++) { 304 insert_into_name_dict(fFamilyNameDict, names[i], familyRecID); 305 } 306 } 307 308 } 309 310 DEBUG_FONT(("---- We have %d system fonts", fFonts.count())); 311 312 if (fFontFamilies.count() > 0) { 313 fDefaultFamilyRecID = 0; 314 } 315 316 // scans the default fallback font chain, adding every entry to every other 317 // fallback font chain to which it does not belong. this results in every 318 // language-specific fallback font chain having all of its fallback fonts at 319 // the front of the chain, and everything else at the end. 320 FallbackFontList* fallbackList; 321 SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict); 322 const char* fallbackLang = iter.next(&fallbackList); 323 while(fallbackLang != NULL) { 324 for (int i = 0; i < fDefaultFallbackList.count(); i++) { 325 FamilyRecID familyRecID = fDefaultFallbackList[i]; 326 const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions.getLanguage().getTag(); 327 if (strcmp(fallbackLang, fontLang.c_str()) != 0) { 328 fallbackList->push(familyRecID); 329 } 330 } 331 // move to the next fallback list in the dictionary 332 fallbackLang = iter.next(&fallbackList); 333 } 334 } 335 336 SkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() { 337 // iterate through and cleanup fFallbackFontDict 338 SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict); 339 FallbackFontList* fallbackList; 340 while(iter.next(&fallbackList) != NULL) { 341 SkDELETE(fallbackList); 342 } 343 } 344 345 void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) { 346 SkASSERT(familyRecID < fFontFamilies.count()); 347 const FamilyRec& familyRec = fFontFamilies[familyRecID]; 348 SkASSERT(familyRec.fIsFallbackFont); 349 350 // add to the default fallback list 351 fDefaultFallbackList.push(familyRecID); 352 353 // stop here if it is the default language tag 354 const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag(); 355 if (languageTag.isEmpty()) { 356 return; 357 } 358 359 // add to the appropriate language's custom fallback list 360 FallbackFontList* customList = NULL; 361 if (!fFallbackFontDict.find(languageTag.c_str(), &customList)) { 362 DEBUG_FONT(("---- Created fallback list for \"%s\"", languageTag.c_str())); 363 customList = SkNEW(FallbackFontList); 364 fFallbackFontDict.set(languageTag.c_str(), customList); 365 } 366 SkASSERT(customList != NULL); 367 customList->push(familyRecID); 368 } 369 370 371 static FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style style) { 372 373 const FontRecID* fontRecIDs = family.fFontRecID; 374 375 if (fontRecIDs[style] != INVALID_FONT_REC_ID) { // exact match 376 return fontRecIDs[style]; 377 } 378 // look for a matching bold 379 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 380 if (fontRecIDs[style] != INVALID_FONT_REC_ID) { 381 return fontRecIDs[style]; 382 } 383 // look for the plain 384 if (fontRecIDs[SkTypeface::kNormal] != INVALID_FONT_REC_ID) { 385 return fontRecIDs[SkTypeface::kNormal]; 386 } 387 // look for anything 388 for (int i = 0; i < FamilyRec::FONT_STYLE_COUNT; i++) { 389 if (fontRecIDs[i] != INVALID_FONT_REC_ID) { 390 return fontRecIDs[i]; 391 } 392 } 393 // should never get here, since the fontRecID list should not be empty 394 SkDEBUGFAIL("No valid fonts exist for this family"); 395 return -1; 396 } 397 398 bool SkFontConfigInterfaceAndroid::matchFamilyName(const char familyName[], 399 SkTypeface::Style style, 400 FontIdentity* outFontIdentifier, 401 SkString* outFamilyName, 402 SkTypeface::Style* outStyle) { 403 // clip to legal style bits 404 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 405 406 bool exactNameMatch = false; 407 408 FamilyRecID familyRecID = INVALID_FAMILY_REC_ID; 409 if (NULL != familyName) { 410 SkAutoAsciiToLC tolc(familyName); 411 if (fFamilyNameDict.find(tolc.lc(), &familyRecID)) { 412 exactNameMatch = true; 413 } 414 } else { 415 familyRecID = fDefaultFamilyRecID; 416 417 } 418 419 // If no matching family name is found then return false. This allows clients 420 // to be able to search for other fonts instead of forcing them to use the 421 // default font. 422 if (INVALID_FAMILY_REC_ID == familyRecID) { 423 return false; 424 } 425 426 FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style); 427 FontRec& fontRec = fFonts[fontRecID]; 428 429 if (NULL != outFontIdentifier) { 430 outFontIdentifier->fID = fontRecID; 431 outFontIdentifier->fTTCIndex = 0; 432 outFontIdentifier->fString.set(fontRec.fFileName); 433 // outFontIdentifier->fStyle = fontRec.fStyle; 434 } 435 436 if (NULL != outFamilyName) { 437 if (exactNameMatch) { 438 outFamilyName->set(familyName); 439 } else { 440 // find familyName from list of names 441 const char* familyName = NULL; 442 SkAssertResult(fFamilyNameDict.findKey(familyRecID, &familyName)); 443 SkASSERT(familyName); 444 outFamilyName->set(familyName); 445 } 446 } 447 448 if (NULL != outStyle) { 449 *outStyle = fontRec.fStyle; 450 } 451 452 return true; 453 } 454 455 SkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) { 456 return SkStream::NewFromFile(identity.fString.c_str()); 457 } 458 459 SkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() { 460 SkTDArray<const char*> names; 461 SkTDArray<size_t> sizes; 462 463 SkTDict<FamilyRecID>::Iter iter(fFamilyNameDict); 464 const char* familyName = iter.next(NULL); 465 while(familyName != NULL) { 466 *names.append() = familyName; 467 *sizes.append() = strlen(familyName) + 1; 468 469 // move to the next familyName in the dictionary 470 familyName = iter.next(NULL); 471 } 472 473 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), 474 sizes.begin(), names.count()); 475 } 476 477 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[], 478 SkString* outFamilyName, 479 SkTArray<FontIdentity>*) { 480 return false; 481 } 482 483 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) { 484 const FontRecID* fontRecID = (const FontRecID*)ctx; 485 FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID; 486 return currFontRecID == *fontRecID; 487 } 488 489 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRecID) { 490 FontRec& fontRec = fFonts[fontRecID]; 491 SkTypeface* face = fontRec.fTypeface.get(); 492 if (!face) { 493 // look for it in the typeface cache 494 face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID); 495 496 // if it is not in the cache then create it 497 if (!face) { 498 const char* familyName = NULL; 499 SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &familyName)); 500 SkASSERT(familyName); 501 face = SkTypeface::CreateFromName(familyName, fontRec.fStyle); 502 } 503 504 // store the result for subsequent lookups 505 fontRec.fTypeface = face; 506 } 507 SkASSERT(face); 508 return face; 509 } 510 511 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, 512 const char* lang, 513 SkString* name) { 514 FallbackFontList* fallbackFontList = NULL; 515 const SkString langTag(lang); 516 if (langTag.isEmpty()) { 517 fallbackFontList = this->getCurrentLocaleFallbackFontList(); 518 } else { 519 fallbackFontList = this->findFallbackFontList(langTag); 520 } 521 522 for (int i = 0; i < fallbackFontList->count(); i++) { 523 FamilyRecID familyRecID = fallbackFontList->getAt(i); 524 525 // if it is not one of the accepted variants then move to the next family 526 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | 527 SkPaintOptionsAndroid::kElegant_Variant; 528 if (!(fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants)) { 529 continue; 530 } 531 532 FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal); 533 SkTypeface* face = this->getTypefaceForFontRec(fontRecID); 534 535 SkPaint paint; 536 paint.setTypeface(face); 537 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 538 539 uint16_t glyphID; 540 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); 541 if (glyphID != 0) { 542 name->set(fFonts[fontRecID].fFileName); 543 return true; 544 } 545 } 546 return false; 547 } 548 549 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni, 550 SkTypeface::Style style, 551 SkPaintOptionsAndroid::FontVariant fontVariant) { 552 FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], style); 553 SkTypeface* face = this->getTypefaceForFontRec(fontRecID); 554 555 SkPaintOptionsAndroid paintOptions; 556 paintOptions.setFontVariant(fontVariant); 557 paintOptions.setUseFontFallbacks(true); 558 559 SkPaint paint; 560 paint.setTypeface(face); 561 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 562 paint.setPaintOptionsAndroid(paintOptions); 563 564 SkAutoGlyphCache autoCache(paint, NULL, NULL); 565 SkGlyphCache* cache = autoCache.getCache(); 566 567 SkScalerContext* ctx = cache->getScalerContext(); 568 if (ctx) { 569 SkFontID fontID = ctx->findTypefaceIdForChar(uni); 570 return SkTypefaceCache::FindByID(fontID); 571 } 572 return NULL; 573 } 574 575 FallbackFontList* SkFontConfigInterfaceAndroid::getCurrentLocaleFallbackFontList() { 576 SkString locale = SkFontConfigParser::GetLocale(); 577 if (NULL == fLocaleFallbackFontList || locale != fCachedLocale) { 578 fCachedLocale = locale; 579 fLocaleFallbackFontList = this->findFallbackFontList(locale); 580 } 581 return fLocaleFallbackFontList; 582 } 583 584 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLanguage& lang, 585 bool isOriginal) { 586 const SkString& langTag = lang.getTag(); 587 if (langTag.isEmpty()) { 588 return &fDefaultFallbackList; 589 } 590 591 FallbackFontList* fallbackFontList; 592 if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontList) || 593 fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFontList)) { 594 return fallbackFontList; 595 } 596 597 // attempt a recursive fuzzy match 598 SkLanguage parent = lang.getParent(); 599 fallbackFontList = findFallbackFontList(parent, false); 600 601 // cache the original lang so we don't have to do the recursion again. 602 if (isOriginal) { 603 DEBUG_FONT(("---- Created fallback list alias for \"%s\"", langTag.c_str())); 604 fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList); 605 } 606 return fallbackFontList; 607 } 608 609 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontID, 610 SkFontID origFontID, 611 const SkPaintOptionsAndroid& opts) { 612 // Skia does not support font fallback by default. This enables clients such 613 // as WebKit to customize their font selection. In any case, clients can use 614 // GetFallbackFamilyNameForChar() to get the fallback font for individual 615 // characters. 616 if (!opts.isUsingFontFallbacks()) { 617 return NULL; 618 } 619 620 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage()); 621 SkASSERT(currentFallbackList); 622 623 SkTypeface::Style origStyle = SkTypeface::kNormal; 624 const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID); 625 if (NULL != origTypeface) { 626 origStyle = origTypeface->style(); 627 } 628 629 // we must convert currTypeface into a FontRecID 630 FontRecID currFontRecID = INVALID_FONT_REC_ID; 631 const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID); 632 // non-system fonts are not in the font cache so if we are asked to fallback 633 // for a non-system font we will start at the front of the chain. 634 if (NULL != currTypeface) { 635 currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity().fID; 636 SkASSERT(INVALID_FONT_REC_ID != currFontRecID); 637 } 638 639 FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID; 640 if (INVALID_FONT_REC_ID != currFontRecID) { 641 currFamilyRecID = fFonts[currFontRecID].fFamilyRecID; 642 } 643 644 // lookup the index next font in the chain 645 int currFallbackFontIndex = currentFallbackList->find(currFamilyRecID); 646 // We add 1 to the returned index for 2 reasons: (1) if find succeeds it moves 647 // our index to the next entry in the list; (2) if find() fails it returns 648 // -1 and incrementing it will set our starting index to 0 (the head of the list) 649 int nextFallbackFontIndex = currFallbackFontIndex + 1; 650 651 if(nextFallbackFontIndex >= currentFallbackList->count()) { 652 return NULL; 653 } 654 655 // If a rec object is set to prefer "kDefault_Variant" it means they have no preference 656 // In this case, we set the value to "kCompact_Variant" 657 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant(); 658 if (variant == SkPaintOptionsAndroid::kDefault_Variant) { 659 variant = SkPaintOptionsAndroid::kCompact_Variant; 660 } 661 662 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant; 663 664 SkTypeface* nextLogicalTypeface = 0; 665 while (nextFallbackFontIndex < currentFallbackList->count()) { 666 FamilyRecID familyRecID = currentFallbackList->getAt(nextFallbackFontIndex); 667 if ((fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) { 668 FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle); 669 nextLogicalTypeface = this->getTypefaceForFontRec(matchedFont); 670 break; 671 } 672 nextFallbackFontIndex++; 673 } 674 675 DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%d, " 676 "lang=%s, variant=%d, nextFallbackIndex[%d,%d] => nextLogicalTypeface=%d", 677 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag().c_str(), 678 variant, nextFallbackFontIndex, currentFallbackList->getAt(nextFallbackFontIndex), 679 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0)); 680 return SkSafeRef(nextLogicalTypeface); 681 } 682 683 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForGlyphID(uint16_t glyphID, 684 const SkTypeface* origTypeface, 685 const SkPaintOptionsAndroid& opts, 686 int* lBounds, int* uBounds) { 687 // If we aren't using fallbacks then we shouldn't be calling this 688 SkASSERT(opts.isUsingFontFallbacks()); 689 SkASSERT(origTypeface); 690 691 SkTypeface* currentTypeface = NULL; 692 int lowerBounds = 0; //inclusive 693 int upperBounds = origTypeface->countGlyphs(); //exclusive 694 695 // check to see if the glyph is in the bounds of the origTypeface 696 if (glyphID < upperBounds) { 697 currentTypeface = const_cast<SkTypeface*>(origTypeface); 698 } else { 699 FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage()); 700 SkASSERT(currentFallbackList); 701 702 // If an object is set to prefer "kDefault_Variant" it means they have no preference 703 // In this case, we set the value to "kCompact_Variant" 704 SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant(); 705 if (variant == SkPaintOptionsAndroid::kDefault_Variant) { 706 variant = SkPaintOptionsAndroid::kCompact_Variant; 707 } 708 709 int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant; 710 SkTypeface::Style origStyle = origTypeface->style(); 711 712 for (int x = 0; x < currentFallbackList->count(); ++x) { 713 const FamilyRecID familyRecID = currentFallbackList->getAt(x); 714 const SkPaintOptionsAndroid& familyOptions = fFontFamilies[familyRecID].fPaintOptions; 715 if ((familyOptions.getFontVariant() & acceptedVariants) != 0) { 716 FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle); 717 currentTypeface = this->getTypefaceForFontRec(matchedFont); 718 lowerBounds = upperBounds; 719 upperBounds += currentTypeface->countGlyphs(); 720 if (glyphID < upperBounds) { 721 break; 722 } 723 } 724 } 725 } 726 727 if (NULL != currentTypeface) { 728 if (lBounds) { 729 *lBounds = lowerBounds; 730 } 731 if (uBounds) { 732 *uBounds = upperBounds; 733 } 734 } 735 return currentTypeface; 736 } 737 738 /////////////////////////////////////////////////////////////////////////////// 739 740 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { 741 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 742 return fontConfig->getFallbackFamilyNameForChar(uni, NULL, name); 743 } 744 745 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name) { 746 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 747 return fontConfig->getFallbackFamilyNameForChar(uni, lang, name); 748 } 749 750 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, 751 const char* fontsdir) { 752 gTestMainConfigFile = mainconf; 753 gTestFallbackConfigFile = fallbackconf; 754 gTestFontFilePrefix = fontsdir; 755 SkASSERT(gTestMainConfigFile); 756 SkASSERT(gTestFallbackConfigFile); 757 SkASSERT(gTestFontFilePrefix); 758 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s", 759 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix)); 760 } 761 762 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, 763 const SkPaintOptionsAndroid& options) { 764 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 765 return fontConfig->nextLogicalTypeface(currFontID, origFontID, options); 766 767 } 768 769 SkTypeface* SkGetTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface, 770 const SkPaintOptionsAndroid& options, 771 int* lowerBounds, int* upperBounds) { 772 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 773 return fontConfig->getTypefaceForGlyphID(glyphID, origTypeface, options, 774 lowerBounds, upperBounds); 775 } 776 777 /////////////////////////////////////////////////////////////////////////////// 778 779 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 780 781 struct HB_UnicodeMapping { 782 // TODO: when the WebView no longer needs harfbuzz_old, remove 783 HB_Script script_old; 784 hb_script_t script; 785 const SkUnichar unicode; 786 }; 787 788 /* 789 * The following scripts are not complex fonts and we do not expect them to be parsed by this table 790 * HB_SCRIPT_COMMON, 791 * HB_SCRIPT_GREEK, 792 * HB_SCRIPT_CYRILLIC, 793 * HB_SCRIPT_HANGUL 794 * HB_SCRIPT_INHERITED 795 */ 796 797 /* Harfbuzz (old) is missing a number of scripts in its table. For these, 798 * we include a value which can never happen. We won't get complex script 799 * shaping in these cases, but the library wouldn't know how to shape 800 * them anyway. */ 801 #define HB_Script_Unknown HB_ScriptCount 802 803 static HB_UnicodeMapping HB_UnicodeMappingArray[] = { 804 {HB_Script_Armenian, HB_SCRIPT_ARMENIAN, 0x0531}, 805 {HB_Script_Hebrew, HB_SCRIPT_HEBREW, 0x0591}, 806 {HB_Script_Arabic, HB_SCRIPT_ARABIC, 0x0600}, 807 {HB_Script_Syriac, HB_SCRIPT_SYRIAC, 0x0710}, 808 {HB_Script_Thaana, HB_SCRIPT_THAANA, 0x0780}, 809 {HB_Script_Nko, HB_SCRIPT_NKO, 0x07C0}, 810 {HB_Script_Devanagari, HB_SCRIPT_DEVANAGARI, 0x0901}, 811 {HB_Script_Bengali, HB_SCRIPT_BENGALI, 0x0981}, 812 {HB_Script_Gurmukhi, HB_SCRIPT_GURMUKHI, 0x0A10}, 813 {HB_Script_Gujarati, HB_SCRIPT_GUJARATI, 0x0A90}, 814 {HB_Script_Oriya, HB_SCRIPT_ORIYA, 0x0B10}, 815 {HB_Script_Tamil, HB_SCRIPT_TAMIL, 0x0B82}, 816 {HB_Script_Telugu, HB_SCRIPT_TELUGU, 0x0C10}, 817 {HB_Script_Kannada, HB_SCRIPT_KANNADA, 0x0C90}, 818 {HB_Script_Malayalam, HB_SCRIPT_MALAYALAM, 0x0D10}, 819 {HB_Script_Sinhala, HB_SCRIPT_SINHALA, 0x0D90}, 820 {HB_Script_Thai, HB_SCRIPT_THAI, 0x0E01}, 821 {HB_Script_Lao, HB_SCRIPT_LAO, 0x0E81}, 822 {HB_Script_Tibetan, HB_SCRIPT_TIBETAN, 0x0F00}, 823 {HB_Script_Myanmar, HB_SCRIPT_MYANMAR, 0x1000}, 824 {HB_Script_Georgian, HB_SCRIPT_GEORGIAN, 0x10A0}, 825 {HB_Script_Unknown, HB_SCRIPT_ETHIOPIC, 0x1200}, 826 {HB_Script_Unknown, HB_SCRIPT_CHEROKEE, 0x13A0}, 827 {HB_Script_Ogham, HB_SCRIPT_OGHAM, 0x1680}, 828 {HB_Script_Runic, HB_SCRIPT_RUNIC, 0x16A0}, 829 {HB_Script_Khmer, HB_SCRIPT_KHMER, 0x1780}, 830 {HB_Script_Unknown, HB_SCRIPT_TAI_LE, 0x1950}, 831 {HB_Script_Unknown, HB_SCRIPT_NEW_TAI_LUE, 0x1980}, 832 {HB_Script_Unknown, HB_SCRIPT_TAI_THAM, 0x1A20}, 833 {HB_Script_Unknown, HB_SCRIPT_CHAM, 0xAA00}, 834 }; 835 836 static hb_script_t getHBScriptFromHBScriptOld(HB_Script script_old) { 837 hb_script_t script = HB_SCRIPT_INVALID; 838 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping); 839 for (int i = 0; i < numSupportedFonts; i++) { 840 if (script_old == HB_UnicodeMappingArray[i].script_old) { 841 script = HB_UnicodeMappingArray[i].script; 842 break; 843 } 844 } 845 return script; 846 } 847 848 // returns 0 for "Not Found" 849 static SkUnichar getUnicodeFromHBScript(hb_script_t script) { 850 SkUnichar unichar = 0; 851 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping); 852 for (int i = 0; i < numSupportedFonts; i++) { 853 if (script == HB_UnicodeMappingArray[i].script) { 854 unichar = HB_UnicodeMappingArray[i].unicode; 855 break; 856 } 857 } 858 return unichar; 859 } 860 861 struct TypefaceLookupStruct { 862 hb_script_t script; 863 SkTypeface::Style style; 864 SkPaintOptionsAndroid::FontVariant fontVariant; 865 SkTypeface* typeface; 866 }; 867 868 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex); // This is the mutex for gTypefaceTable 869 static SkTDArray<TypefaceLookupStruct> gTypefaceTable; // This is protected by gTypefaceTableMutex 870 871 static int typefaceLookupCompare(const TypefaceLookupStruct& first, 872 const TypefaceLookupStruct& second) { 873 if (first.script != second.script) { 874 return (first.script > second.script) ? 1 : -1; 875 } 876 if (first.style != second.style) { 877 return (first.style > second.style) ? 1 : -1; 878 } 879 if (first.fontVariant != second.fontVariant) { 880 return (first.fontVariant > second.fontVariant) ? 1 : -1; 881 } 882 return 0; 883 } 884 885 SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style style, 886 SkPaintOptionsAndroid::FontVariant fontVariant) { 887 SkAutoMutexAcquire ac(gTypefaceTableMutex); 888 889 TypefaceLookupStruct key; 890 key.script = script; 891 key.style = style; 892 key.fontVariant = fontVariant; 893 894 int index = SkTSearch<TypefaceLookupStruct>( 895 (const TypefaceLookupStruct*) gTypefaceTable.begin(), 896 gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct), 897 typefaceLookupCompare); 898 899 SkTypeface* retTypeface = NULL; 900 if (index >= 0) { 901 retTypeface = gTypefaceTable[index].typeface; 902 } 903 else { 904 SkUnichar unichar = getUnicodeFromHBScript(script); 905 if (!unichar) { 906 return NULL; 907 } 908 909 SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface(); 910 retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant); 911 912 // add to the lookup table 913 key.typeface = retTypeface; 914 *gTypefaceTable.insert(~index) = key; 915 } 916 917 // we ref(), the caller is expected to unref when they are done 918 return SkSafeRef(retTypeface); 919 } 920 921 SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style, 922 SkPaintOptionsAndroid::FontVariant fontVariant) { 923 return SkCreateTypefaceForScriptNG(getHBScriptFromHBScriptOld(script), style, fontVariant); 924 } 925 926 #endif 927 928 /////////////////////////////////////////////////////////////////////////////// 929 930 SkFontMgr* SkFontMgr::Factory() { 931 return NULL; 932 } 933