RFR: 8269806: Emoji rendering on Linux [v20]
Nikita Gubarkov
ngubarkov at openjdk.org
Sat Oct 7 16:58:22 UTC 2023
On Wed, 5 Apr 2023 14:31:34 GMT, Nikita Gubarkov <ngubarkov at openjdk.org> wrote:
>> It was implemented in JetBrains Runtime a year ago and was ported & refactored for this PR
>> It includes:
>> - Bitmap glyph loading via Freetype
>> - Manual scaling & transformation of bitmap glyphs with nearest-neighbor or bilinear-mipmap style algorithms depending on the text antialiasing hint
>> - Storing BGRA glyphs in glyph cache & rendering them as plain images, as currently used XRender text drawing functions doesn't support colored glyphs
>> - Small fixes in related code like null-checks which could cause NPE & comment typos
>
> Nikita Gubarkov has updated the pull request incrementally with one additional commit since the last revision:
>
> EmojiFont CRLF -> LF
I thought we are on the same page with this, but I will try to explain my idea.
We have two PhysicalFonts for mono end colored emoji. Inside fallback sequence we want them to be preferred over one another depending on specific glyph and variation selector used. This is necessary to support emoji and VS the *proper* way. Cheating and using only colored font, forcing monochrome presentation in certain cases is an option, but out of topic. In short: it would require a bunch of new hacks, which we are trying to get rid of, while the result looking not quite how user would expect.
Current CompositeFont implementation is strictly linear - all component fonts are tried in sequence, all must be PhysicalFonts (which is an artificial limitation). Anyway, current implementation doesn't permit the desired behavior (leaving aside hacks with exclusion ranges, which are ignored in presence of VS).
Natural solution to achieve what we want is to encapsulate our two PhysicalFonts into single virtual emoji font. However then it wouldn't be a PhysicalFont and therefore cannot be used inside CompositeFont. I want to emphasise this - the problem is not with emoji font, but with CompositeFont. Being able to put arbitrary Font2D into CompositeFont is completely logical and legitimate, the restriction is artificial.
CompositeFont is too limited for the job, but it can be fixed - the only thing preventing CompositeFont from being able to contain Font2Ds is generally non-bijective mapping of glyph codes. CompositeFont goes easy way and encodes slot index in high byte, leaving others for original glyph code (essentially sequential indices). Of course nesting CompositeFonts would encode slot index into already used high byte, breaking the thing. My solution is to encode glyph codes in such way, that slot index is always inserted in low bits, shifting the original code, thus being able to recursively "wrap" glyph codes (unless we overflow, but we currently don't handle such case anyway).
I personally don't see anything bad with it being implemented "just for emoji", because changes to CompositeFont have nothing to do with emoji - it's just a generalization to cover more usage scenaros. I don't know who else could need such complex fallback approaches, but they would at least be possible now. There is one thing which I considered while implementing this though - sometimes users want to configure font fallback behavior, it would be very nice to allow them to construct custom fallback chains (trees, whatever), which would require some refactoring to CompositeFont, and this change is a small step in that direction too.
Finally, I understand your concerns that such changes are risky, but the tests are green and changes are battle-tested in JBR, for example, Linux users of JetBrains products are enjoying emoji for around 3 years already 😀 I keep this PR in sync and include all fixed bugs and regressions, of course.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/4798#issuecomment-1751769222
More information about the client-libs-dev
mailing list