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