Skip to content

Commit 0bbb4d6

Browse files
Get the correct iOS system font for each weight (flutter#48937)
See [flutter/issue/139689](flutter#139689) and [flutter/issue/132475](flutter#132475) Registers all of the possible font weight values for "CupertinoSystemDisplay". The registering of "CupertinoSystemText" was removed, as the fallback will correctly show the right fonts, and this logic does not work for the smaller font due to Apple APIs removing the font weight. The font weights for 800 and 900 had to be added outside of the loop as they were coming back with values different from what was being put in. Before: <img width="250" alt="Screenshot 2023-12-06 at 1 17 11�PM" src="https://github.com/flutter/engine/assets/58190796/036231eb-d4e2-4c93-82de-fa62d7ddc7c1"> After: <img width="364" alt="Screenshot 2024-01-03 at 3 15 33�PM" src="https://github.com/flutter/engine/assets/58190796/69651f01-d694-4758-9fb5-acf50a1895c4"> [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent cd90498 commit 0bbb4d6

2 files changed

Lines changed: 66 additions & 23 deletions

File tree

third_party/txt/src/txt/platform_mac.mm

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020

2121
// Apple system font larger than size 29 returns SFProDisplay typeface.
2222
static const CGFloat kSFProDisplayBreakPoint = 29;
23-
// Apple system font smaller than size 16 returns SFProText typeface.
24-
static const CGFloat kSFProTextBreakPoint = 16;
2523
// Font name represents the "SF Pro Display" system font on Apple platforms.
2624
static const std::string kSFProDisplayName = "CupertinoSystemDisplay";
27-
// Font name represents the "SF Pro Text" system font on Apple platforms.
28-
static const std::string kSFProTextName = "CupertinoSystemText";
25+
// Font weight representing Regular
26+
float kNormalWeightValue = 400;
2927

3028
namespace txt {
3129

30+
const FourCharCode kWeightTag = 'wght';
31+
3232
std::vector<std::string> GetDefaultFontFamilies() {
3333
if (fml::IsPlatformVersionAtLeast(9)) {
3434
return {[FONT_CLASS systemFontOfSize:14].familyName.UTF8String};
@@ -42,34 +42,76 @@
4242
return mgr;
4343
}
4444

45+
CTFontRef MatchSystemUIFont(float desired_weight, float size) {
46+
CTFontRef ct_font(
47+
CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr));
48+
49+
if (desired_weight == kNormalWeightValue) {
50+
return ct_font;
51+
}
52+
53+
CFMutableDictionaryRef variations(CFDictionaryCreateMutable(
54+
kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks,
55+
&kCFTypeDictionaryValueCallBacks));
56+
57+
auto add_axis_to_variations = [&variations](const FourCharCode tag,
58+
float desired_value,
59+
float normal_value) {
60+
if (desired_value != normal_value) {
61+
CFNumberRef tag_number(
62+
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &tag));
63+
CFNumberRef value_number(CFNumberCreate(
64+
kCFAllocatorDefault, kCFNumberFloatType, &desired_value));
65+
CFDictionarySetValue(variations, tag_number, value_number);
66+
}
67+
};
68+
add_axis_to_variations(kWeightTag, desired_weight, kNormalWeightValue);
69+
70+
CFMutableDictionaryRef attributes(CFDictionaryCreateMutable(
71+
kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks,
72+
&kCFTypeDictionaryValueCallBacks));
73+
CFDictionarySetValue(attributes, kCTFontVariationAttribute, variations);
74+
75+
CTFontDescriptorRef var_font_desc(
76+
CTFontDescriptorCreateWithAttributes(attributes));
77+
78+
return CTFontCreateCopyWithAttributes(ct_font, size, nullptr, var_font_desc);
79+
}
80+
4581
void RegisterSystemFonts(const DynamicFontManager& dynamic_font_manager) {
4682
// iOS loads different system fonts when size is greater than 28 or lower
4783
// than 17. The "familyName" property returned from CoreText stays the same
4884
// despite the typeface is different.
4985
//
50-
// Below code manually loads and registers them as two different fonts
51-
// so Flutter app can access them on macOS and iOS.
86+
// Below code manually loads and registers the larger font. The existing
87+
// fallback correctly loads the smaller font. The code also iterates through
88+
// the possible font weights from 100 - 900 to correctly load all of them, as
89+
// a CTFont object for the large system font does not include all of the font
90+
// weights by default.
5291
//
5392
// Darwin system fonts from 17 to 28 also have dynamic spacing based on sizes.
5493
// These two fonts do not match the spacings when sizes are from 17 to 28.
5594
// The spacing should be handled by the app or the framework.
5695
//
5796
// See https://www.wwdcnotes.com/notes/wwdc20/10175/ for Apple's document on
5897
// this topic.
59-
sk_sp<SkTypeface> large_system_font = SkMakeTypefaceFromCTFont(
60-
(CTFontRef)CFAutorelease(CTFontCreateUIFontForLanguage(
61-
kCTFontUIFontSystem, kSFProDisplayBreakPoint, NULL)));
62-
if (large_system_font) {
63-
dynamic_font_manager.font_provider().RegisterTypeface(large_system_font,
64-
kSFProDisplayName);
65-
}
66-
sk_sp<SkTypeface> regular_system_font = SkMakeTypefaceFromCTFont(
67-
(CTFontRef)CFAutorelease(CTFontCreateUIFontForLanguage(
68-
kCTFontUIFontSystem, kSFProTextBreakPoint, NULL)));
69-
if (regular_system_font) {
70-
dynamic_font_manager.font_provider().RegisterTypeface(regular_system_font,
71-
kSFProTextName);
98+
auto register_weighted_font = [&dynamic_font_manager](const int weight) {
99+
sk_sp<SkTypeface> large_system_font_weighted =
100+
SkMakeTypefaceFromCTFont((CTFontRef)CFAutorelease(
101+
MatchSystemUIFont(weight, kSFProDisplayBreakPoint)));
102+
if (large_system_font_weighted) {
103+
dynamic_font_manager.font_provider().RegisterTypeface(
104+
large_system_font_weighted, kSFProDisplayName);
105+
}
106+
};
107+
for (int i = 0; i < 8; i++) {
108+
const int font_weight = i * 100;
109+
register_weighted_font(font_weight);
72110
}
111+
// The value 780 returns a font weight of 800.
112+
register_weighted_font(780);
113+
// The value of 810 returns a font weight of 900.
114+
register_weighted_font(810);
73115
}
74116

75117
} // namespace txt

third_party/txt/tests/platform_mac_tests.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ class PlatformMacTests : public ::testing::Test {
2121
TEST_F(PlatformMacTests, RegisterSystemFonts) {
2222
DynamicFontManager dynamic_font_manager;
2323
RegisterSystemFonts(dynamic_font_manager);
24-
ASSERT_EQ(dynamic_font_manager.font_provider().GetFamilyCount(), 2ul);
24+
ASSERT_EQ(dynamic_font_manager.font_provider().GetFamilyCount(), 1ul);
2525
ASSERT_NE(dynamic_font_manager.font_provider().MatchFamily(
2626
"CupertinoSystemDisplay"),
2727
nullptr);
28-
ASSERT_NE(
29-
dynamic_font_manager.font_provider().MatchFamily("CupertinoSystemText"),
30-
nullptr);
28+
ASSERT_EQ(dynamic_font_manager.font_provider()
29+
.MatchFamily("CupertinoSystemDisplay")
30+
->count(),
31+
10);
3132
}
3233

3334
} // namespace testing

0 commit comments

Comments
 (0)