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