| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 Google Inc. | 2 * Copyright 2009 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" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 iden->fID = 10; | 70 iden->fID = 10; |
| 71 iden->fTTCIndex = 2; | 71 iden->fTTCIndex = 2; |
| 72 iden->fString.set("Hello world"); | 72 iden->fString.set("Hello world"); |
| 73 iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant); | 73 iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant); |
| 74 } | 74 } |
| 75 | 75 |
| 76 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0, | 76 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0, |
| 77 int initValue) { | 77 int initValue) { |
| 78 SkFontConfigInterface::FontIdentity iden1; | 78 SkFontConfigInterface::FontIdentity iden1; |
| 79 | 79 |
| 80 size_t size0 = iden0.writeToMemory(NULL); | 80 size_t size0 = iden0.writeToMemory(nullptr); |
| 81 | 81 |
| 82 SkAutoMalloc storage(size0); | 82 SkAutoMalloc storage(size0); |
| 83 memset(storage.get(), initValue, size0); | 83 memset(storage.get(), initValue, size0); |
| 84 | 84 |
| 85 size_t size1 = iden0.writeToMemory(storage.get()); | 85 size_t size1 = iden0.writeToMemory(storage.get()); |
| 86 SkASSERT(size0 == size1); | 86 SkASSERT(size0 == size1); |
| 87 | 87 |
| 88 SkASSERT(iden0 != iden1); | 88 SkASSERT(iden0 != iden1); |
| 89 size_t size2 = iden1.readFromMemory(storage.get(), size1); | 89 size_t size2 = iden1.readFromMemory(storage.get(), size1); |
| 90 SkASSERT(size2 == size1); | 90 SkASSERT(size2 == size1); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 virtual bool matchFamilySet(const char inFamilyName[], | 124 virtual bool matchFamilySet(const char inFamilyName[], |
| 125 SkString* outFamilyName, | 125 SkString* outFamilyName, |
| 126 SkTArray<FontIdentity>*) override; | 126 SkTArray<FontIdentity>*) override; |
| 127 | 127 |
| 128 private: | 128 private: |
| 129 SkMutex mutex_; | 129 SkMutex mutex_; |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase
Mutex* mutex) { | 132 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase
Mutex* mutex) { |
| 133 SkAutoMutexAcquire ac(mutex); | 133 SkAutoMutexAcquire ac(mutex); |
| 134 static SkFontConfigInterfaceDirect* singleton = NULL; | 134 static SkFontConfigInterfaceDirect* singleton = nullptr; |
| 135 if (singleton == NULL) { | 135 if (singleton == nullptr) { |
| 136 singleton = new SkFontConfigInterfaceDirect; | 136 singleton = new SkFontConfigInterfaceDirect; |
| 137 } | 137 } |
| 138 return singleton; | 138 return singleton; |
| 139 } | 139 } |
| 140 | 140 |
| 141 /////////////////////////////////////////////////////////////////////////////// | 141 /////////////////////////////////////////////////////////////////////////////// |
| 142 | 142 |
| 143 // Returns the string from the pattern, or NULL | 143 // Returns the string from the pattern, or nullptr |
| 144 static const char* get_name(FcPattern* pattern, const char field[], | 144 static const char* get_name(FcPattern* pattern, const char field[], |
| 145 int index = 0) { | 145 int index = 0) { |
| 146 const char* name; | 146 const char* name; |
| 147 if (FcPatternGetString(pattern, field, index, | 147 if (FcPatternGetString(pattern, field, index, |
| 148 (FcChar8**)&name) != FcResultMatch) { | 148 (FcChar8**)&name) != FcResultMatch) { |
| 149 name = NULL; | 149 name = nullptr; |
| 150 } | 150 } |
| 151 return name; | 151 return name; |
| 152 } | 152 } |
| 153 | 153 |
| 154 /////////////////////////////////////////////////////////////////////////////// | 154 /////////////////////////////////////////////////////////////////////////////// |
| 155 | 155 |
| 156 namespace { | 156 namespace { |
| 157 | 157 |
| 158 // Equivalence classes, used to match the Liberation and other fonts | 158 // Equivalence classes, used to match the Liberation and other fonts |
| 159 // with their metric-compatible replacements. See the discussion in | 159 // with their metric-compatible replacements. See the discussion in |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 } | 353 } |
| 354 return true; | 354 return true; |
| 355 } | 355 } |
| 356 | 356 |
| 357 // Find matching font from |font_set| for the given font family. | 357 // Find matching font from |font_set| for the given font family. |
| 358 FcPattern* MatchFont(FcFontSet* font_set, | 358 FcPattern* MatchFont(FcFontSet* font_set, |
| 359 const char* post_config_family, | 359 const char* post_config_family, |
| 360 const SkString& family) { | 360 const SkString& family) { |
| 361 // Older versions of fontconfig have a bug where they cannot select | 361 // Older versions of fontconfig have a bug where they cannot select |
| 362 // only scalable fonts so we have to manually filter the results. | 362 // only scalable fonts so we have to manually filter the results. |
| 363 FcPattern* match = NULL; | 363 FcPattern* match = nullptr; |
| 364 for (int i = 0; i < font_set->nfont; ++i) { | 364 for (int i = 0; i < font_set->nfont; ++i) { |
| 365 FcPattern* current = font_set->fonts[i]; | 365 FcPattern* current = font_set->fonts[i]; |
| 366 if (valid_pattern(current)) { | 366 if (valid_pattern(current)) { |
| 367 match = current; | 367 match = current; |
| 368 break; | 368 break; |
| 369 } | 369 } |
| 370 } | 370 } |
| 371 | 371 |
| 372 if (match && !IsFallbackFontAllowed(family)) { | 372 if (match && !IsFallbackFontAllowed(family)) { |
| 373 bool acceptable_substitute = false; | 373 bool acceptable_substitute = false; |
| 374 for (int id = 0; id < 255; ++id) { | 374 for (int id = 0; id < 255; ++id) { |
| 375 const char* post_match_family = get_name(match, FC_FAMILY, id); | 375 const char* post_match_family = get_name(match, FC_FAMILY, id); |
| 376 if (!post_match_family) | 376 if (!post_match_family) |
| 377 break; | 377 break; |
| 378 acceptable_substitute = | 378 acceptable_substitute = |
| 379 (strcasecmp(post_config_family, post_match_family) == 0 || | 379 (strcasecmp(post_config_family, post_match_family) == 0 || |
| 380 // Workaround for Issue 12530: | 380 // Workaround for Issue 12530: |
| 381 // requested family: "Bitstream Vera Sans" | 381 // requested family: "Bitstream Vera Sans" |
| 382 // post_config_family: "Arial" | 382 // post_config_family: "Arial" |
| 383 // post_match_family: "Bitstream Vera Sans" | 383 // post_match_family: "Bitstream Vera Sans" |
| 384 // -> We should treat this case as a good match. | 384 // -> We should treat this case as a good match. |
| 385 strcasecmp(family.c_str(), post_match_family) == 0) || | 385 strcasecmp(family.c_str(), post_match_family) == 0) || |
| 386 IsMetricCompatibleReplacement(family.c_str(), post_match_family); | 386 IsMetricCompatibleReplacement(family.c_str(), post_match_family); |
| 387 if (acceptable_substitute) | 387 if (acceptable_substitute) |
| 388 break; | 388 break; |
| 389 } | 389 } |
| 390 if (!acceptable_substitute) | 390 if (!acceptable_substitute) |
| 391 return NULL; | 391 return nullptr; |
| 392 } | 392 } |
| 393 | 393 |
| 394 return match; | 394 return match; |
| 395 } | 395 } |
| 396 | 396 |
| 397 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. | 397 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. |
| 398 SkTypeface::Style GetFontStyle(FcPattern* font) { | 398 SkTypeface::Style GetFontStyle(FcPattern* font) { |
| 399 int resulting_bold; | 399 int resulting_bold; |
| 400 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) | 400 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) |
| 401 resulting_bold = FC_WEIGHT_NORMAL; | 401 resulting_bold = FC_WEIGHT_NORMAL; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); | 462 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
| 463 } | 463 } |
| 464 FcPatternAddInteger(pattern, FC_WEIGHT, | 464 FcPatternAddInteger(pattern, FC_WEIGHT, |
| 465 (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD | 465 (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD |
| 466 : FC_WEIGHT_NORMAL); | 466 : FC_WEIGHT_NORMAL); |
| 467 FcPatternAddInteger(pattern, FC_SLANT, | 467 FcPatternAddInteger(pattern, FC_SLANT, |
| 468 (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC | 468 (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC |
| 469 : FC_SLANT_ROMAN); | 469 : FC_SLANT_ROMAN); |
| 470 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); | 470 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
| 471 | 471 |
| 472 FcConfigSubstitute(NULL, pattern, FcMatchPattern); | 472 FcConfigSubstitute(nullptr, pattern, FcMatchPattern); |
| 473 FcDefaultSubstitute(pattern); | 473 FcDefaultSubstitute(pattern); |
| 474 | 474 |
| 475 // Font matching: | 475 // Font matching: |
| 476 // CSS often specifies a fallback list of families: | 476 // CSS often specifies a fallback list of families: |
| 477 // font-family: a, b, c, serif; | 477 // font-family: a, b, c, serif; |
| 478 // However, fontconfig will always do its best to find *a* font when asked | 478 // However, fontconfig will always do its best to find *a* font when asked |
| 479 // for something so we need a way to tell if the match which it has found is | 479 // for something so we need a way to tell if the match which it has found is |
| 480 // "good enough" for us. Otherwise, we can return NULL which gets piped up | 480 // "good enough" for us. Otherwise, we can return nullptr which gets piped u
p |
| 481 // and lets WebKit know to try the next CSS family name. However, fontconfig | 481 // and lets WebKit know to try the next CSS family name. However, fontconfig |
| 482 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we | 482 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we |
| 483 // wish to support that. | 483 // wish to support that. |
| 484 // | 484 // |
| 485 // Thus, if a specific family is requested we set @family_requested. Then we | 485 // Thus, if a specific family is requested we set @family_requested. Then we |
| 486 // record two strings: the family name after config processing and the | 486 // record two strings: the family name after config processing and the |
| 487 // family name after resolving. If the two are equal, it's a good match. | 487 // family name after resolving. If the two are equal, it's a good match. |
| 488 // | 488 // |
| 489 // So consider the case where a user has mapped Arial to Helvetica in their | 489 // So consider the case where a user has mapped Arial to Helvetica in their |
| 490 // config. | 490 // config. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 } | 572 } |
| 573 } | 573 } |
| 574 return false; | 574 return false; |
| 575 } | 575 } |
| 576 | 576 |
| 577 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { | 577 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { |
| 578 SkAutoMutexAcquire ac(mutex_); | 578 SkAutoMutexAcquire ac(mutex_); |
| 579 | 579 |
| 580 FcPattern* pat = FcPatternCreate(); | 580 FcPattern* pat = FcPatternCreate(); |
| 581 SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat); | 581 SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat); |
| 582 if (NULL == pat) { | 582 if (nullptr == pat) { |
| 583 return NULL; | 583 return nullptr; |
| 584 } | 584 } |
| 585 | 585 |
| 586 FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0); | 586 FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0); |
| 587 SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os); | 587 SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os); |
| 588 if (NULL == os) { | 588 if (nullptr == os) { |
| 589 return NULL; | 589 return nullptr; |
| 590 } | 590 } |
| 591 | 591 |
| 592 FcFontSet* fs = FcFontList(NULL, pat, os); | 592 FcFontSet* fs = FcFontList(nullptr, pat, os); |
| 593 SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs); | 593 SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs); |
| 594 if (NULL == fs) { | 594 if (nullptr == fs) { |
| 595 return NULL; | 595 return nullptr; |
| 596 } | 596 } |
| 597 | 597 |
| 598 SkTDArray<const char*> names; | 598 SkTDArray<const char*> names; |
| 599 SkTDArray<size_t> sizes; | 599 SkTDArray<size_t> sizes; |
| 600 for (int i = 0; i < fs->nfont; ++i) { | 600 for (int i = 0; i < fs->nfont; ++i) { |
| 601 FcPattern* match = fs->fonts[i]; | 601 FcPattern* match = fs->fonts[i]; |
| 602 const char* famName = get_name(match, FC_FAMILY); | 602 const char* famName = get_name(match, FC_FAMILY); |
| 603 if (famName && !find_name(names, famName)) { | 603 if (famName && !find_name(names, famName)) { |
| 604 *names.append() = famName; | 604 *names.append() = famName; |
| 605 *sizes.append() = strlen(famName) + 1; | 605 *sizes.append() = strlen(famName) + 1; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 623 | 623 |
| 624 SkAutoMutexAcquire ac(mutex_); | 624 SkAutoMutexAcquire ac(mutex_); |
| 625 | 625 |
| 626 FcPattern* pattern = FcPatternCreate(); | 626 FcPattern* pattern = FcPatternCreate(); |
| 627 | 627 |
| 628 if (familyName) { | 628 if (familyName) { |
| 629 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); | 629 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
| 630 } | 630 } |
| 631 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); | 631 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
| 632 | 632 |
| 633 FcConfigSubstitute(NULL, pattern, FcMatchPattern); | 633 FcConfigSubstitute(nullptr, pattern, FcMatchPattern); |
| 634 FcDefaultSubstitute(pattern); | 634 FcDefaultSubstitute(pattern); |
| 635 | 635 |
| 636 // Font matching: | 636 // Font matching: |
| 637 // CSS often specifies a fallback list of families: | 637 // CSS often specifies a fallback list of families: |
| 638 // font-family: a, b, c, serif; | 638 // font-family: a, b, c, serif; |
| 639 // However, fontconfig will always do its best to find *a* font when asked | 639 // However, fontconfig will always do its best to find *a* font when asked |
| 640 // for something so we need a way to tell if the match which it has found is | 640 // for something so we need a way to tell if the match which it has found is |
| 641 // "good enough" for us. Otherwise, we can return NULL which gets piped up | 641 // "good enough" for us. Otherwise, we can return nullptr which gets piped u
p |
| 642 // and lets WebKit know to try the next CSS family name. However, fontconfig | 642 // and lets WebKit know to try the next CSS family name. However, fontconfig |
| 643 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we | 643 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we |
| 644 // wish to support that. | 644 // wish to support that. |
| 645 // | 645 // |
| 646 // Thus, if a specific family is requested we set @family_requested. Then we | 646 // Thus, if a specific family is requested we set @family_requested. Then we |
| 647 // record two strings: the family name after config processing and the | 647 // record two strings: the family name after config processing and the |
| 648 // family name after resolving. If the two are equal, it's a good match. | 648 // family name after resolving. If the two are equal, it's a good match. |
| 649 // | 649 // |
| 650 // So consider the case where a user has mapped Arial to Helvetica in their | 650 // So consider the case where a user has mapped Arial to Helvetica in their |
| 651 // config. | 651 // config. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 } | 713 } |
| 714 return true; | 714 return true; |
| 715 | 715 |
| 716 //////////////////// | 716 //////////////////// |
| 717 | 717 |
| 718 int count; | 718 int count; |
| 719 FcPattern** match = MatchFont(font_set, post_config_family, &count); | 719 FcPattern** match = MatchFont(font_set, post_config_family, &count); |
| 720 if (!match) { | 720 if (!match) { |
| 721 FcPatternDestroy(pattern); | 721 FcPatternDestroy(pattern); |
| 722 FcFontSetDestroy(font_set); | 722 FcFontSetDestroy(font_set); |
| 723 return NULL; | 723 return nullptr; |
| 724 } | 724 } |
| 725 | 725 |
| 726 FcPatternDestroy(pattern); | 726 FcPatternDestroy(pattern); |
| 727 | 727 |
| 728 SkTDArray<FcPattern*> trimmedMatches; | 728 SkTDArray<FcPattern*> trimmedMatches; |
| 729 for (int i = 0; i < count; ++i) { | 729 for (int i = 0; i < count; ++i) { |
| 730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); | 730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); |
| 731 if (!is_lower(*justName)) { | 731 if (!is_lower(*justName)) { |
| 732 *trimmedMatches.append() = match[i]; | 732 *trimmedMatches.append() = match[i]; |
| 733 } | 733 } |
| 734 } | 734 } |
| 735 | 735 |
| 736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); | 736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC
(trimmedMatches.begin(),
trimmedMatches.count()); |
| 737 #endif | 737 #endif |
| 738 return false; | 738 return false; |
| 739 } | 739 } |
| OLD | NEW |