Issue with glyphs in Devanagari (Unicode)

There seems to be a glitch in the display of Devanagari (Indian) symbols on Mac (on Windows, it’s anyway not developed). You can reproduce with the following code over a displayed component:

void MainComponent::paint (juce::Graphics& g)
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));

g.setFont (juce::Font ("Poppins", 16.f, juce::Font::plain ));
g.setColour (juce::Colours::white);

int line = 1;

g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 5 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);
g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 25 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);
g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 45 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);
g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 65 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);
g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 85 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);
g.drawText (juce::CharPointer_UTF8 ("प्रत्येक 105 क्षण"), 10, ++line * 30, getWidth() - 10, 30, juce::Justification::centredLeft, true);

}

Only the last line (105) displays as intended. On the others, the final word is truncated.

I have tried debugging it, but have reached my limits at some point in the code…

Thanks for your help.

Ok, I was able to find the issue. It’s in juce_GlyphArrangement.cpp, in the addCurtailedLineOfText() method.

In a language like Devanagari (Sanskrit), some characters get combined into a single one. Here we have a desynchronisation between the text argument that contains ALL individual characters, and the newGlyphs array that contains the COMBINED ones.

We rightly display the combined characters in newGlyphs, but simultaneously increment the text argument to determine when there is a space. This means some correct characters are flagged as whitespace, and therefore don’t display.

I have been able to apply a quick fix as follows:

    auto t = text.getCharPointer();
    
    bool charsInSync = (text.length() == textLen); << ADDED

    for (int i = 0; i < textLen; ++i)
    {
        auto nextX = xOffsets.getUnchecked (i + 1);

        if (nextX > maxWidthPixels + 1.0f)
        {
            // curtail the string if it's too wide..
            if (useEllipsis && textLen > 3 && glyphs.size() >= 3)
                insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size());

            break;
        }

        auto thisX = xOffsets.getUnchecked (i);
        auto isWhitespace = charsInSync && (isNonBreakingSpace (*t) || t.isWhitespace()); << UPDATED

        glyphs.add (PositionedGlyph (font, t.getAndAdvance(),
                                     newGlyphs.getUnchecked(i),
                                     xOffset + thisX, yOffset,
                                     nextX - thisX, isWhitespace));
    }

It seems that even with isWhitespace at FALSE, the whitespace characters display fine (since the glyph is a space), so it’s all good now.

I hope the JUCE team can look into this and publish a better fix.

Hey!

The current Unicode work will address this. Sorry it’s taking so long, it’s a mammoth task!

There’s no simple way to fix just this issue without potentially breaking other scripts.

Oli

Oh, great to hear there is an ongoing development for this. Hopefully it will work on Windows as well.

I understand, it must be an insane amount of work.

In the meantime, do you see any big issue with my fix? Should work as before on normal English, and only be applied of scripts like Devanagari, right?

@oli1 - is that also going to fix this issue? It sounds like the same problem perhaps.

Possibly. Looks like a similar issue.

ongoing development

Apologies in advance if this is thread-hijacking, but would there be a chance that we might be able to use glyphs in JUCE, a la FF Chartwell and other such ligature-packed fonts?

Because if so, that would be an astounding step forward for high-performance UI’s, just sayin’ …

EDIT: its kind of an opportunity:

Yes, it should fix most of the outstanding font/text related issues :slight_smile:

This might work as-is with the new Unicode work, but I don’t think we will add any specialization for it.

Understood. Ligatures are a very nice way of indicating parameter values; you can call any dial or knob out for its ligatures. And also:font path is optimal shader path on most platforms…