Showing RTL text in a TextButton


#1

Hi all,

As I continue my journey into JUCE, I am attempting to get my sample code running.

I noticed that one of my buttons was displaying empty squares, and I fixed that by overriding "getFont()" so the Hebrew text displays.

However, it is drawn left-to-right, and I cannot find any way to tell the TextButton it should render right-to-left.  Is there something I'm missing?

I did see the discussions on the text rendering system, but those are all several years old.  

How can I best accomplish RTL drawing of my TextButton labels?  Note that Hebrew doesn't need glyph reforming like some other languages do, it just needs mirrored text display.


#2

There are a couple of different mechanisms in there for drawing text, but RTL can only be done by using AttributedString and using the OS layout mechanisms. I thought that was used by TextButton, but I could be wrong.. If not, it'd be simple enough to implement your own LookAndFeel::drawButtonText method


#3

I created my own "LookAndFeel" and overrode the "drawButtonText".   I verified that my code is indeed called, but the text is still not drawing RTL.

Is the following code (mostly lifted from the V2 code) correct?  Because it doesn't actually work:


void LookAndFeel_8::drawButtonText (Graphics& g, TextButton& button, bool , bool ) 
{
    Font font (getTextButtonFont (button));
    g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
                                                            : TextButton::textColourOffId)
                       .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));
    const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2;
    const int fontHeight = roundToInt (font.getHeight() * 0.6f);
    const int leftIndent  = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2));
    const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2));
    String str = button.getButtonText();
    AttributedString astr(str);
    astr.setFont(font);
    astr.setJustification(Justification::centred);
    juce_wchar wch = str[0];
    if (wch >= 0x05d0 && wch <= 0x5ea)
    {
        // Hebrew, so rtl
        astr.setReadingDirection(juce::AttributedString::rightToLeft);
    }
    Rectangle<float> rect(leftIndent, 0, button.getWidth() - leftIndent - rightIndent, button.getHeight());
    astr.draw(g, rect);
}

#4

What platform are you using? On some OS versions the unicode text layout calls aren't available. e.g. check that JUCE_USE_DIRECTWRITE isn't disabled.


#5

I'm using 64-bit Linux


#6

Ah, well that would explain it. Linux doesn't provide an API for unicode text support!


#7

pango has been around for quite a while.


#8

Also, libicu is cross-platform and with a bit more work can do the job, I think.


#9

Yeah, I researched this when I added RTL support for Windows and OSX, and found there were a ton of bloated and not-very-good unicode handling libraries, all of which had horrible dependency chains, and none of which were integrated with any actual typeface handling, so would all have been a total nightmare to implement.

The landscape may have improved now, but back then it sounded like everyone was struggling with the same problem, even the browsers didn't have a good solution.

I'd love to offer to make it work, but it'd take at days if not weeks of effort, which I can't spare right now..


#10

Understood.  I'll defer dealing with this until later, since there are more critical issues I need to address before I can use JUCE for my application.

Though I will say the entire point for me is to have identical (or nearly so) GUI across platforms.  If it looks one way on Windows and another on Linux, that's not good...

thanks