RFR: 8290866: Apple Color Emoji turns gray after JavaFX version 18

Kevin Rushforth kcr at openjdk.org
Fri Feb 24 19:31:24 UTC 2023


On Thu, 23 Feb 2023 20:43:29 GMT, Phil Race <prr at openjdk.org> wrote:

> This fix properly supports colour rendering of Emoji on macOS
> 
> 
> On other platforms the Emoji will be rendered as ordinary greyscale glyphs - if there is font
> support for the requested code point.
> 
> A simple manual test is provided which uses a Text node, Label control
> and editable TextField control.
> 
> Some highlights of the code
> - To determine if it is a color emoji glyph probe the 'sbix' font table which is what is used by Apple
> - Text runs now break at an Emoji glyph
> - The Emoji is retrieved as an BGRA image - ie 4 channel including alpha
> - It was necessary to retrieve the Emoji glyph bounds via a different CoreText API since
>    the bounds that were being retrieved were wrong for the Emoji image - causing clipping
> - It was necessary to retrieve the Emoji code point advance via a CoreText API since
>    the HMTX metrics were very wrong - causing overlapping glyphs
> - drawString checks if it is an Emoji run and redirects to a new drawColorGlyph method
>    which draws the image as a texture
> - All 3 rendering pipelines have this support and have been verified on all 3 desktop platforms

My testing all looks good. Since all of the changes for the shader-based pipelines are in BaseShaderGraphics, I decided it might be interesting to try this with the metal pipeline (from the `jfx-sandbox:metal` branch). And... it just worked!

I did a partial code review (I'll finish this afternoon) and left a few comments and questions.

modules/javafx.graphics/src/main/java/com/sun/javafx/font/PrismFontFile.java line 1182:

> 1180: 
> 1181: 
> 1182:     public float getAdvance(int glyphCode, float ptSize) {

Did you mean to remove the `@Override` for this method?

modules/javafx.graphics/src/main/java/com/sun/javafx/font/PrismFontFile.java line 1184:

> 1182:     public float getAdvance(int glyphCode, float ptSize) {
> 1183:         if (glyphCode == CharToGlyphMapper.INVISIBLE_GLYPH_ID)
> 1184:             return 0f;

Please surround with curly braces.

modules/javafx.graphics/src/main/java/com/sun/javafx/font/PrismFontFile.java line 1430:

> 1428: 
> 1429:    private static int USHORT_MASK = 0xffff;
> 1430:    private static int UINT_MASK   = 0xffffffff;

Minor: can be final.

modules/javafx.graphics/src/main/java/com/sun/javafx/font/PrismFontFile.java line 1448:

> 1446:               return false;
> 1447:            }
> 1448:            return dataOffsets[gid] < dataOffsets[gid+1];

If `gid` is equal to `dataOffsets.length - 1`, won't this throw AIOOBE?

modules/javafx.graphics/src/main/java/com/sun/javafx/font/PrismFontFile.java line 1456:

> 1454:    private boolean isSbixGlyph(int glyphID) {
> 1455:        if (sbixStrikes == null) {
> 1456:            synchronized (this) {

This looks like a double-checked locking pattern, which is not guaranteed to be thread-safe.

Suggestion: move the `synchronized` before the `if`.

modules/javafx.graphics/src/main/java/com/sun/javafx/font/coretext/CTGlyph.java line 90:

> 88: 
> 89:         if (drawShapes) return;
> 90: 

Just curious: do you know why this test was there in the first place? And why it needs to be removed?

-------------

PR: https://git.openjdk.org/jfx/pull/1047


More information about the openjfx-dev mailing list