I need an emoji along with text editing support, but when I insert any emoji in the text area (no matter if via code or via clipboard) it doesn’t display at all. I tried downloading NotoColorEmoji font and setting it for the text area, but again nothing is displayed. Moreover, this font only contains emoji, so regular characters are not displayed as well.
var url = getClass().getResource("NotoColorEmoji-Regular.ttf").toExternalForm();
var ta = new TextArea("๐๐๐");
ta.setFont(Font.loadFont(url, 12));
I know about 3rd party libs, but they can’t all be used for various reasons. So, please, don’t recommend any of them.
Is there a way to get emoji support in standard text input control? Any workarounds?
UPDATE:
TL;DR: I think it’s a JavaFX bug. Some emoji fonts fully/partially cannot be rendered. Those that do only rendered as greyscale.
Environment: Ubuntu 22.04 (KDE 5.24) or Fedora 39 (KDE 5.27), JDK/JFX 21 or JDK/JFX 22 (latest)
Out-of-the-box, both Ubuntu and Fedora use the ‘Noto Color Emoji’ font, which cannot be rendered by JavaFX. Most symbols are missing.
JavaFX has own font renderer engine which reads the Linux font config settings. It’s easy to check by not closing the XML tag. You’ll get a JavaFX warning on startup.
So I downloaded all the available emoji TTF fonts and tried them out. To change the font, you need to put the TTF files in ~/.fonts
and the configuration in ~/.config/fontconfig
.
<match>
<test name="family">
<string>sans-serif</string>
</test>
<edit binding="strong" name="family" mode="prepend">
<string>Segoe UI Emoji</string>
</edit>
</match>
<match>
<test name="family">
<string>serif</string>
</test>
<edit binding="strong" name="family" mode="prepend">
<string>Segoe UI Emoji</string>
</edit>
</match>
<match>
<test name="family">
<string>monospace</string>
</test>
<edit binding="strong" name="family" mode="prepend">
<string>Segoe UI Emoji</string>
</edit>
</match>
<!-- optionally override system emoji font -->
<match>
<test name="family">
<string>Noto Emoji</string>
</test>
<edit binding="strong" name="family" mode="prepend">
<string>Segoe UI Emoji</string>
</edit>
</match>
Here is the test node:
var eta = new TextArea("""
๐ ๐ ๐ ๐ ๐ ๐
๐ ๐คฃ ๐ฅฒ ๐ฅน ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ฅฐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐คช
๐คจ ๐ง ๐ค ๐ ๐ฅธ ๐คฉ ๐ฅณ ๐โ ๐ ๐ ๐โ ๐ ๐ ๐ ๐ ๐ โน๏ธ ๐ฃ ๐ ๐ซ ๐ฉ ๐ฅบ ๐ข ๐ญ ๐ฎ ๐ค ๐
๐ก ๐คฌ ๐คฏ ๐ณ ๐ฅต ๐ฅถ ๐ฑ ๐จ ๐ฐ ๐ฅ ๐ ๐ซฃ ๐ค ๐ซก ๐ค ๐ซข ๐คญ ๐คซ ๐คฅ ๐ถ ๐ถ ๐ ๐ ๐ฌ ๐ซจ ๐ซ ๐
๐ฏ ๐ฆ ๐ง ๐ฎ ๐ฒ ๐ฅฑ ๐ด ๐คค ๐ช ๐ต ๐ต ๐ซฅ ๐ค ๐ฅด ๐คข ๐คฎ ๐คง ๐ท ๐ค ๐ค ๐ค ๐ค ๐ ๐ฟ ๐น ๐บ ๐คก
๐ฉ ๐ป ๐ ๐ฝ ๐พ ๐ค ๐ ๐บ ๐ธ ๐น ๐ป ๐ผ ๐ฝ ๐ ๐ฟ ๐พ
""");
.root {
-fx-font-family: "serif";
}
- Twitter Emoji, https://github.com/13rac1/twemoji-color-font
- Apple Emoji, https://github.com/samuelngs/apple-emoji-linux
- OpenSans Emoji, https://github.com/MorbZ/OpenSansEmoji
- Noto Emoji, https://fonts.google.com/noto/specimen/Noto+Color+Emoji
I also found a very similar bug for MacOS JDK-8290866, but unfortunately setting -Dprism.lcdtext=true
as well as changing -fx-smoothing-type
didn’t help.
And the results:
2
Answers
Likely your computer lacks a font with glyphs for those particular characters. Or you are using an older version of Java that did not support the necessary level of Unicode. Java 22 supports Unicode 15.1 per Release Notes.
To debug the situation, write a minimal app to demonstrate the problem. ๐๐ฝ Add several other characters from various parts of Unicode to see if they render.
In example below we add FACE WITH MEDICAL MASK, the King & Queen of chess, and your faces.
This example works on macOS Sonoma 14, with Java 22, and JavaFX 23-ea+22.
The content with
TextArea
:And an app to exercise that code:
Just to be clear, here is my POM.
Screenshot:
You can edit that text, as well as paste emoji.
All emoji
We can modify our example app to display all emoji characters. Designating emoji characters is the job of the Unicode Consortium.
We loop all of the million code point range in Unicode. Then we use method
Character.isEmoji
to filter. In Java 22, we find 1,424.Many more emoji are possible, by combining traits. We ignore that here, focusing on just the basics.
While I did not study extensively, in a quick scan my eye failed to notice any missing glyphs. Apple Inc. seems to have covered all the current emoji in one or more fonts bundled with macOS Sonoma 14.
By the wayโฆ We switched from
VBox
toBorderPane
to make the text field auto-expand when window stretches.Just swap out
EmojiPane
class for this version:An example to demonstrate current behavior and summarize comments, showing how various emoji fonts are handled (not a comprehensive cross-platform answer).
I only ran the example app on OS X, other OS environments may exhibit different behavior.
OS X output
Environment
Sample app
In the example app, the fonts required are downloaded dynamically at runtime, so they don’t need to be pre-downloaded and installed in the OS for you to use them. However, the drawback of this approach is that it takes a few seconds for the app to start as it gathers and initializes the fonts off of the net.
Notes
From my testing (on Mac), the color Emojis only work with the default Mac Apple Color Emoji font and Mac appears to fall back to use that if the appropriate glyphs aren’t in the requested font, but no other color fonts will work with JavaFX (they will be rendered monochrome or not at all).
If I run this code
on a Mac, it works just fine, and the emojis you have in your question display. Also copy and paste of your emojis into the text area works fine as well as editing caret positioning, selection highlighting and the delete key.
On Mac the Emojis display in color, with the default system font. The standard "command + ctrl + space" keyboard sequence will bring up an emoji input selection in most Mac apps, but not in JavaFX apps. So I am not sure how to use the keyboard to enter new emojis.
To get multicolored emoji characters, you probably need to use a color font, e.g. on Windows, you could try "Segoe UI Emoji". However, from my testing on Mac, JavaFX didn’t seem to handle color fonts (except the "Apple Color Emoji" font that ships with the OS).
I know the asker doesn’t want to use a third-party library, but for others who come across this question who do, you could consider pavlobu / emoji-text-flow-javafx, mentioned in this similar question and answer, which "allow users to use extended TextFlow to display emojis. It helps to display consistent emoji images on different platforms where JavaFX application runs."
I also tried it on Mac with the OpenSansEmoji font -> output was similar to that in the question, but (most glyphs rendered monochrome, but glyphs rendered garbled in the question were displayed in color, probably just falling back to the default Apple Emoji Font, which works). Same for Segoe UI Emoji, which renders many more black and white glyphs as shown in the question, and color default Appen Emoji Fonts for the glyphs not rendered in Segoe. Noto Color Emoji rendered blank characters on Mac.
So what that means to me is that JavaFX can only render the color emojis from the default Apple Emoji Font on a Mac, but not a custom color font. Probably there is some special fallback on Macs to use the Apple Emoji font if the current font doesn’t have the appropriate Emoji glyphs. Still, outside of that, color glyphs aren’t rendered (similar to Linux), so it is probably a cross-platform limitation of JavaFX font processing and not Linux-specific.
FAQ
I didn’t do anything to have that fallback behavior, it just seems to happen. You can see in the result that some emoji fonts are rendering monochrome for glyphs, which is coming from the emoji font. But when the emoji font does not seem to have an appropriate glyph you see color glyphs coming from the Apple emoji font.
The Noto Color Emoji font has all the glyphs, but they don’t render with JavaFX, ending up with blank text.