diff --git a/third_party/txt/src/txt/platform_mac.mm b/third_party/txt/src/txt/platform_mac.mm index 3a747d3304823..6cec1dcf68838 100644 --- a/third_party/txt/src/txt/platform_mac.mm +++ b/third_party/txt/src/txt/platform_mac.mm @@ -20,15 +20,15 @@ // Apple system font larger than size 29 returns SFProDisplay typeface. static const CGFloat kSFProDisplayBreakPoint = 29; -// Apple system font smaller than size 16 returns SFProText typeface. -static const CGFloat kSFProTextBreakPoint = 16; // Font name represents the "SF Pro Display" system font on Apple platforms. static const std::string kSFProDisplayName = "CupertinoSystemDisplay"; -// Font name represents the "SF Pro Text" system font on Apple platforms. -static const std::string kSFProTextName = "CupertinoSystemText"; +// Font weight representing Regular +float kNormalWeightValue = 400; namespace txt { +const FourCharCode kWeightTag = 'wght'; + std::vector GetDefaultFontFamilies() { if (fml::IsPlatformVersionAtLeast(9)) { return {[FONT_CLASS systemFontOfSize:14].familyName.UTF8String}; @@ -42,13 +42,52 @@ return mgr; } +CTFontRef MatchSystemUIFont(float desired_weight, float size) { + CTFontRef ct_font( + CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr)); + + if (desired_weight == kNormalWeightValue) { + return ct_font; + } + + CFMutableDictionaryRef variations(CFDictionaryCreateMutable( + kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + auto add_axis_to_variations = [&variations](const FourCharCode tag, + float desired_value, + float normal_value) { + if (desired_value != normal_value) { + CFNumberRef tag_number( + CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &tag)); + CFNumberRef value_number(CFNumberCreate( + kCFAllocatorDefault, kCFNumberFloatType, &desired_value)); + CFDictionarySetValue(variations, tag_number, value_number); + } + }; + add_axis_to_variations(kWeightTag, desired_weight, kNormalWeightValue); + + CFMutableDictionaryRef attributes(CFDictionaryCreateMutable( + kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + CFDictionarySetValue(attributes, kCTFontVariationAttribute, variations); + + CTFontDescriptorRef var_font_desc( + CTFontDescriptorCreateWithAttributes(attributes)); + + return CTFontCreateCopyWithAttributes(ct_font, size, nullptr, var_font_desc); +} + void RegisterSystemFonts(const DynamicFontManager& dynamic_font_manager) { // iOS loads different system fonts when size is greater than 28 or lower // than 17. The "familyName" property returned from CoreText stays the same // despite the typeface is different. // - // Below code manually loads and registers them as two different fonts - // so Flutter app can access them on macOS and iOS. + // Below code manually loads and registers the larger font. The existing + // fallback correctly loads the smaller font. The code also iterates through + // the possible font weights from 100 - 900 to correctly load all of them, as + // a CTFont object for the large system font does not include all of the font + // weights by default. // // Darwin system fonts from 17 to 28 also have dynamic spacing based on sizes. // These two fonts do not match the spacings when sizes are from 17 to 28. @@ -56,20 +95,23 @@ void RegisterSystemFonts(const DynamicFontManager& dynamic_font_manager) { // // See https://www.wwdcnotes.com/notes/wwdc20/10175/ for Apple's document on // this topic. - sk_sp large_system_font = SkMakeTypefaceFromCTFont( - (CTFontRef)CFAutorelease(CTFontCreateUIFontForLanguage( - kCTFontUIFontSystem, kSFProDisplayBreakPoint, NULL))); - if (large_system_font) { - dynamic_font_manager.font_provider().RegisterTypeface(large_system_font, - kSFProDisplayName); - } - sk_sp regular_system_font = SkMakeTypefaceFromCTFont( - (CTFontRef)CFAutorelease(CTFontCreateUIFontForLanguage( - kCTFontUIFontSystem, kSFProTextBreakPoint, NULL))); - if (regular_system_font) { - dynamic_font_manager.font_provider().RegisterTypeface(regular_system_font, - kSFProTextName); + auto register_weighted_font = [&dynamic_font_manager](const int weight) { + sk_sp large_system_font_weighted = + SkMakeTypefaceFromCTFont((CTFontRef)CFAutorelease( + MatchSystemUIFont(weight, kSFProDisplayBreakPoint))); + if (large_system_font_weighted) { + dynamic_font_manager.font_provider().RegisterTypeface( + large_system_font_weighted, kSFProDisplayName); + } + }; + for (int i = 0; i < 8; i++) { + const int font_weight = i * 100; + register_weighted_font(font_weight); } + // The value 780 returns a font weight of 800. + register_weighted_font(780); + // The value of 810 returns a font weight of 900. + register_weighted_font(810); } } // namespace txt diff --git a/third_party/txt/tests/platform_mac_tests.cc b/third_party/txt/tests/platform_mac_tests.cc index 54cea1c1324a1..5ede81394ecdc 100644 --- a/third_party/txt/tests/platform_mac_tests.cc +++ b/third_party/txt/tests/platform_mac_tests.cc @@ -21,13 +21,14 @@ class PlatformMacTests : public ::testing::Test { TEST_F(PlatformMacTests, RegisterSystemFonts) { DynamicFontManager dynamic_font_manager; RegisterSystemFonts(dynamic_font_manager); - ASSERT_EQ(dynamic_font_manager.font_provider().GetFamilyCount(), 2ul); + ASSERT_EQ(dynamic_font_manager.font_provider().GetFamilyCount(), 1ul); ASSERT_NE(dynamic_font_manager.font_provider().MatchFamily( "CupertinoSystemDisplay"), nullptr); - ASSERT_NE( - dynamic_font_manager.font_provider().MatchFamily("CupertinoSystemText"), - nullptr); + ASSERT_EQ(dynamic_font_manager.font_provider() + .MatchFamily("CupertinoSystemDisplay") + ->count(), + 10); } } // namespace testing