Graphics drawText etc do not behave properly for RTL text


#1

We've been trying to figure out why Hebrew text is drawn incorrectly in JUCE (in e.g. buttons , labels etc)

I finally figured out that 'drawText', etc simply don't work correctly.

When I replaced (in my own LookAndFeel) the call to drawText* with AttributedString draw, the text was drawn correctly.  

The manifestation of the problem is that chunks of the text will not appear, especially if there is a space (e.g. not-RTL) char inside the string.  If the text were "ABC DEF" (assuming they are RTL chars) then the output looked like "ABC D F" or some other mashup.

At first I thought there was a problem where my code was messing up the string, but printf right before the calls showed that wasn't the issue, and changing to AttributedString seems to have solved the problem. I assume a similar problem would occur with Arabic and other RTL languages.


#2

No input on this? It's becoming a bigger issue as my app progresses...  "TextEditor" doesn't show RTL text correctly at all, for instance.


#3

It's a tricky problem, especially for the TextEditor..

Creating an RTL text layout happens via some nasty use of CoreText or DirectWrite (which isn't even available on old versions of win32), but on linux/android there's not even an equivalent API. The TextEditor layout stuff doesn't use those APIs yet, and it also has to deal with cursor movement, etc, which complicates things even further. It all probably needs a bit of a serious re-think, which I don't have the bandwidth for right at the moment. I'm fully aware of the problem though!


#4

Hi again -

I agree it's a tricky problem.  Particularly if you have mixed text (e.g. LTR RTL LTR etc).

What is actually needed is to break text into runs of direction-ness, and then to draw each chunk as appropriate.  The real complication centers around cursor movement and editing, as that needs to be aware not only of the direction of the current text run, but also whether or not it's on a text-run boundary.

When you add in various fonts and so forth, it becomes an even bigger problem.  However, I would be happy if it worked for just the case where the font was uniform.  Then I would be able to allow users to enter text in Hebrew (for instance), which they can do now -- but the UX is very wrong.

I'm willing to put effort into this because I really, really need it; but I need to know from you where the best place to make the change (e.g. minimal change) is.  As I mentioned before, I was able to get correct display (in other components) by using the AttributedText, but it seems you've got a plethora of low-level font/glyph/text classes and I don't know where it's best to put the effort.


#5

Your input would be appreciated on this - hoping to have some more bandwidth soon as the juce team grows in the next month or so!


#6

Thanks, Jules.

I'm going to have my co-worker deal with this particular issue, so she'll probably be asking questions.  If you don't mind, though; where do you think the best place to apply the effort would be?  At the level of the TextEditor or below, say in the GlyphArrangement etc?


#7

The TextLayout class would be a good place to look. That's where there are different implementations that use a software layout, CoreText, DirectWrite etc.

And TextEditor itself would probably need some serious refactoring to make it more flexible too.

 


#8

From what I can see, the TextEditor does not use a TextLayout at all.


#9

No, at the moment it doesn't. But to get advanced layout info it would need to. That's why it's quite a big refactoring job to support it.


#10

Neither.

If you want to build a text editor control capable of editing Hebrew (or Arabic/Indic/etc) you need to start from scratch. There is so much complexity in Complex Text Layout that refactoring TextEditor is simply not an option.

The only multi-platform approach to creating such an editor is to utilize Harfbuzz and ICU. This is what QT and Chrome does.

I expect there would be significant pushback to making ICU and its 30MB of libraries a requirement for all Juce GUI apps. I think a compromise could be made by creating a juce internationalization (i8ln) module. This i8ln module would be an optional module which contains all il8n relevant classes like GUI controls that supported all scripts but also localization things like dates and number formats. This module would have a hard dependency on harfbuzz and ICU.

Jules is that something you'd approve of?


#11

That's a really good summary of the problem!

I did look into things like harfbuzz a couple of years ago, but they're just ridiculously huge - adding support for it would double or triple the size of most binaries that people build!

But yes, adding some kind of i8ln layer would be the smart approach - so that it can use a simple back-end that only handles LTR text if you don't need anything beyond that, but being able to swap it out for a more capable back-end in apps where that's necessary. It's a huge task, but is on our radar!


Suggestion on supporting unicode and Complex Text Layout
#12

RTL and BiDi seems to be completely off with JUCE.
While for plug-ins this is understandable, for “apps” aka Mobile frameworks this is a huge drawback :frowning:

JUCE becomes/became a greater player in cross-platform C++ development.

Currently I see inconsistencies even on basic texts under Android/Apple/Microsoft
I don’t expect a fully blown Text Editor but I guess most would expect basic user definable text to be written properly or at least provide exact same experience across all platforms.


#13

נכון מאד

It’s a problem I’ve been dealing with off and on, in 8th (which uses JUCE for x-platform UI).

The problems is worse by far on Linux.