Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab8c7388 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio
Browse files

Fix bug #5929529 Parentheses aren't correctly rendered in RTL context

- do BiDi mirrored char mirroring in TextLayoutCache
- see BiDi mirrored chars list at:

 http://www.unicode.org/Public/6.0.0/ucd/extracted/DerivedBinaryProperties.txt

Change-Id: Ia0af0e252dbb0c55cc689bc9db34e05591bb6ee8
parent cf0c7d10
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ namespace android {

ANDROID_SINGLETON_STATIC_INSTANCE(TextLayoutEngine);

static KeyedVector<UChar, UChar> gBidiMirrored;

//--------------------------------------------------------------------------------------------------

TextLayoutCache::TextLayoutCache(TextLayoutShaper* shaper) :
@@ -350,6 +352,23 @@ TextLayoutShaper::TextLayoutShaper() : mShaperItemGlyphArraySize(0) {

    mShaperItem.font = &mFontRec;
    mShaperItem.font->userData = &mShapingPaint;

    // Fill the BiDi mirrored chars map
    // See: http://www.unicode.org/Public/6.0.0/ucd/extracted/DerivedBinaryProperties.txt
    gBidiMirrored.add('(', ')');
    gBidiMirrored.add(')', '(');
    gBidiMirrored.add('[', ']');
    gBidiMirrored.add(']', '[');
    gBidiMirrored.add('{', '}');
    gBidiMirrored.add('}', '{');
    gBidiMirrored.add('<', '>');
    gBidiMirrored.add('>', '<');
    gBidiMirrored.add(0x00ab, 0x00bb); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
    gBidiMirrored.add(0x00bb, 0x00ab); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
    gBidiMirrored.add(0x2039, 0x203a); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
    gBidiMirrored.add(0x203a, 0x2039); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
    gBidiMirrored.add(0x2264, 0x2265); // LESS-THAN OR EQUAL TO
    gBidiMirrored.add(0x2265, 0x2264); // GREATER-THAN OR EQUAL TO
}

TextLayoutShaper::~TextLayoutShaper() {
@@ -577,6 +596,31 @@ void TextLayoutShaper::computeRunValues(const SkPaint* paint, const UChar* chars
        }
    }

    // Reverse "BiDi mirrored chars" in RTL mode only
    // See: http://www.unicode.org/Public/6.0.0/ucd/extracted/DerivedBinaryProperties.txt
    // This is a workaround because Harfbuzz is not able to do mirroring in all cases and
    // script-run splitting with Harfbuzz is splitting on parenthesis
    if (isRTL) {
        for (ssize_t i = 0; i < ssize_t(count); i++) {
            UChar ch = chars[i];
            ssize_t index = gBidiMirrored.indexOfKey(ch);
            // Skip non "BiDi mirrored" chars
            if (index < 0) {
                continue;
            }
            if (!useNormalizedString) {
                useNormalizedString = true;
                mNormalizedString.setTo(false /* not terminated*/, chars, count);
            }
            UChar result = gBidiMirrored.valueAt(index);
            mNormalizedString.setCharAt(i, result);
#if DEBUG_GLYPHS
            ALOGD("Rewriting codepoint '%d' to '%d' at position %d",
                    ch, mNormalizedString[i], int(i));
#endif
        }
    }

#if DEBUG_GLYPHS
    if (useNormalizedString) {
        ALOGD("Will use normalized string '%s', length = %d",