mikke89/RmlUi

Current HarfBuzz sample is not able to render emojis

Closed this issue · 6 comments

Hey there,
Been messing around with RmlUi and HarfBuzz lately and realized you have a sample for it, after checking it, I realized it's not able to render emojis, I've taken code for loading fonts from IME sample, basically using seguiemj.ttf, and fails to render.

I commented the line setting custom font renderer and it works perfectly fine, but loses the ability to reshape glyphs for languages like Arabic

Edit: After digging a little bit I realized there's no fallback implementation in HarfBuzz sample, so that's the reason behind it

Thanks for reporting, sounds indeed like a feature that's just not been implemented into our harfbuzz font engine.

@LucidSigma Perhaps something you might want to take a look at?

I forewent adding fallback fonts to the HarfBuzz sample since the initial goal of the HarfBuzz sample was to determine how feasibly HarfBuzz could be implemented into RmlUi's text engine system.

Implementing fallback fonts shouldn't be too much of an issue. The best way to implement it would be to add a lookup table to each font that maps characters to fallback glyph bitmaps for each character that the font doesn't support, and to populate this table when HarfBuzz returns a glyph index of zero. I've implemented a similar system in my own text renderer. I'll have a go at adding it to the text-shaping sample when I have a free time slot.

There's also another issue with the HarfBuzz sample where it still uses FreeType's advance and kerning for letter spacing (instead of HarfBuzz's). However, this should be a simple fix. I'll amend this when I implement the fallback fonts.

I ended up having a few hours of spare time so I went ahead and implemented fallback fonts into the HarfBuzz sample. It ended up being a bit more complex than I thought, and there are still a few more things I need to fix/refactor, but it's nearly done. Hopefully, I should have a pull request done within the next few days.

I'll fix the aforementioned kerning issue once this is merged.

Fallback emojis in HarfBuzz sample.

Awesome! Thanks a lot for looking into this, and the result looks great. Looking forward the the PR.

That's great! I did an attempt myself but it involved passing character to FontFaceHandlerHarfBuzz::GetOrAppendGlyph as an alternative when glyph index wasn't available (or equal to 0) to perform finding it in fallback fonts and the rest is just like the default font engine; But obviously isn't the best solution I guess.

There's also something else bothering me as in by default it shouldn't be like this but in this sample it is. With fallback fonts GenerateString is still designed in a way to use internally stored font face (hb_font) for HarfBuzz, therefore if you mix English and Arabic texts it's not going to reshape them and I can't think of a good performant way of doing this.

I've created the pull request (#635); let me know what you think.

Regarding having mixed-language strings, I think the best way to handle them right now would be to create elements programmatically using the Unicode bidirectional algorithm, such as one implemented in SheenBidi.

For example, you could execute the bidirectional algorithm on the initial string, and then for each “run” (videlicet, each segment of a line that flows in a certain direction) that goes against the parent element's language/direction, you could create a sub-element with the segment's text and apply appropriate localisation attributes and styles. You could use some HarfBuzz functionality, such as hb-buffer-guess-segment-properties, to assist with determining the properties of the segment's text.

That being said, I do believe that RmlUi could benefit from some overrideable functions for such bidirectional text processing to help streamline the process (including a way where you don't need to create new sub-elements).