Open zjrwdl opened 1 year ago
please add in web index.html
return engineInitializer.initializeEngine({
useColorEmoji: true,
});
}).then(function (appRunner) {
return appRunner.runApp();
please add in web index.html
return engineInitializer.initializeEngine({
useColorEmoji: true, }); }).then(function (appRunner) { return appRunner.runApp();
useColorEmoji: true is only supported in canvaskit mode .
Verified this behavior using latest stable and master version and observed that the reported behavior persists using html renderer as below, ie, the emojis are rendered properly as-is with color but overlaps:
Using canvaskit, although the emojis are not rendered as-is (color) but are not overlapped, but as below:
The reported behavior doesn't occur on desktop and mobile.
Looks like how html renders unicode chars as mentioned in original description. There may have been similar / reported issues with emojis not rendering properly (ie unicode chars) on web, but I couldn't find an exact issue if this is a known one already.
Regarding this issue, i was trying to reproduce and found interesting insights!
I reproduced the example using "flutter run -d chrome --web-renderer html" and pasting the text code as described. But with a little tweak, i used SelectableText instead of text, that let me see the text that is trying to be displayed on html.
These are the findings:
1) As you can see i can reproduce correctly.
2) When accessing the text area with js console, i actually get the actual string with emojis that is written in code. This means that the value is the exact same and is not being contorted (from flutter to the UI).
3) When inspecting the text area, see that we have the background set as transparent, and the color set as transparent.
4) If we disable the background, we see that the text actually dissapears, this is because i assume that we are actually drawing that text in the background of our elements when using the html renderer, instead of just showing the text in the element value (the one in the js console).
5) If we disable the color attribute, we see the emojis well displayed! That's because for some reason we don't want to display the text value of the element, don't know why though.
Conclusion:
It seems like the emojis don't naturally display because the html renderer doesn't know how to draw them properly, while the browser actually can. Does anybody know why we don't want to let the browser render the text instead of drawing it ?
P.D: You can ignore the 2⃣, when pasting it in the dart file it didn't even get recognized at least on my system (macos ventura), but focus on the 1️⃣.
After investigating a bit on the engine code 1️⃣
Now i know why "why we don't want to let the browser render the text instead of drawing it" and that is because we want to keep the general interaction effects that are already coded in the flutter part.
if we display the raw text in html, that text won't have any effects / styles / animations that we declare on flutter, it will only be raw text, so we don't want that. That's probably something you guys already know but i'm new to the flutter ecosystem so sorry for the rookie mistakes 😄.
That said, i think this is an engine problem, the browser can easily understand that emoji because it has wide support in different browsers https://emojipedia.org/keycap-digit-one/. But it seems that the text that we draw in the engine can't find at least that emoji.
Another interesting bit is that the 1️⃣ emoji was introduced in Emoji 3.0, see link above for details. And i tried to display emojis from that specification and guess what they work:
So this issue only seems to affect those random emojis 😕
After investigating a bit on the engine code 1️⃣
Now i know why "why we don't want to let the browser render the text instead of drawing it" and that is because we want to keep the general interaction effects that are already coded in the flutter part.
if we display the raw text in html, that text won't have any effects / styles / animations that we declare on flutter, it will only be raw text, so we don't want that. That's probably something you guys already know but i'm new to the flutter ecosystem so sorry for the rookie mistakes 😄.
That said, i think this is an engine problem, the browser can easily understand that emoji because it has wide support in different browsers https://emojipedia.org/keycap-digit-one/. But it seems that the text that we draw in the engine can't find at least that emoji.
Another interesting bit is that the 1️⃣ emoji was introduced in Emoji 3.0, see link above for details. And i tried to display emojis from that specification and guess what they work:
So this issue only seems to affect those random emojis 😕
Thank you for your detailed analysis. It is now certain that this problem comes from the engine
////src/flutter/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart `DomElement _createDomElement() { final DomElement rootElement = domDocument.createElement('flt-paragraph');
// 1. Set paragraph-level styles.
final DomCSSStyleDeclaration cssStyle = rootElement.style;
cssStyle
..position = 'absolute'
// Prevent the browser from doing any line breaks in the paragraph. We want
// to have full control of the paragraph layout.
..whiteSpace = 'pre';
// 2. Append all spans to the paragraph.
for (int i = 0; i < lines.length; i++) {
// final ParagraphLine line = lines[i];
// for (final LayoutFragment fragment in line.fragments) {
// if (fragment.isPlaceholder) {
// continue;
// }
//
// final String text = fragment.getText(this);
// if (text.isEmpty) {
// continue;
// }
//
// final DomElement spanElement = domDocument.createElement('flt-span');
// if (fragment.textDirection == ui.TextDirection.rtl) {
// spanElement.setAttribute('dir', 'rtl');
// }
// applyTextStyleToElement(element: spanElement, style: fragment.style);
// _positionSpanElement(spanElement, line, fragment);
//
// spanElement.appendText(text);
// rootElement.append(spanElement);
// }
final ParagraphLine line = lines[i];
String fullText = '';
for (final LayoutFragment fragment in line.fragments) {
if (fragment.isPlaceholder) {
continue;
}
final String text = fragment.getText(this);
if (text.isEmpty) {
continue;
}
fullText += text;
}
if (line.fragments.isNotEmpty) {
final LayoutFragment firstFragment = line.fragments[0];
final DomElement spanElement = domDocument.createElement('flt-span');
if (firstFragment.textDirection == ui.TextDirection.rtl) {
spanElement.setAttribute('dir', 'rtl');
}
applyTextStyleToElement(
element: spanElement, style: firstFragment.style);
_positionSpanElement(spanElement, line, firstFragment);
spanElement.appendText(fullText);
rootElement.append(spanElement);
}
}
return rootElement;
}`
I tried to modify the above code, and the above problem can be fixed after the modification. I think the reason for the problem is that the element is created for each character separately, but some emoji are composed of multiple characters (such as the problem emoji mentioned in issue). @ Lautarourtiaga @darshankawar @ditman
Good initiative! Feel free to open a PR and link it here! Good job for finding out about it and sharing!
Good initiative! Feel free to open a PR and link it here! Good job for finding out about it and sharing!
https://github.com/flutter/engine/pull/44247 This is my first pr submission and I have some problems. I suggest that the official can only use this submission as a reference, and then modify it yourself. @ditman @darshankawar
Thanks for the thorough investigation here, and the PR! This is very good insight!
I think the reason for the problem is that the element is created for each character separately, but some emoji are composed of multiple characters (such as the problem emoji mentioned in issue).
That's called an "Emoji ZWJ Sequence". Does the issue reproduce with other ZWJ emojis? Here's a bunch of them: https://emojipedia.org/emoji-zwj-sequence/ (Other keycaps: https://emojipedia.org/emoji-keycap-sequence/)
The triaged-engine
label is irrelevant if there is no team-engine
label or fyi-engine
label.
🤔Can you solve the quiz?💰 🤖#AI got puzzled! 🎁$30 for 5 each!To win:1️⃣ FL &❤️ & RT @binary_x2⃣ Fill in the blank👇 & tag 2 friends!')
I tested a few randomly, and it can be displayed normally in the current flutter version; it can also be displayed normally in my customized version.
Is there any plan to fix this problem and merge it into the mainline? @ditman
any updates?
Nothing to share about this for now.
Here's some news about the future of the HTML renderer:
Please, comment in that issue what's preventing you from adopting the Canvaskit renderer.
PR https://github.com/flutter/engine/pull/44247 was written to solve this issue but unfortunately it was not completed so the PR has been closed. If anyone would like to start from that PR and apply the review comments and drive this PR to completion, you are definitely welcome to do so!
Is there an existing issue for this?
Steps to reproduce
1、flutter create emoji_sample 2、add code below: Text( '🤔Can you solve the quiz?💰 🤖#AI got puzzled! 🎁\$30 for 5 each!To win:1️⃣ FL &❤️ & RT @binary_x2⃣ Fill in the blank👇 & tag 2 friends!'), 3、flutter run -d chrome --web-renderer html
As shown in the picture, the emoji 1️⃣ in the red frame is not correct. 1️⃣ equals \u{0031}\u{FE0F}\u{20E3} This emoji is actually composed of two characters: the number "1" (U+0031) and a variable selector (U+FE0F), followed by a combined closed keyboard selector (U+20E3)
4、if run with --web-renderer canvaskit and set useColorEmoji: true when inital engine, the result is right.
List of known issues emoji in flutter web html rendering:
The Unicode encoding for 1️⃣ is: U+0031 (1) + U+FE0F (️ Variation Selector-16, VS-16). The Unicode encoding for 2⃣ is: U+0032 (2) + U+20E3 (⃣ Combining Enclosing Keycap).
@ditman
Expected results
Actual results
Code sample
Code sample
```dart Text( '🤔Can you solve the quiz?💰 🤖#AI got puzzled! 🎁\$30 for 5 each!To win:1️⃣ FL &❤️ & RT @binary_x2⃣ Fill in the blank👇 & tag 2 friends!'), ```Screenshots or Video
Screenshots / Video demonstration
[Upload media here]Logs
Logs
```console [Paste your logs here] ```Flutter Doctor output
Doctor output
```console [✓] Flutter (Channel stable, 3.10.2, on macOS 11.6 20G165 darwin-x64, locale zh-Hans-CN) [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 13.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2022.1) [✓] Connected device (2 available) ```