Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[reland] Canvaskit get googlefont data #35646

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
efa7c61
WIP font data script
harryterkelsen Jun 23, 2022
5df1ee4
wip
harryterkelsen Jun 23, 2022
377703c
WIP
harryterkelsen Jun 23, 2022
2ff37e5
wip
harryterkelsen Jun 24, 2022
c7e7b54
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Jun 27, 2022
a9ffa81
WIP
harryterkelsen Jun 29, 2022
dc119fe
Merge main
harryterkelsen Jun 30, 2022
d68dade
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Jul 18, 2022
62db0c0
Remove family count and touch up tests
harryterkelsen Jul 18, 2022
9da5993
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Jul 18, 2022
f2edc35
Undo spurious changes
harryterkelsen Jul 18, 2022
493fa6d
Update license
harryterkelsen Jul 18, 2022
d5e28f8
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Jul 29, 2022
0293256
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 1, 2022
88f6683
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 2, 2022
0255cd8
WIP
harryterkelsen Aug 5, 2022
d448215
WIP
harryterkelsen Aug 9, 2022
e385094
Use flat range list and binary search
harryterkelsen Aug 9, 2022
4275e7c
Update README
harryterkelsen Aug 9, 2022
c4c5829
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 9, 2022
3ac2c06
Add edge cases for when the range containing the unit is either the
harryterkelsen Aug 10, 2022
2724489
Fix edge cases in binary search where first or last range contains the
harryterkelsen Aug 10, 2022
4c434c0
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 17, 2022
9744831
Retry tests
harryterkelsen Aug 17, 2022
a6b6567
Fix generated file
harryterkelsen Aug 17, 2022
a6a33b1
Fix generated file
harryterkelsen Aug 17, 2022
facbe5d
Fix generated fonts
harryterkelsen Aug 17, 2022
56970e6
Fix generation
harryterkelsen Aug 17, 2022
19df75b
Generate font data
harryterkelsen Aug 17, 2022
cfd7b45
Analysis warnings
harryterkelsen Aug 17, 2022
9ca5ecd
Make font list final
harryterkelsen Aug 17, 2022
2f1f7f8
Don't download fonts locally
harryterkelsen Aug 17, 2022
cdb770f
unused imports
harryterkelsen Aug 18, 2022
63297d4
Tweak README to kick the CI
harryterkelsen Aug 18, 2022
e6b8b27
Fix binary search
harryterkelsen Aug 18, 2022
01f3d0b
Update test for alphabetical order
harryterkelsen Aug 18, 2022
54d3647
Make SC the default if all CJK languages match equally
harryterkelsen Aug 18, 2022
7af2330
Choose SC for the best font if it's an option, for consistency
harryterkelsen Aug 19, 2022
9a4c545
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 23, 2022
88960f7
WIP figure out bug in framework tests w/ timer
harryterkelsen Aug 23, 2022
52d9c23
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 24, 2022
cb3d1f3
Disable font fallbacks in tests where it will cause errors
harryterkelsen Aug 24, 2022
f12befc
Merge branch 'main' into canvaskit-get-googlefont-data
harryterkelsen Aug 24, 2022
ec01769
Move debugDisableFontFallbacks to engine.dart
harryterkelsen Aug 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/canvaskit_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/color_filter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/embedded_views_diff.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/font_fallback_data.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/font_fallbacks.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/fonts.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/image.dart
Expand All @@ -1151,6 +1152,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.d
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/mask_filter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/n_way_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/noto_font.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/painting.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/path.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/path_metrics.dart
Expand Down
13 changes: 13 additions & 0 deletions lib/web_ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,19 @@ directly), follow these steps to roll to the new version:
If you have questions, contact the Flutter Web team on Flutter Discord on the
#hackers-web-🌍 channel.

### Rolling Noto Font Data

In order to generate new data for the Noto fallback fonts, you will need
a GoogleFonts API key. Once you have one, run:

```
./dev/felt generate-fallback-font-data --key=<your GoogleFonts API key>
```

This will generate the file `lib/src/engine/canvaskit/font_fallback_data.dart` with
the latest data from GoogleFonts. This generated file should then be rolled in with
a PR to the engine.

### Configuration files

`browser_lock.yaml` contains the version of browsers we use to test Flutter for
Expand Down
2 changes: 2 additions & 0 deletions lib/web_ui/dev/felt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:args/command_runner.dart';
import 'build.dart';
import 'clean.dart';
import 'exceptions.dart';
import 'generate_fallback_font_data.dart';
import 'licenses.dart';
import 'run.dart';
import 'test_runner.dart';
Expand All @@ -20,6 +21,7 @@ CommandRunner<bool> runner = CommandRunner<bool>(
)
..addCommand(BuildCommand())
..addCommand(CleanCommand())
..addCommand(GenerateFallbackFontDataCommand())
..addCommand(LicensesCommand())
..addCommand(RunCommand())
..addCommand(TestCommand());
Expand Down
289 changes: 289 additions & 0 deletions lib/web_ui/dev/generate_fallback_font_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert' show jsonDecode;
import 'dart:io' as io;

import 'package:args/command_runner.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;

import 'environment.dart';
import 'exceptions.dart';
import 'utils.dart';

class GenerateFallbackFontDataCommand extends Command<bool>
with ArgUtils<bool> {
GenerateFallbackFontDataCommand() {
argParser.addOption(
'key',
defaultsTo: '',
help: 'The Google Fonts API key. Used to get data about fonts hosted on '
'Google Fonts.',
);
argParser.addFlag(
'download-test-fonts',
defaultsTo: true,
help: 'Whether to download the Noto fonts into a local folder to use in'
'tests.',
);
}

@override
final String name = 'generate-fallback-font-data';

@override
final String description = 'Generate fallback font data from GoogleFonts';

String get apiKey => stringArg('key');

bool get downloadTestFonts => boolArg('download-test-fonts');

@override
Future<bool> run() async {
await _generateFallbackFontData();
return true;
}

Future<void> _generateFallbackFontData() async {
if (apiKey.isEmpty) {
throw UsageException('No Google Fonts API key provided', argParser.usage);
}
final http.Client client = http.Client();
final http.Response response = await client.get(Uri.parse(
'https://www.googleapis.com/webfonts/v1/webfonts?key=$apiKey'));
if (response.statusCode != 200) {
throw ToolExit('Failed to download Google Fonts list.');
}
final Map<String, dynamic> googleFontsResult =
jsonDecode(response.body) as Map<String, dynamic>;
final List<Map<String, dynamic>> fontDatas =
(googleFontsResult['items'] as List<dynamic>)
.cast<Map<String, dynamic>>();
final Map<String, Uri> urlForFamily = <String, Uri>{};
for (final Map<String, dynamic> fontData in fontDatas) {
if (fallbackFonts.contains(fontData['family'])) {
final Uri uri = Uri.parse(fontData['files']['regular'] as String);
urlForFamily[fontData['family'] as String] = uri;
}
}
final Map<String, String> charsetForFamily = <String, String>{};
final io.Directory fontDir = downloadTestFonts
? await io.Directory(path.join(
environment.webUiBuildDir.path,
'assets',
'noto',
)).create(recursive: true)
: await io.Directory.systemTemp.createTemp('fonts');
// Delete old fonts in the font directory.
await for (final io.FileSystemEntity file in fontDir.list()) {
await file.delete();
}
for (final String family in fallbackFonts) {
print('Downloading $family...');
final Uri uri = urlForFamily[family]!;
final http.Response fontResponse = await client.get(uri);
if (fontResponse.statusCode != 200) {
throw ToolExit('Failed to download font for $family');
}
final io.File fontFile =
io.File(path.join(fontDir.path, path.basename(uri.path)));
await fontFile.writeAsBytes(fontResponse.bodyBytes);
final io.ProcessResult fcQueryResult =
await io.Process.run('fc-query', <String>[
'--format=%{charset}',
'--',
fontFile.path,
]);
final String encodedCharset = fcQueryResult.stdout as String;
charsetForFamily[family] = encodedCharset;
}

final StringBuffer sb = StringBuffer();

sb.writeln('// Copyright 2013 The Flutter Authors. All rights reserved.');
sb.writeln('// Use of this source code is governed by a BSD-style license '
'that can be');
sb.writeln('// found in the LICENSE file.');
sb.writeln();
sb.writeln('// DO NOT EDIT! This file is generated. See:');
sb.writeln('// dev/generate_fallback_font_data.dart');
sb.writeln("import 'noto_font.dart';");
sb.writeln();
sb.writeln('final List<NotoFont> fallbackFonts = <NotoFont>[');
for (final String family in fallbackFonts) {
sb.write(" NotoFont.fromFlatRanges('$family', '${urlForFamily[family]!}', "
'<int>[');
for (final String range in charsetForFamily[family]!.split(' ')) {
String? start;
String? end;
final List<String> parts = range.split('-');
if (parts.length == 1) {
start = parts[0];
end = parts[0];
} else {
start = parts[0];
end = parts[1];
}
sb.write('0x$start,0x$end,');
}
sb.writeln(']),');
}
sb.writeln('];');

final io.File fontDataFile = io.File(path.join(
environment.webUiRootDir.path,
'lib',
'src',
'engine',
'canvaskit',
'font_fallback_data.dart',
));
await fontDataFile.writeAsString(sb.toString());
}
}

const List<String> fallbackFonts = <String>[
'Noto Sans',
'Noto Emoji',
'Noto Sans Symbols',
'Noto Sans Symbols 2',
'Noto Sans Adlam',
'Noto Sans Anatolian Hieroglyphs',
'Noto Sans Arabic',
'Noto Sans Armenian',
'Noto Sans Avestan',
'Noto Sans Balinese',
'Noto Sans Bamum',
'Noto Sans Bassa Vah',
'Noto Sans Batak',
'Noto Sans Bengali',
'Noto Sans Bhaiksuki',
'Noto Sans Brahmi',
'Noto Sans Buginese',
'Noto Sans Buhid',
'Noto Sans Canadian Aboriginal',
'Noto Sans Carian',
'Noto Sans Caucasian Albanian',
'Noto Sans Chakma',
'Noto Sans Cham',
'Noto Sans Cherokee',
'Noto Sans Coptic',
'Noto Sans Cuneiform',
'Noto Sans Cypriot',
'Noto Sans Deseret',
'Noto Sans Devanagari',
'Noto Sans Duployan',
'Noto Sans Egyptian Hieroglyphs',
'Noto Sans Elbasan',
'Noto Sans Elymaic',
'Noto Sans Georgian',
'Noto Sans Glagolitic',
'Noto Sans Gothic',
'Noto Sans Grantha',
'Noto Sans Gujarati',
'Noto Sans Gunjala Gondi',
'Noto Sans Gurmukhi',
'Noto Sans HK',
'Noto Sans Hanunoo',
'Noto Sans Hatran',
'Noto Sans Hebrew',
'Noto Sans Imperial Aramaic',
'Noto Sans Indic Siyaq Numbers',
'Noto Sans Inscriptional Pahlavi',
'Noto Sans Inscriptional Parthian',
'Noto Sans JP',
'Noto Sans Javanese',
'Noto Sans KR',
'Noto Sans Kaithi',
'Noto Sans Kannada',
'Noto Sans Kayah Li',
'Noto Sans Kharoshthi',
'Noto Sans Khmer',
'Noto Sans Khojki',
'Noto Sans Khudawadi',
'Noto Sans Lao',
'Noto Sans Lepcha',
'Noto Sans Limbu',
'Noto Sans Linear A',
'Noto Sans Linear B',
'Noto Sans Lisu',
'Noto Sans Lycian',
'Noto Sans Lydian',
'Noto Sans Mahajani',
'Noto Sans Malayalam',
'Noto Sans Mandaic',
'Noto Sans Manichaean',
'Noto Sans Marchen',
'Noto Sans Masaram Gondi',
'Noto Sans Math',
'Noto Sans Mayan Numerals',
'Noto Sans Medefaidrin',
'Noto Sans Meetei Mayek',
'Noto Sans Meroitic',
'Noto Sans Miao',
'Noto Sans Modi',
'Noto Sans Mongolian',
'Noto Sans Mro',
'Noto Sans Multani',
'Noto Sans Myanmar',
'Noto Sans N Ko',
'Noto Sans Nabataean',
'Noto Sans New Tai Lue',
'Noto Sans Newa',
'Noto Sans Nushu',
'Noto Sans Ogham',
'Noto Sans Ol Chiki',
'Noto Sans Old Hungarian',
'Noto Sans Old Italic',
'Noto Sans Old North Arabian',
'Noto Sans Old Permic',
'Noto Sans Old Persian',
'Noto Sans Old Sogdian',
'Noto Sans Old South Arabian',
'Noto Sans Old Turkic',
'Noto Sans Oriya',
'Noto Sans Osage',
'Noto Sans Osmanya',
'Noto Sans Pahawh Hmong',
'Noto Sans Palmyrene',
'Noto Sans Pau Cin Hau',
'Noto Sans Phags Pa',
'Noto Sans Phoenician',
'Noto Sans Psalter Pahlavi',
'Noto Sans Rejang',
'Noto Sans Runic',
'Noto Sans SC',
'Noto Sans Saurashtra',
'Noto Sans Sharada',
'Noto Sans Shavian',
'Noto Sans Siddham',
'Noto Sans Sinhala',
'Noto Sans Sogdian',
'Noto Sans Sora Sompeng',
'Noto Sans Soyombo',
'Noto Sans Sundanese',
'Noto Sans Syloti Nagri',
'Noto Sans Syriac',
'Noto Sans TC',
'Noto Sans Tagalog',
'Noto Sans Tagbanwa',
'Noto Sans Tai Le',
'Noto Sans Tai Tham',
'Noto Sans Tai Viet',
'Noto Sans Takri',
'Noto Sans Tamil',
'Noto Sans Tamil Supplement',
'Noto Sans Telugu',
'Noto Sans Thaana',
'Noto Sans Thai',
'Noto Sans Tifinagh',
'Noto Sans Tirhuta',
'Noto Sans Ugaritic',
'Noto Sans Vai',
'Noto Sans Wancho',
'Noto Sans Warang Citi',
'Noto Sans Yi',
'Noto Sans Zanabazar Square',
];
1 change: 1 addition & 0 deletions lib/web_ui/lib/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ set debugEmulateFlutterTesterEnvironment(bool value) {
engine.window.webOnlyDebugPhysicalSizeOverride =
logicalSize * window.devicePixelRatio;
}
engine.debugDisableFontFallbacks = value;
}

bool _debugEmulateFlutterTesterEnvironment = false;
Expand Down
2 changes: 2 additions & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export 'engine/canvaskit/canvaskit_canvas.dart';
export 'engine/canvaskit/color_filter.dart';
export 'engine/canvaskit/embedded_views.dart';
export 'engine/canvaskit/embedded_views_diff.dart';
export 'engine/canvaskit/font_fallback_data.dart';
export 'engine/canvaskit/font_fallbacks.dart';
export 'engine/canvaskit/fonts.dart';
export 'engine/canvaskit/image.dart';
Expand All @@ -38,6 +39,7 @@ export 'engine/canvaskit/layer_scene_builder.dart';
export 'engine/canvaskit/layer_tree.dart';
export 'engine/canvaskit/mask_filter.dart';
export 'engine/canvaskit/n_way_canvas.dart';
export 'engine/canvaskit/noto_font.dart';
export 'engine/canvaskit/painting.dart';
export 'engine/canvaskit/path.dart';
export 'engine/canvaskit/path_metrics.dart';
Expand Down
Loading