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