From bebb8137091ceeb1990564c4e0e2ad8e5bec9a93 Mon Sep 17 00:00:00 2001 From: Tim Maffett Date: Mon, 1 May 2023 13:49:41 -0700 Subject: [PATCH] Fixes font-subset to not drop GSUB/GPOS/GDEF tables for variable fonts where they are needed Fixes #125704 (flutter/engine#41592) This PR fixes font-subset to check to see if a font is a variable font with variable font axes before additionally dropping the GSUB/GPOS/GDEF tables. These tables were being forced dropped in all cases (even though harfbuzz had been modified to always keep them). I made the change only drop the tables for variable fonts to preserve the previous behavior in the most possible cases. This PR fixes [#125704](https://github.com/flutter/flutter/issues/125704). To see the bug (or verify it is fixed) in the live web examples below you must select the font variations Fill->1 and Weight->100. (See issue [#125704](https://github.com/flutter/flutter/issues/125704) for more details). The issue [#125704](https://github.com/flutter/flutter/issues/125704) includes examples of the font-subset being used (and breaking) the variable fonts, as well as example of the `--no-tree-shake-icons` being used where the fonts do not break. Additionally, I have created an additional [live example](https://timmaffett.github.io/material_symbols_icons_showing_tree_shake_fixed/) where this PR has been applied to font-subset and icon tree shaking is still taking place. (Example w/ icon tree-shaking using the broken font-subset for icon tree shaking is found [here](https://timmaffett.github.io/material_symbols_icons_showing_tree_shake_bug/) ). In the example build output below note that the non-variable fonts "CupertinoIcons.ttf" and "MaterialIcons-Regular.otf" have the same size savings as before the change, but the variable fonts "MaterialSymbolsSharp[FILL,GRAD,opsz,wght].ttf", "MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf", and "MaterialSymbolsRounded[FILL,GRAD,opsz,wght].ttf" now have a much more reasonable saving of ~2% because every icon in the font is included in the example. The previous extra ~30% savings was from having the GSUB table removed. The 30% size savings for a tree-shaking for a case where *every* icon is used in the example probably should have been suspect.. lol. Output of build using fixed font-subset.exe [live fix example](https://timmaffett.github.io/material_symbols_icons_showing_tree_shake_fixed/) : ```console flutter build web --release --web-renderer canvaskit --base-href "/material_symbols_icons_showing_tree_shake_fixed/" Font asset "CupertinoIcons.ttf" was tree-shaken, reducing it from 283452 to 1236 bytes (99.6% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 10808 bytes (99.3% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsSharp[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 5848492 to 5683212 bytes (2.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 6944756 to 6779476 bytes (2.4% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsRounded[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 9361824 to 9196544 bytes (1.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Compiling lib\main.dart for the Web... 79.5s ``` BEFORE font-subset fix [live bug example here](https://timmaffett.github.io/material_symbols_icons_showing_tree_shake_bug/): ```console flutter build web --release --web-renderer canvaskit --base-href "/material_symbols_icons_showing_tree_shake_bug/" Font asset "CupertinoIcons.ttf" was tree-shaken, reducing it from 283452 to 1236 bytes (99.6% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsSharp[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 5848492 to 4079548 bytes (30.2% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 6944756 to 4781576 bytes(31.1% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 10808 bytes (99.3% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Font asset "MaterialSymbolsRounded[FILL,GRAD,opsz,wght].ttf" was tree-shaken, reducing it from 9361824 to 6397020 bytes (31.7% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Compiling lib\main.dart for the Web... 63.8s ``` --- .../tools/font-subset/fixtures/1variable.ttf | Bin 0 -> 5020 bytes .../tools/font-subset/fixtures/2variable.ttf | Bin 0 -> 7844 bytes .../tools/font-subset/fixtures/3variable.ttf | Bin 0 -> 10304 bytes .../fixtures/MaterialSymbols-Variable.ttf | Bin 0 -> 56304 bytes engine/src/flutter/tools/font-subset/main.cc | 22 +++++--- engine/src/flutter/tools/font-subset/test.py | 47 ++++++++++++++++++ 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 engine/src/flutter/tools/font-subset/fixtures/1variable.ttf create mode 100644 engine/src/flutter/tools/font-subset/fixtures/2variable.ttf create mode 100644 engine/src/flutter/tools/font-subset/fixtures/3variable.ttf create mode 100644 engine/src/flutter/tools/font-subset/fixtures/MaterialSymbols-Variable.ttf diff --git a/engine/src/flutter/tools/font-subset/fixtures/1variable.ttf b/engine/src/flutter/tools/font-subset/fixtures/1variable.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b5702ad83495a32592710b68a87cb4bc07649e30 GIT binary patch literal 5020 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 IFfcFx0R6yQod5s; literal 0 HcmV?d00001 diff --git a/engine/src/flutter/tools/font-subset/fixtures/2variable.ttf b/engine/src/flutter/tools/font-subset/fixtures/2variable.ttf new file mode 100644 index 0000000000000000000000000000000000000000..031beabff156914c92e49b8617ac0f49905feedd GIT binary patch literal 7844 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 literal 0 HcmV?d00001 diff --git a/engine/src/flutter/tools/font-subset/main.cc b/engine/src/flutter/tools/font-subset/main.cc index fc53ef4e61..fc9765b616 100644 --- a/engine/src/flutter/tools/font-subset/main.cc +++ b/engine/src/flutter/tools/font-subset/main.cc @@ -59,14 +59,20 @@ struct HarfBuzzSubset { // The prior version of harfbuzz automatically dropped layout tables, // but in the new version they are kept by default. So re-add them to the // drop list to retain the same behaviour. - - hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), - HB_TAG('G', 'S', 'U', 'B')); - hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), - HB_TAG('G', 'P', 'O', 'S')); - hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), - HB_TAG('G', 'D', 'E', 'F')); - + if (!hb_ot_var_has_data(face) || hb_ot_var_get_axis_count(face) == 0) { + // we can only drop GSUB/GPOS/GDEF for non variable fonts, they may be + // needed for variable fonts (guessing we need to keep all of these, but + // in Material Symbols Icon variable fonts if we drop the GSUB table (they + // do not have GPOS/DEF) then the Fill=1,Weight=100 variation is rendered + // incorrect. (and other variations are probably less noticibly + // incorrect)) + hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), + HB_TAG('G', 'S', 'U', 'B')); + hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), + HB_TAG('G', 'P', 'O', 'S')); + hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG), + HB_TAG('G', 'D', 'E', 'F')); + } return HarfbuzzWrappers::HbFacePtr(hb_subset_or_fail(face, input)); } }; diff --git a/engine/src/flutter/tools/font-subset/test.py b/engine/src/flutter/tools/font-subset/test.py index fff6f89b86..540b27c027 100755 --- a/engine/src/flutter/tools/font-subset/test.py +++ b/engine/src/flutter/tools/font-subset/test.py @@ -28,6 +28,9 @@ PLATFORM_2_PATH = { SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, '..', '..', '..')) MATERIAL_TTF = os.path.join(SCRIPT_DIR, 'fixtures', 'MaterialIcons-Regular.ttf') +VARIABLE_MATERIAL_TTF = os.path.join( + SCRIPT_DIR, 'fixtures', 'MaterialSymbols-Variable.ttf' +) IS_WINDOWS = sys.platform.startswith(('cygwin', 'win')) EXE = '.exe' if IS_WINDOWS else '' BAT = '.bat' if IS_WINDOWS else '' @@ -67,6 +70,27 @@ COMPARE_TESTS = ( r'0xE004', r'0xE021', ]), + # repeat tests with variable input font and verified variable output goldens + (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'57347']), + (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'0xE003']), + (True, '1variable.ttf', VARIABLE_MATERIAL_TTF, [r'\uE003']), + (False, '1variable.ttf', VARIABLE_MATERIAL_TTF, + [r'57348']), # False because different codepoint + (True, '2variable.ttf', VARIABLE_MATERIAL_TTF, [r'0xE003', r'0xE004']), + ( + True, '2variable.ttf', VARIABLE_MATERIAL_TTF, [ + r'0xE003', + r'0xE004', + r'57347', + ] + ), # Duplicated codepoint + ( + True, '3variable.ttf', VARIABLE_MATERIAL_TTF, [ + r'0xE003', + r'0xE004', + r'0xE021', + ] + ), ) FAIL_TESTS = [ @@ -95,6 +119,29 @@ FAIL_TESTS = [ ]), # empty input ([FONT_SUBSET, 'output.ttf', MATERIAL_TTF], []), # empty input ([FONT_SUBSET, 'output.ttf', MATERIAL_TTF], ['']), # empty input + # repeat tests with variable input font + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], [ + '0xFFFFFFFF', + ]), # Value too big. + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], [ + '-1', + ]), # invalid value + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], [ + 'foo', + ]), # no valid values + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], [ + '0xE003', + '0x12', + '0xE004', + ]), # codepoint not in font + ([FONT_SUBSET, 'non-existent-dir/output.ttf', VARIABLE_MATERIAL_TTF], [ + '0xE003', + ]), # dir doesn't exist + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], [ + ' ', + ]), # empty input + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], []), # empty input + ([FONT_SUBSET, 'output.ttf', VARIABLE_MATERIAL_TTF], ['']), # empty input ]