未验证 提交 2db93a74 编写于 作者: H Harry Terkelsen 提交者: GitHub

Place Emoji fallback font at the front of the list (#27491)

上级 51104bb2
......@@ -126,7 +126,8 @@ class FontFallbackData {
fonts.addAll(typefacesForFamily);
}
}
final List<bool> codeUnitsSupported = List<bool>.filled(codeUnits.length, false);
final List<bool> codeUnitsSupported =
List<bool>.filled(codeUnits.length, false);
final String testString = String.fromCharCodes(codeUnits);
for (SkFont font in fonts) {
final Uint8List glyphs = font.getGlyphIDs(testString);
......@@ -167,11 +168,13 @@ class FontFallbackData {
// fonts. Check them and update the cache.
final List<int> codeUnits = _codeUnitsToCheckAgainstFallbackFonts.toList();
_codeUnitsToCheckAgainstFallbackFonts.clear();
final List<bool> codeUnitsSupported = List<bool>.filled(codeUnits.length, false);
final List<bool> codeUnitsSupported =
List<bool>.filled(codeUnits.length, false);
final String testString = String.fromCharCodes(codeUnits);
for (String font in globalFontFallbacks) {
final List<SkFont>? fontsForFamily = skiaFontCollection.familyToFontMap[font];
final List<SkFont>? fontsForFamily =
skiaFontCollection.familyToFontMap[font];
if (fontsForFamily == null) {
printWarning('A fallback font was registered but we '
'cannot retrieve the typeface for it.');
......@@ -227,8 +230,20 @@ class FontFallbackData {
final int fontFallbackTag = fontFallbackCounts[family]!;
fontFallbackCounts[family] = fontFallbackCounts[family]! + 1;
final String countedFamily = '$family $fontFallbackTag';
// Insert emoji font before all other fallback fonts so we use the emoji
// whenever it's available.
registeredFallbackFonts.add(RegisteredFont(bytes, countedFamily, typeface));
globalFontFallbacks.add(countedFamily);
// Insert emoji font before all other fallback fonts so we use the emoji
// whenever it's available.
if (family == 'Noto Color Emoji Compat') {
if (globalFontFallbacks.first == 'Roboto') {
globalFontFallbacks.insert(1, countedFamily);
} else {
globalFontFallbacks.insert(0, countedFamily);
}
} else {
globalFontFallbacks.add(countedFamily);
}
}
}
......@@ -351,14 +366,16 @@ _ResolvedNotoFont? _makeResolvedNotoFontFromCss(String css, String name) {
if (startEnd.length == 1) {
final String singleRange = startEnd.single;
assert(singleRange.startsWith('U+'));
final int rangeValue = int.parse(singleRange.substring(2), radix: 16);
final int rangeValue =
int.parse(singleRange.substring(2), radix: 16);
fontFaceUnicodeRanges.add(CodeunitRange(rangeValue, rangeValue));
} else {
assert(startEnd.length == 2);
final String startRange = startEnd[0];
final String endRange = startEnd[1];
assert(startRange.startsWith('U+'));
final int startValue = int.parse(startRange.substring(2), radix: 16);
final int startValue =
int.parse(startRange.substring(2), radix: 16);
final int endValue = int.parse(endRange, radix: 16);
fontFaceUnicodeRanges.add(CodeunitRange(startValue, endValue));
}
......@@ -410,15 +427,15 @@ Future<void> _registerSymbolsAndEmoji() async {
return;
}
data.registeredSymbolsAndEmoji = true;
const String symbolsUrl =
'https://fonts.googleapis.com/css2?family=Noto+Sans+Symbols';
const String emojiUrl =
'https://fonts.googleapis.com/css2?family=Noto+Color+Emoji+Compat';
const String symbolsUrl =
'https://fonts.googleapis.com/css2?family=Noto+Sans+Symbols';
final String symbolsCss =
await notoDownloadQueue.downloader.downloadAsString(symbolsUrl);
final String emojiCss =
await notoDownloadQueue.downloader.downloadAsString(emojiUrl);
final String symbolsCss =
await notoDownloadQueue.downloader.downloadAsString(symbolsUrl);
String? extractUrlFromCss(String css) {
for (final String line in LineSplitter.split(css)) {
......@@ -436,21 +453,21 @@ Future<void> _registerSymbolsAndEmoji() async {
return null;
}
final String? symbolsFontUrl = extractUrlFromCss(symbolsCss);
final String? emojiFontUrl = extractUrlFromCss(emojiCss);
final String? symbolsFontUrl = extractUrlFromCss(symbolsCss);
if (symbolsFontUrl != null) {
if (emojiFontUrl != null) {
notoDownloadQueue.add(_ResolvedNotoSubset(
symbolsFontUrl, 'Noto Sans Symbols', const <CodeunitRange>[]));
emojiFontUrl, 'Noto Color Emoji Compat', const <CodeunitRange>[]));
} else {
printWarning('Error parsing CSS for Noto Symbols font.');
printWarning('Error parsing CSS for Noto Emoji font.');
}
if (emojiFontUrl != null) {
if (symbolsFontUrl != null) {
notoDownloadQueue.add(_ResolvedNotoSubset(
emojiFontUrl, 'Noto Color Emoji Compat', const <CodeunitRange>[]));
symbolsFontUrl, 'Noto Sans Symbols', const <CodeunitRange>[]));
} else {
printWarning('Error parsing CSS for Noto Emoji font.');
printWarning('Error parsing CSS for Noto Symbols font.');
}
}
......
......@@ -56,24 +56,6 @@ void testMain() {
});
test('will download Noto Naskh Arabic if Arabic text is added', () async {
final Completer<void> fontChangeCompleter = Completer<void>();
// Intercept the system font change message.
ui.window.onPlatformMessage = (String name, ByteData? data,
ui.PlatformMessageResponseCallback? callback) {
if (name == 'flutter/system') {
const JSONMessageCodec codec = JSONMessageCodec();
final dynamic message = codec.decodeMessage(data);
if (message is Map) {
if (message['type'] == 'fontsChange') {
fontChangeCompleter.complete();
}
}
}
if (savedCallback != null) {
savedCallback!(name, data, callback);
}
};
TestDownloader.mockDownloads[
'https://fonts.googleapis.com/css2?family=Noto+Naskh+Arabic+UI'] =
'''
......@@ -98,7 +80,7 @@ void testMain() {
EnginePlatformDispatcher.instance.rasterizer!
.debugRunPostFrameCallbacks();
await fontChangeCompleter.future;
await notoDownloadQueue.debugWhenIdle();
expect(FontFallbackData.instance.globalFontFallbacks,
contains('Noto Naskh Arabic UI 0'));
......@@ -123,30 +105,71 @@ void testMain() {
// TODO: https://github.com/flutter/flutter/issues/71520
}, skip: isIosSafari || isFirefox);
test('will download Noto Emojis and Noto Symbols if no matching Noto Font',
test('will put the Noto Emoji font before other fallback fonts in the list',
() async {
final Completer<void> fontChangeCompleter = Completer<void>();
// Intercept the system font change message.
ui.window.onPlatformMessage = (String name, ByteData? data,
ui.PlatformMessageResponseCallback? callback) {
if (name == 'flutter/system') {
const JSONMessageCodec codec = JSONMessageCodec();
final dynamic message = codec.decodeMessage(data);
if (message is Map) {
if (message['type'] == 'fontsChange') {
fontChangeCompleter.complete();
}
}
}
if (savedCallback != null) {
savedCallback!(name, data, callback);
}
};
TestDownloader.mockDownloads[
'https://fonts.googleapis.com/css2?family=Noto+Color+Emoji+Compat'] =
'''
@font-face {
font-family: 'Noto Color Emoji';
src: url(packages/ui/assets/NotoColorEmoji.ttf) format('ttf');
}
''';
TestDownloader.mockDownloads[
'https://fonts.googleapis.com/css2?family=Noto+Naskh+Arabic+UI'] =
'''
/* arabic */
@font-face {
font-family: 'Noto Naskh Arabic UI';
font-style: normal;
font-weight: 400;
src: url(packages/ui/assets/NotoNaskhArabic-Regular.ttf) format('ttf');
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC;
}
''';
expect(FontFallbackData.instance.globalFontFallbacks, <String>['Roboto']);
// Creating this paragraph should cause us to start to download the
// Arabic fallback font.
CkParagraphBuilder pb = CkParagraphBuilder(
CkParagraphStyle(),
);
pb.addText('مرحبا');
EnginePlatformDispatcher.instance.rasterizer!
.debugRunPostFrameCallbacks();
await notoDownloadQueue.debugWhenIdle();
expect(FontFallbackData.instance.globalFontFallbacks,
<String>['Roboto', 'Noto Naskh Arabic UI 0']);
pb = CkParagraphBuilder(
CkParagraphStyle(),
);
pb.pushStyle(ui.TextStyle(fontSize: 26));
pb.addText('Hello 😊 مرحبا');
pb.pop();
final CkParagraph paragraph = pb.build();
paragraph.layout(ui.ParagraphConstraints(width: 1000));
EnginePlatformDispatcher.instance.rasterizer!
.debugRunPostFrameCallbacks();
await notoDownloadQueue.debugWhenIdle();
expect(FontFallbackData.instance.globalFontFallbacks, <String>[
'Roboto',
'Noto Color Emoji Compat 0',
'Noto Naskh Arabic UI 0',
]);
});
test('will download Noto Emojis and Noto Symbols if no matching Noto Font',
() async {
TestDownloader.mockDownloads[
'https://fonts.googleapis.com/css2?family=Noto+Color+Emoji+Compat'] =
'''
@font-face {
font-family: 'Noto Color Emoji';
src: url(packages/ui/assets/NotoColorEmoji.ttf) format('ttf');
......@@ -164,7 +187,7 @@ void testMain() {
EnginePlatformDispatcher.instance.rasterizer!
.debugRunPostFrameCallbacks();
await fontChangeCompleter.future;
await notoDownloadQueue.debugWhenIdle();
expect(FontFallbackData.instance.globalFontFallbacks,
contains('Noto Color Emoji Compat 0'));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册