-
Notifications
You must be signed in to change notification settings - Fork 6k
[web] Split all 1MB+ fallback fonts (including CJK) #56388
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
|
This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again. |
harryterkelsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
I still need to do something about these. |
I think instead of comparing the font to the (single) Noto Sans SC, TC, etc you can basically replace the checks for "if font == _notoSansSC" with "if font.name == 'Noto Sans SC'" |
Yep, that and there are also some |
ditman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a small suggestion to improve error reporting a little bit.
|
@harryterkelsen @ditman would you mind taking another look? I fixed the logic for picking a font based on user preferred language. I want to make sure that part is reviewed too. |
ditman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see anything major, it seems the font selection stays the same?
| @visibleForTesting | ||
| String get debugUserPreferredLanguage => _language; | ||
|
|
||
| @visibleForTesting | ||
| set debugUserPreferredLanguage(String value) { | ||
| _language = value; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @visibleForTesting | |
| String get debugUserPreferredLanguage => _language; | |
| @visibleForTesting | |
| set debugUserPreferredLanguage(String value) { | |
| _language = value; | |
| } | |
| @visibleForTesting | |
| String debugUserPreferredLanguage = _language; |
Same effect, less code? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. With your suggestion, debugUserPreferredLanguage will get out of sync with _language, and the code below won't pick up changes to debugUserPreferredLanguage.
| _isNotoSansHK(font) || | ||
| _isNotoSansJP(font) || | ||
| _isNotoSansKR(font))) { | ||
| if (_language == 'zh-Hans' || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can _language ever be just 'zh'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure. Revising the logic wasn't a goal for this PR. I was just trying to make the logic work the same way after the font split.
That said, I think you're right in the other comment that the zh case is handled later by the catch-all.
| // If the list of best fonts are all CJK fonts, choose the best one based | ||
| // on user preferred language. Otherwise just choose the first font. | ||
| if (bestFonts.every((NotoFont font) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this to check that all bestFonts are CJK, or should this kick in when there's "more than one"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question, and we may want to revise some of the logic in this file. But, again, this is a non-goal for this PR 🙂
| } else if (bestFonts.contains(_notoSansSC)) { | ||
| bestFont = _notoSansSC; | ||
| } else { | ||
| final notoSansSC = bestFonts.firstWhereOrNull(_isNotoSansSC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this final catch-all solves all the possible corner cases of CJK fonts, by defaulting to simplified chinese :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding a test for this (i.e. lang="zh")
| final commonCJKCodePoints = <int>[ | ||
| 0x56de, // CJK Unified Ideographs | ||
| 0x700b, // CJK Unified Ideographs | ||
| 0x9c57, // CJK Unified Ideographs | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think testing in more than one codepoint adds much to the test? This is testing the language selection mostly, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original idea was to find code points that would naturally default to different fonts when no language is specified (e.g. one code point that defaults to JP and another that would default to KR). But I couldn't find any unfortunately.
I think I'll use just one code point and get rid of the for loop.
| for (final lang in <String>['zh-Hans', 'zh-CN', 'zh-SG', 'zh-MY', 'en-US']) { | ||
| // Simplified Chinese is also prioritized when preferred language is en-US. | ||
| test('prioritizes Noto Sans SC for code-point=$codePointHex lang=$lang', () async { | ||
| await checkDownloadedFamilyForCharCode(codePoint, 'Noto Sans SC', userPreferredLanguage: lang); | ||
| }); | ||
| } | ||
|
|
||
| // Traditional Chinese | ||
| for (final lang in <String>['zh-Hant', 'zh-TW', 'zh-MO']) { | ||
| test('prioritizes Noto Sans TC for code-point=$codePointHex lang=$lang', () async { | ||
| await checkDownloadedFamilyForCharCode(codePoint, 'Noto Sans TC', userPreferredLanguage: lang); | ||
| }); | ||
| } | ||
|
|
||
| // Hong Kong |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could simplify all these tests with:
const fontFamilyToPreferredLanguage = Map<String, List<String>> {
'Noto Sans SC': <String>['zh-Hans', 'zh-CN', 'zh-SG'...],
'Noto Sans TC': <String>['zh-Hant', 'zh-TW', ...],
...
}And iterating over its entries to generate all the possible tests without duplicating any code? :)
(It might make the actual test harder to find when it fails if we try to search by the error message or line number though)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was actually leaning the opposite direction. I prefer better readability/searchability. I was thinking of removing all for loops and doing:
test('prioritizes Noto Sans TC for code-point=0x700b lang=zh-Hant', () async {
await checkDownloadedFamilyForCharCode(codePoint, 'Noto Sans TC', userPreferredLanguage: 'zh-Hant');
});
test('prioritizes Noto Sans TC for code-point=0x700b lang=zh-TW', () async {
await checkDownloadedFamilyForCharCode(codePoint, 'Noto Sans TC', userPreferredLanguage: 'zh-TW');
});
test('prioritizes Noto Sans TC for code-point=0x700b lang=zh-MO', () async {
await checkDownloadedFamilyForCharCode(codePoint, 'Noto Sans TC', userPreferredLanguage: 'zh-MO');
});The code duplication isn't bad honestly. All the logic lives in checkDownloadedFamilyForCharCode.
Now that you suggested testing only one code point, I have an even stronger feeling to remove all the for loops 🙂
harryterkelsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. |
…158402) flutter/engine@6b77347...b7134d3 2024-11-08 [email protected] fml: Use CFRef where possible and add docs (flutter/engine#56436) 2024-11-08 [email protected] [web] Split all 1MB+ fallback fonts (including CJK) (flutter/engine#56388) 2024-11-08 [email protected] yapf: Add more detailed error message and TODO (flutter/engine#56458) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
|
Time to revert pull request flutter/engine/56388 has elapsed. |
…6388) By splitting all large fallback fonts (1MB+) into smaller parts, we get faster downloads and fast decoding. Some fonts are split into 100+ parts, and that's causing `main.dart.js`'s size to grow by ~47KB (Brotli-compressed). The increase in size is due to the extra data we have to store about all the parts of these fonts. The PR also makes changes to ensure we don't download the same license file 100 times (once for each part of the split font). Fixes flutter#138288 Part of flutter#153974
By splitting all large fallback fonts (1MB+) into smaller parts, we get faster downloads and fast decoding.
Some fonts are split into 100+ parts, and that's causing
main.dart.js's size to grow by ~47KB (Brotli-compressed). The increase in size is due to the extra data we have to store about all the parts of these fonts.The PR also makes changes to ensure we don't download the same license file 100 times (once for each part of the split font).
Fixes flutter/flutter#138288
Part of flutter/flutter#153974