| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 Google Inc. | 2 * Copyright 2009-2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ | 8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ |
| 9 | 9 |
| 10 #include "SkBuffer.h" | 10 #include "SkBuffer.h" |
| 11 #include "SkDataTable.h" | 11 #include "SkDataTable.h" |
| 12 #include "SkFontConfigInterface.h" | 12 #include "SkFontConfigInterface_direct.h" |
| 13 #include "SkFontStyle.h" | 13 #include "SkFontStyle.h" |
| 14 #include "SkMutex.h" | 14 #include "SkMutex.h" |
| 15 #include "SkStream.h" | 15 #include "SkStream.h" |
| 16 #include "SkString.h" | 16 #include "SkString.h" |
| 17 #include "SkTArray.h" | 17 #include "SkTArray.h" |
| 18 #include "SkTDArray.h" | 18 #include "SkTDArray.h" |
| 19 #include "SkTemplates.h" | 19 #include "SkTemplates.h" |
| 20 #include "SkTypeface.h" | 20 #include "SkTypeface.h" |
| 21 #include "SkTypes.h" | 21 #include "SkTypes.h" |
| 22 | 22 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 SkASSERT(iden0 != iden1); | 100 SkASSERT(iden0 != iden1); |
| 101 | 101 |
| 102 make_iden(&iden1); | 102 make_iden(&iden1); |
| 103 SkASSERT(iden0 == iden1); | 103 SkASSERT(iden0 == iden1); |
| 104 | 104 |
| 105 test_writeToMemory(iden0, 0); | 105 test_writeToMemory(iden0, 0); |
| 106 test_writeToMemory(iden0, 0); | 106 test_writeToMemory(iden0, 0); |
| 107 } | 107 } |
| 108 #endif | 108 #endif |
| 109 | 109 |
| 110 class SkFontConfigInterfaceDirect : public SkFontConfigInterface { | |
| 111 public: | |
| 112 SkFontConfigInterfaceDirect(); | |
| 113 virtual ~SkFontConfigInterfaceDirect(); | |
| 114 | |
| 115 virtual bool matchFamilyName(const char familyName[], | |
| 116 SkTypeface::Style requested, | |
| 117 FontIdentity* outFontIdentifier, | |
| 118 SkString* outFamilyName, | |
| 119 SkTypeface::Style* outStyle) override; | |
| 120 SkStreamAsset* openStream(const FontIdentity&) override; | |
| 121 | |
| 122 // new APIs | |
| 123 SkDataTable* getFamilyNames() override; | |
| 124 virtual bool matchFamilySet(const char inFamilyName[], | |
| 125 SkString* outFamilyName, | |
| 126 SkTArray<FontIdentity>*) override; | |
| 127 | |
| 128 private: | |
| 129 SkMutex mutex_; | |
| 130 }; | |
| 131 | |
| 132 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase
Mutex* mutex) { | |
| 133 SkAutoMutexAcquire ac(mutex); | |
| 134 static SkFontConfigInterfaceDirect* singleton = nullptr; | |
| 135 if (singleton == nullptr) { | |
| 136 singleton = new SkFontConfigInterfaceDirect; | |
| 137 } | |
| 138 return singleton; | |
| 139 } | |
| 140 | |
| 141 /////////////////////////////////////////////////////////////////////////////// | 110 /////////////////////////////////////////////////////////////////////////////// |
| 142 | 111 |
| 143 // Returns the string from the pattern, or nullptr | 112 // Returns the string from the pattern, or nullptr |
| 144 static const char* get_name(FcPattern* pattern, const char field[], | 113 static const char* get_name(FcPattern* pattern, const char field[], |
| 145 int index = 0) { | 114 int index = 0) { |
| 146 const char* name; | 115 const char* name; |
| 147 if (FcPatternGetString(pattern, field, index, | 116 if (FcPatternGetString(pattern, field, index, |
| 148 (FcChar8**)&name) != FcResultMatch) { | 117 (FcChar8**)&name) != FcResultMatch) { |
| 149 name = nullptr; | 118 name = nullptr; |
| 150 } | 119 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 // basic font names like "Sans", "Serif" or "Monospace". This function | 296 // basic font names like "Sans", "Serif" or "Monospace". This function |
| 328 // tells you whether a given request is for such a fallback. | 297 // tells you whether a given request is for such a fallback. |
| 329 bool IsFallbackFontAllowed(const SkString& family) { | 298 bool IsFallbackFontAllowed(const SkString& family) { |
| 330 const char* family_cstr = family.c_str(); | 299 const char* family_cstr = family.c_str(); |
| 331 return family.isEmpty() || | 300 return family.isEmpty() || |
| 332 strcasecmp(family_cstr, "sans") == 0 || | 301 strcasecmp(family_cstr, "sans") == 0 || |
| 333 strcasecmp(family_cstr, "serif") == 0 || | 302 strcasecmp(family_cstr, "serif") == 0 || |
| 334 strcasecmp(family_cstr, "monospace") == 0; | 303 strcasecmp(family_cstr, "monospace") == 0; |
| 335 } | 304 } |
| 336 | 305 |
| 337 static bool valid_pattern(FcPattern* pattern) { | 306 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. |
| 307 SkTypeface::Style GetFontStyle(FcPattern* font) { |
| 308 int resulting_bold; |
| 309 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) |
| 310 resulting_bold = FC_WEIGHT_NORMAL; |
| 311 |
| 312 int resulting_italic; |
| 313 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) |
| 314 resulting_italic = FC_SLANT_ROMAN; |
| 315 |
| 316 // If we ask for an italic font, fontconfig might take a roman font and set |
| 317 // the undocumented property FC_MATRIX to a skew matrix. It'll then say |
| 318 // that the font is italic or oblique. So, if we see a matrix, we don't |
| 319 // believe that it's italic. |
| 320 FcValue matrix; |
| 321 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; |
| 322 |
| 323 // If we ask for an italic font, fontconfig might take a roman font and set |
| 324 // FC_EMBOLDEN. |
| 325 FcValue embolden; |
| 326 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) ==
0; |
| 327 |
| 328 int styleBits = 0; |
| 329 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { |
| 330 styleBits |= SkTypeface::kBold; |
| 331 } |
| 332 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { |
| 333 styleBits |= SkTypeface::kItalic; |
| 334 } |
| 335 |
| 336 return (SkTypeface::Style)styleBits; |
| 337 } |
| 338 |
| 339 } // anonymous namespace |
| 340 |
| 341 /////////////////////////////////////////////////////////////////////////////// |
| 342 |
| 343 #define kMaxFontFamilyLength 2048 |
| 344 |
| 345 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { |
| 346 SkAutoMutexAcquire ac(mutex_); |
| 347 |
| 348 FcInit(); |
| 349 |
| 350 SkDEBUGCODE(fontconfiginterface_unittest();) |
| 351 } |
| 352 |
| 353 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { |
| 354 } |
| 355 |
| 356 bool SkFontConfigInterfaceDirect::isAccessible(const char* filename) { |
| 357 if (access(filename, R_OK) != 0) { |
| 358 return false; |
| 359 } |
| 360 return true; |
| 361 } |
| 362 |
| 363 bool SkFontConfigInterfaceDirect::isValidPattern(FcPattern* pattern) { |
| 338 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS | 364 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS |
| 339 FcBool is_scalable; | 365 FcBool is_scalable; |
| 340 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch | 366 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch |
| 341 || !is_scalable) { | 367 || !is_scalable) { |
| 342 return false; | 368 return false; |
| 343 } | 369 } |
| 344 #endif | 370 #endif |
| 345 | 371 |
| 346 // fontconfig can also return fonts which are unreadable | 372 // fontconfig can also return fonts which are unreadable |
| 347 const char* c_filename = get_name(pattern, FC_FILE); | 373 const char* c_filename = get_name(pattern, FC_FILE); |
| 348 if (!c_filename) { | 374 if (!c_filename) { |
| 349 return false; | 375 return false; |
| 350 } | 376 } |
| 351 if (access(c_filename, R_OK) != 0) { | 377 return this->isAccessible(c_filename); |
| 352 return false; | |
| 353 } | |
| 354 return true; | |
| 355 } | 378 } |
| 356 | 379 |
| 357 // Find matching font from |font_set| for the given font family. | 380 // Find matching font from |font_set| for the given font family. |
| 358 FcPattern* MatchFont(FcFontSet* font_set, | 381 FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set, |
| 359 const char* post_config_family, | 382 const char* post_config_family
, |
| 360 const SkString& family) { | 383 const SkString& family) { |
| 361 // Older versions of fontconfig have a bug where they cannot select | 384 // Older versions of fontconfig have a bug where they cannot select |
| 362 // only scalable fonts so we have to manually filter the results. | 385 // only scalable fonts so we have to manually filter the results. |
| 363 FcPattern* match = nullptr; | 386 FcPattern* match = nullptr; |
| 364 for (int i = 0; i < font_set->nfont; ++i) { | 387 for (int i = 0; i < font_set->nfont; ++i) { |
| 365 FcPattern* current = font_set->fonts[i]; | 388 FcPattern* current = font_set->fonts[i]; |
| 366 if (valid_pattern(current)) { | 389 if (this->isValidPattern(current)) { |
| 367 match = current; | 390 match = current; |
| 368 break; | 391 break; |
| 369 } | 392 } |
| 370 } | 393 } |
| 371 | 394 |
| 372 if (match && !IsFallbackFontAllowed(family)) { | 395 if (match && !IsFallbackFontAllowed(family)) { |
| 373 bool acceptable_substitute = false; | 396 bool acceptable_substitute = false; |
| 374 for (int id = 0; id < 255; ++id) { | 397 for (int id = 0; id < 255; ++id) { |
| 375 const char* post_match_family = get_name(match, FC_FAMILY, id); | 398 const char* post_match_family = get_name(match, FC_FAMILY, id); |
| 376 if (!post_match_family) | 399 if (!post_match_family) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 387 if (acceptable_substitute) | 410 if (acceptable_substitute) |
| 388 break; | 411 break; |
| 389 } | 412 } |
| 390 if (!acceptable_substitute) | 413 if (!acceptable_substitute) |
| 391 return nullptr; | 414 return nullptr; |
| 392 } | 415 } |
| 393 | 416 |
| 394 return match; | 417 return match; |
| 395 } | 418 } |
| 396 | 419 |
| 397 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. | |
| 398 SkTypeface::Style GetFontStyle(FcPattern* font) { | |
| 399 int resulting_bold; | |
| 400 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) | |
| 401 resulting_bold = FC_WEIGHT_NORMAL; | |
| 402 | |
| 403 int resulting_italic; | |
| 404 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) | |
| 405 resulting_italic = FC_SLANT_ROMAN; | |
| 406 | |
| 407 // If we ask for an italic font, fontconfig might take a roman font and set | |
| 408 // the undocumented property FC_MATRIX to a skew matrix. It'll then say | |
| 409 // that the font is italic or oblique. So, if we see a matrix, we don't | |
| 410 // believe that it's italic. | |
| 411 FcValue matrix; | |
| 412 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; | |
| 413 | |
| 414 // If we ask for an italic font, fontconfig might take a roman font and set | |
| 415 // FC_EMBOLDEN. | |
| 416 FcValue embolden; | |
| 417 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) ==
0; | |
| 418 | |
| 419 int styleBits = 0; | |
| 420 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { | |
| 421 styleBits |= SkTypeface::kBold; | |
| 422 } | |
| 423 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { | |
| 424 styleBits |= SkTypeface::kItalic; | |
| 425 } | |
| 426 | |
| 427 return (SkTypeface::Style)styleBits; | |
| 428 } | |
| 429 | |
| 430 } // anonymous namespace | |
| 431 | |
| 432 /////////////////////////////////////////////////////////////////////////////// | |
| 433 | |
| 434 #define kMaxFontFamilyLength 2048 | |
| 435 | |
| 436 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { | |
| 437 SkAutoMutexAcquire ac(mutex_); | |
| 438 | |
| 439 FcInit(); | |
| 440 | |
| 441 SkDEBUGCODE(fontconfiginterface_unittest();) | |
| 442 } | |
| 443 | |
| 444 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { | |
| 445 } | |
| 446 | |
| 447 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], | 420 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
| 448 SkTypeface::Style style, | 421 SkTypeface::Style style, |
| 449 FontIdentity* outIdentity, | 422 FontIdentity* outIdentity, |
| 450 SkString* outFamilyName, | 423 SkString* outFamilyName, |
| 451 SkTypeface::Style* outStyle) { | 424 SkTypeface::Style* outStyle) { |
| 452 SkString familyStr(familyName ? familyName : ""); | 425 SkString familyStr(familyName ? familyName : ""); |
| 453 if (familyStr.size() > kMaxFontFamilyLength) { | 426 if (familyStr.size() > kMaxFontFamilyLength) { |
| 454 return false; | 427 return false; |
| 455 } | 428 } |
| 456 | 429 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 post_config_family = ""; | 480 post_config_family = ""; |
| 508 } | 481 } |
| 509 | 482 |
| 510 FcResult result; | 483 FcResult result; |
| 511 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); | 484 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
| 512 if (!font_set) { | 485 if (!font_set) { |
| 513 FcPatternDestroy(pattern); | 486 FcPatternDestroy(pattern); |
| 514 return false; | 487 return false; |
| 515 } | 488 } |
| 516 | 489 |
| 517 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); | 490 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr); |
| 518 if (!match) { | 491 if (!match) { |
| 519 FcPatternDestroy(pattern); | 492 FcPatternDestroy(pattern); |
| 520 FcFontSetDestroy(font_set); | 493 FcFontSetDestroy(font_set); |
| 521 return false; | 494 return false; |
| 522 } | 495 } |
| 523 | 496 |
| 524 FcPatternDestroy(pattern); | 497 FcPatternDestroy(pattern); |
| 525 | 498 |
| 526 // From here out we just extract our results from 'match' | 499 // From here out we just extract our results from 'match' |
| 527 | 500 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 637 |
| 665 const char* post_config_family = get_name(pattern, FC_FAMILY); | 638 const char* post_config_family = get_name(pattern, FC_FAMILY); |
| 666 | 639 |
| 667 FcResult result; | 640 FcResult result; |
| 668 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); | 641 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
| 669 if (!font_set) { | 642 if (!font_set) { |
| 670 FcPatternDestroy(pattern); | 643 FcPatternDestroy(pattern); |
| 671 return false; | 644 return false; |
| 672 } | 645 } |
| 673 | 646 |
| 674 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); | 647 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr); |
| 675 if (!match) { | 648 if (!match) { |
| 676 FcPatternDestroy(pattern); | 649 FcPatternDestroy(pattern); |
| 677 FcFontSetDestroy(font_set); | 650 FcFontSetDestroy(font_set); |
| 678 return false; | 651 return false; |
| 679 } | 652 } |
| 680 | 653 |
| 681 FcPatternDestroy(pattern); | 654 FcPatternDestroy(pattern); |
| 682 | 655 |
| 683 // From here out we just extract our results from 'match' | 656 // From here out we just extract our results from 'match' |
| 684 | 657 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 709 outFamilyName->set((const char*)post_config_family); | 682 outFamilyName->set((const char*)post_config_family); |
| 710 } | 683 } |
| 711 if (outStyle) { | 684 if (outStyle) { |
| 712 *outStyle = GetFontStyle(match); | 685 *outStyle = GetFontStyle(match); |
| 713 } | 686 } |
| 714 return true; | 687 return true; |
| 715 | 688 |
| 716 //////////////////// | 689 //////////////////// |
| 717 | 690 |
| 718 int count; | 691 int count; |
| 719 FcPattern** match = MatchFont(font_set, post_config_family, &count); | 692 FcPattern** match = this->MatchFont(font_set, post_config_family, &count
); |
| 720 if (!match) { | 693 if (!match) { |
| 721 FcPatternDestroy(pattern); | 694 FcPatternDestroy(pattern); |
| 722 FcFontSetDestroy(font_set); | 695 FcFontSetDestroy(font_set); |
| 723 return nullptr; | 696 return nullptr; |
| 724 } | 697 } |
| 725 | 698 |
| 726 FcPatternDestroy(pattern); | 699 FcPatternDestroy(pattern); |
| 727 | 700 |
| 728 SkTDArray<FcPattern*> trimmedMatches; | 701 SkTDArray<FcPattern*> trimmedMatches; |
| 729 for (int i = 0; i < count; ++i) { | 702 for (int i = 0; i < count; ++i) { |
| 730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); | 703 const char* justName = find_just_name(get_name(match[i], FC_FILE)); |
| 731 if (!is_lower(*justName)) { | 704 if (!is_lower(*justName)) { |
| 732 *trimmedMatches.append() = match[i]; | 705 *trimmedMatches.append() = match[i]; |
| 733 } | 706 } |
| 734 } | 707 } |
| 735 | 708 |
| 736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); | 709 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); |
| 737 #endif | 710 #endif |
| 738 return false; | 711 return false; |
| 739 } | 712 } |
| OLD | NEW |