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