1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkFontConfigParser_android.h" 9 #include "SkFontDescriptor.h" 10 #include "SkFontHost_FreeType_common.h" 11 #include "SkFontMgr.h" 12 #include "SkFontStyle.h" 13 #include "SkStream.h" 14 #include "SkTDArray.h" 15 #include "SkTSearch.h" 16 #include "SkTypeface.h" 17 #include "SkTypeface_android.h" 18 #include "SkTypefaceCache.h" 19 20 #include <limits> 21 #include <stdlib.h> 22 23 #ifndef SK_FONT_FILE_PREFIX 24 # define SK_FONT_FILE_PREFIX "/fonts/" 25 #endif 26 27 #ifndef SK_DEBUG_FONTS 28 #define SK_DEBUG_FONTS 0 29 #endif 30 31 #if SK_DEBUG_FONTS 32 # define DEBUG_FONT(args) SkDebugf args 33 #else 34 # define DEBUG_FONT(args) 35 #endif 36 37 // For test only. 38 static const char* gTestMainConfigFile = NULL; 39 static const char* gTestFallbackConfigFile = NULL; 40 static const char* gTestFontFilePrefix = NULL; 41 42 class SkTypeface_Android : public SkTypeface_FreeType { 43 public: 44 SkTypeface_Android(int index, 45 Style style, 46 bool isFixedPitch, 47 const SkString familyName) 48 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) 49 , fIndex(index) 50 , fFamilyName(familyName) { } 51 52 protected: 53 virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE { 54 *familyName = fFamilyName; 55 } 56 57 int fIndex; 58 SkString fFamilyName; 59 60 private: 61 typedef SkTypeface_FreeType INHERITED; 62 }; 63 64 class SkTypeface_AndroidSystem : public SkTypeface_Android { 65 public: 66 SkTypeface_AndroidSystem(const SkString pathName, 67 int index, 68 Style style, 69 bool isFixedPitch, 70 const SkString familyName, 71 const SkLanguage& lang, 72 FontVariant variantStyle) 73 : INHERITED(index, style, isFixedPitch, familyName) 74 , fPathName(pathName) 75 , fLang(lang) 76 , fVariantStyle(variantStyle) { } 77 78 virtual void onGetFontDescriptor(SkFontDescriptor* desc, 79 bool* serialize) const SK_OVERRIDE { 80 SkASSERT(desc); 81 SkASSERT(serialize); 82 desc->setFamilyName(fFamilyName.c_str()); 83 desc->setFontFileName(fPathName.c_str()); 84 desc->setFontIndex(fIndex); 85 *serialize = false; 86 } 87 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 88 *ttcIndex = fIndex; 89 return SkStream::NewFromFile(fPathName.c_str()); 90 } 91 92 const SkString fPathName; 93 const SkLanguage fLang; 94 const FontVariant fVariantStyle; 95 96 typedef SkTypeface_Android INHERITED; 97 }; 98 99 class SkTypeface_AndroidStream : public SkTypeface_Android { 100 public: 101 SkTypeface_AndroidStream(SkStream* stream, 102 int index, 103 Style style, 104 bool isFixedPitch, 105 const SkString familyName) 106 : INHERITED(index, style, isFixedPitch, familyName) 107 , fStream(SkRef(stream)) { } 108 109 virtual void onGetFontDescriptor(SkFontDescriptor* desc, 110 bool* serialize) const SK_OVERRIDE { 111 SkASSERT(desc); 112 SkASSERT(serialize); 113 desc->setFamilyName(fFamilyName.c_str()); 114 desc->setFontFileName(NULL); 115 *serialize = true; 116 } 117 118 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 119 *ttcIndex = fIndex; 120 return fStream->duplicate(); 121 } 122 123 private: 124 SkAutoTUnref<SkStream> fStream; 125 126 typedef SkTypeface_Android INHERITED; 127 }; 128 129 void get_path_for_sys_fonts(const char* basePath, const SkString& name, SkString* full) { 130 if (basePath) { 131 full->set(basePath); 132 } else { 133 full->set(getenv("ANDROID_ROOT")); 134 full->append(SK_FONT_FILE_PREFIX); 135 } 136 full->append(name); 137 } 138 139 class SkFontStyleSet_Android : public SkFontStyleSet { 140 public: 141 explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath) { 142 const SkString* cannonicalFamilyName = NULL; 143 if (family.fNames.count() > 0) { 144 cannonicalFamilyName = &family.fNames[0]; 145 } 146 // TODO? make this lazy 147 for (int i = 0; i < family.fFonts.count(); ++i) { 148 const FontFileInfo& fontFile = family.fFonts[i]; 149 150 SkString pathName; 151 get_path_for_sys_fonts(basePath, fontFile.fFileName, &pathName); 152 153 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str())); 154 if (!stream.get()) { 155 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str())); 156 continue; 157 } 158 159 const int ttcIndex = fontFile.fIndex; 160 SkString familyName; 161 SkTypeface::Style style; 162 bool isFixedWidth; 163 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, 164 &familyName, &style, &isFixedWidth)) { 165 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str())); 166 continue; 167 } 168 169 const SkLanguage& lang = family.fLanguage; 170 uint32_t variant = family.fVariant; 171 if (kDefault_FontVariant == variant) { 172 variant = kCompact_FontVariant | kElegant_FontVariant; 173 } 174 175 // The first specified family name overrides the family name found in the font. 176 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return 177 // all of the specified family names in addition to the names found in the font. 178 if (cannonicalFamilyName != NULL) { 179 familyName = *cannonicalFamilyName; 180 } 181 182 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, 183 (pathName, ttcIndex, 184 style, isFixedWidth, familyName, 185 lang, variant))); 186 } 187 } 188 189 virtual int count() SK_OVERRIDE { 190 return fStyles.count(); 191 } 192 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE { 193 if (index < 0 || fStyles.count() <= index) { 194 return; 195 } 196 if (style) { 197 *style = this->style(index); 198 } 199 if (name) { 200 name->reset(); 201 } 202 } 203 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE { 204 if (index < 0 || fStyles.count() <= index) { 205 return NULL; 206 } 207 return SkRef(fStyles[index].get()); 208 } 209 210 /** Find the typeface in this style set that most closely matches the given pattern. 211 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); 212 * this simpler version using match_score() passes all our tests. 213 */ 214 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 215 if (0 == fStyles.count()) { 216 return NULL; 217 } 218 SkTypeface_AndroidSystem* closest = fStyles[0]; 219 int minScore = std::numeric_limits<int>::max(); 220 for (int i = 0; i < fStyles.count(); ++i) { 221 SkFontStyle style = this->style(i); 222 int score = match_score(pattern, style); 223 if (score < minScore) { 224 closest = fStyles[i]; 225 minScore = score; 226 } 227 } 228 return SkRef(closest); 229 } 230 231 private: 232 SkFontStyle style(int index) { 233 return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width, 234 this->slant(index)); 235 } 236 SkFontStyle::Weight weight(int index) { 237 if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight; 238 return SkFontStyle::kNormal_Weight; 239 } 240 SkFontStyle::Slant slant(int index) { 241 if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant; 242 return SkFontStyle::kUpright_Slant; 243 } 244 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 245 int score = 0; 246 score += abs((pattern.width() - candidate.width()) * 100); 247 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000); 248 score += abs(pattern.weight() - candidate.weight()); 249 return score; 250 } 251 252 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles; 253 254 friend struct NameToFamily; 255 friend class SkFontMgr_Android; 256 257 typedef SkFontStyleSet INHERITED; 258 }; 259 260 /** On Android a single family can have many names, but our API assumes unique names. 261 * Map names to the back end so that all names for a given family refer to the same 262 * (non-replicated) set of typefaces. 263 * SkTDict<> doesn't let us do index-based lookup, so we write our own mapping. 264 */ 265 struct NameToFamily { 266 SkString name; 267 SkFontStyleSet_Android* styleSet; 268 }; 269 270 class SkFontMgr_Android : public SkFontMgr { 271 public: 272 SkFontMgr_Android() { 273 SkTDArray<FontFamily*> fontFamilies; 274 SkFontConfigParser::GetFontFamilies(fontFamilies); 275 this->buildNameToFamilyMap(fontFamilies, NULL); 276 this->findDefaultFont(); 277 } 278 SkFontMgr_Android(const char* mainConfigFile, const char* fallbackConfigFile, 279 const char* basePath) 280 { 281 SkTDArray<FontFamily*> fontFamilies; 282 SkFontConfigParser::GetTestFontFamilies(fontFamilies, mainConfigFile, fallbackConfigFile); 283 this->buildNameToFamilyMap(fontFamilies, basePath); 284 this->findDefaultFont(); 285 } 286 287 protected: 288 /** Returns not how many families we have, but how many unique names 289 * exist among the families. 290 */ 291 virtual int onCountFamilies() const SK_OVERRIDE { 292 return fNameToFamilyMap.count(); 293 } 294 295 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { 296 if (index < 0 || fNameToFamilyMap.count() <= index) { 297 familyName->reset(); 298 return; 299 } 300 familyName->set(fNameToFamilyMap[index].name); 301 } 302 303 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { 304 if (index < 0 || fNameToFamilyMap.count() <= index) { 305 return NULL; 306 } 307 return SkRef(fNameToFamilyMap[index].styleSet); 308 } 309 310 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE { 311 if (!familyName) { 312 return NULL; 313 } 314 SkAutoAsciiToLC tolc(familyName); 315 for (int i = 0; i < fNameToFamilyMap.count(); ++i) { 316 if (fNameToFamilyMap[i].name.equals(tolc.lc())) { 317 return SkRef(fNameToFamilyMap[i].styleSet); 318 } 319 } 320 // TODO: eventually we should not need to name fallback families. 321 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) { 322 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) { 323 return SkRef(fFallbackNameToFamilyMap[i].styleSet); 324 } 325 } 326 return NULL; 327 } 328 329 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 330 const SkFontStyle& style) const SK_OVERRIDE { 331 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 332 return sset->matchStyle(style); 333 } 334 335 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, 336 const SkFontStyle& style) const SK_OVERRIDE { 337 for (int i = 0; i < fFontStyleSets.count(); ++i) { 338 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) { 339 if (fFontStyleSets[i]->fStyles[j] == typeface) { 340 return fFontStyleSets[i]->matchStyle(style); 341 } 342 } 343 } 344 return NULL; 345 } 346 347 static SkTypeface_AndroidSystem* find_family_style_character( 348 const SkTDArray<NameToFamily>& fallbackNameToFamilyMap, 349 const SkFontStyle& style, bool elegant, 350 const SkString& langTag, SkUnichar character) 351 { 352 for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) { 353 SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet; 354 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style)); 355 356 if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) { 357 continue; 358 } 359 360 if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) { 361 continue; 362 } 363 364 SkPaint paint; 365 paint.setTypeface(face); 366 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 367 368 uint16_t glyphID; 369 paint.textToGlyphs(&character, sizeof(character), &glyphID); 370 if (glyphID != 0) { 371 return face.detach(); 372 } 373 } 374 return NULL; 375 } 376 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER 377 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], 378 const SkFontStyle& style, 379 const char* bcp47[], 380 int bcp47Count, 381 SkUnichar character) const SK_OVERRIDE 382 { 383 #else 384 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], 385 const SkFontStyle& style, 386 const char bcp47_val[], 387 SkUnichar character) const SK_OVERRIDE 388 { 389 const char** bcp47 = &bcp47_val; 390 int bcp47Count = bcp47_val ? 1 : 0; 391 #endif 392 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'. 393 // The variant 'default' means 'compact and elegant'. 394 // As a result, it is not possible to know the variant context from the font alone. 395 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request. 396 397 // The first time match anything elegant, second time anything not elegant. 398 for (int elegant = 2; elegant --> 0;) { 399 for (int bcp47Index = bcp47Count; bcp47Index --> 0;) { 400 SkLanguage lang(bcp47[bcp47Index]); 401 while (!lang.getTag().isEmpty()) { 402 SkTypeface_AndroidSystem* matchingTypeface = 403 find_family_style_character(fFallbackNameToFamilyMap, 404 style, SkToBool(elegant), 405 lang.getTag(), character); 406 if (matchingTypeface) { 407 return matchingTypeface; 408 } 409 410 lang = lang.getParent(); 411 } 412 } 413 SkTypeface_AndroidSystem* matchingTypeface = 414 find_family_style_character(fFallbackNameToFamilyMap, 415 style, SkToBool(elegant), 416 SkString(), character); 417 if (matchingTypeface) { 418 return matchingTypeface; 419 } 420 } 421 return NULL; 422 } 423 424 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE { 425 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); 426 return this->createFromStream(stream, ttcIndex); 427 } 428 429 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 430 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 431 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; 432 } 433 434 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE { 435 bool isFixedPitch; 436 SkTypeface::Style style; 437 SkString name; 438 if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) { 439 return NULL; 440 } 441 return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex, 442 style, isFixedPitch, name)); 443 } 444 445 446 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 447 unsigned styleBits) const SK_OVERRIDE { 448 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; 449 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold 450 ? SkFontStyle::kBold_Weight 451 : SkFontStyle::kNormal_Weight, 452 SkFontStyle::kNormal_Width, 453 oldStyle & SkTypeface::kItalic 454 ? SkFontStyle::kItalic_Slant 455 : SkFontStyle::kUpright_Slant); 456 457 if (familyName) { 458 // On Android, we must return NULL when we can't find the requested 459 // named typeface so that the system/app can provide their own recovery 460 // mechanism. On other platforms we'd provide a typeface from the 461 // default family instead. 462 return this->onMatchFamilyStyle(familyName, style); 463 } 464 return fDefaultFamily->matchStyle(style); 465 } 466 467 468 private: 469 470 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets; 471 SkFontStyleSet* fDefaultFamily; 472 SkTypeface* fDefaultTypeface; 473 474 SkTDArray<NameToFamily> fNameToFamilyMap; 475 SkTDArray<NameToFamily> fFallbackNameToFamilyMap; 476 477 void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const char* basePath) { 478 for (int i = 0; i < families.count(); i++) { 479 FontFamily& family = *families[i]; 480 481 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap; 482 if (family.fIsFallbackFont) { 483 nameToFamily = &fFallbackNameToFamilyMap; 484 485 if (0 == family.fNames.count()) { 486 SkString& fallbackName = family.fNames.push_back(); 487 fallbackName.printf("%.2x##fallback", i); 488 } 489 } 490 491 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath)); 492 if (0 == newSet->count()) { 493 SkDELETE(newSet); 494 continue; 495 } 496 fFontStyleSets.push_back().reset(newSet); 497 498 for (int j = 0; j < family.fNames.count(); j++) { 499 NameToFamily* nextEntry = nameToFamily->append(); 500 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j])); 501 nextEntry->styleSet = newSet; 502 } 503 } 504 } 505 506 void findDefaultFont() { 507 SkASSERT(!fFontStyleSets.empty()); 508 509 static const char* gDefaultNames[] = { "sans-serif" }; 510 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 511 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); 512 if (NULL == set) { 513 continue; 514 } 515 SkTypeface* tf = set->matchStyle(SkFontStyle()); 516 if (NULL == tf) { 517 continue; 518 } 519 fDefaultFamily = set; 520 fDefaultTypeface = tf; 521 break; 522 } 523 if (NULL == fDefaultTypeface) { 524 fDefaultFamily = fFontStyleSets[0]; 525 fDefaultTypeface = fDefaultFamily->createTypeface(0); 526 } 527 SkASSERT(fDefaultFamily); 528 SkASSERT(fDefaultTypeface); 529 } 530 531 typedef SkFontMgr INHERITED; 532 }; 533 534 /////////////////////////////////////////////////////////////////////////////// 535 536 SkFontMgr* SkFontMgr::Factory() { 537 // The call to SkGetTestFontConfiguration is so that Chromium can override the environment. 538 // TODO: these globals need to be removed, in favor of a constructor / separate Factory 539 // which can be used instead. 540 const char* mainConfigFile; 541 const char* fallbackConfigFile; 542 const char* basePath; 543 SkGetTestFontConfiguration(&mainConfigFile, &fallbackConfigFile, &basePath); 544 if (mainConfigFile) { 545 return SkNEW_ARGS(SkFontMgr_Android, (mainConfigFile, fallbackConfigFile, basePath)); 546 } 547 548 return SkNEW(SkFontMgr_Android); 549 } 550 551 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, 552 const char* fontsdir) { 553 gTestMainConfigFile = mainconf; 554 gTestFallbackConfigFile = fallbackconf; 555 gTestFontFilePrefix = fontsdir; 556 SkASSERT(gTestMainConfigFile); 557 SkASSERT(gTestFallbackConfigFile); 558 SkASSERT(gTestFontFilePrefix); 559 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s", 560 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix)); 561 } 562 563 void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf, 564 const char** fontsdir) { 565 *mainconf = gTestMainConfigFile; 566 *fallbackconf = gTestFallbackConfigFile; 567 *fontsdir = gTestFontFilePrefix; 568 } 569