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

Commit ce93f310 authored by Roozbeh Pournader's avatar Roozbeh Pournader
Browse files

Override bidi property of new emojis

In BidiFormatter and AndroidBidi, treat emojis new to
Unicode 10.0/Emoji 5 as bidi class ON.

Test: Manual
Bug: 32952475
Change-Id: I1a40c6ee2b6e9d91c9d1e5b64faca6d16301fe93
parent fb2f7e27
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -592,10 +592,21 @@ public final class BidiFormatter {
        static {
            DIR_TYPE_CACHE = new byte[DIR_TYPE_CACHE_SIZE];
            for (int i = 0; i < DIR_TYPE_CACHE_SIZE; i++) {
                // Calling Character.getDirectionality() is OK here, since new emojis start after
                // the end of our cache.
                DIR_TYPE_CACHE[i] = Character.getDirectionality(i);
            }
        }

        private static byte getDirectionality(int codePoint) {
            if (Emoji.isNewEmoji(codePoint)) {
                // TODO: Fix or remove once emoji-data.text 5.0 is in ICU or update to 6.0.
                return Character.DIRECTIONALITY_OTHER_NEUTRALS;
            } else {
                return Character.getDirectionality(codePoint);
            }
        }

        // Internal instance variables.

        /**
@@ -809,7 +820,7 @@ public final class BidiFormatter {
         * cache.
         */
        private static byte getCachedDirectionality(char c) {
            return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : Character.getDirectionality(c);
            return c < DIR_TYPE_CACHE_SIZE ? DIR_TYPE_CACHE[c] : getDirectionality(c);
        }

        /**
@@ -826,7 +837,7 @@ public final class BidiFormatter {
            if (Character.isHighSurrogate(lastChar)) {
                int codePoint = Character.codePointAt(text, charIndex);
                charIndex += Character.charCount(codePoint);
                return Character.getDirectionality(codePoint);
                return getDirectionality(codePoint);
            }
            charIndex++;
            byte dirType = getCachedDirectionality(lastChar);
@@ -856,7 +867,7 @@ public final class BidiFormatter {
            if (Character.isLowSurrogate(lastChar)) {
                int codePoint = Character.codePointBefore(text, charIndex);
                charIndex -= Character.charCount(codePoint);
                return Character.getDirectionality(codePoint);
                return getDirectionality(codePoint);
            }
            charIndex--;
            byte dirType = getCachedDirectionality(lastChar);
+17 −7
Original line number Diff line number Diff line
@@ -65,22 +65,32 @@ public class Emoji {
        return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER_BASE);
    }

    // Returns true if the character has Emoji property.
    public static boolean isEmoji(int codePoint) {
    /**
     * Returns true if the character is a new emoji still not supported in our version of ICU.
     */
    public static boolean isNewEmoji(int codePoint) {
        // Emoji characters new in Unicode emoji 5.0.
        // From http://www.unicode.org/Public/emoji/5.0/emoji-data.txt
        // TODO: Remove once emoji-data.text 5.0 is in ICU or update to 6.0.
        if ((0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
        if (codePoint < 0x1F6F7 || codePoint > 0x1F9E6) {
            // Optimization for characters outside the new emoji range.
            return false;
        }
        return (0x1F6F7 <= codePoint && codePoint <= 0x1F6F8)
                || codePoint == 0x1F91F
                || (0x1F928 <= codePoint && codePoint <= 0x1F92F)
                || (0x1F931 <= codePoint && codePoint <= 0x1F932)
                || codePoint == 0x1F94C
                || (0x1F95F <= codePoint && codePoint <= 0x1F96B)
                || (0x1F992 <= codePoint && codePoint <= 0x1F997)
                || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6)) {
            return true;
                || (0x1F9D0 <= codePoint && codePoint <= 0x1F9E6);
    }
        return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);

    /**
     * Returns true if the character has Emoji property.
     */
    public static boolean isEmoji(int codePoint) {
        return isNewEmoji(codePoint) || UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
    }

    // Returns true if the character can be a base character of COMBINING ENCLOSING KEYCAP.
+4 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "utils/misc.h"
#include "utils/Log.h"
#include "unicode/ubidi.h"
#include <minikin/Emoji.h>

namespace android {

@@ -38,6 +39,9 @@ static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
        if (info != NULL) {
            UErrorCode status = U_ZERO_ERROR;
            UBiDi* bidi = ubidi_openSized(n, 0, &status);
            // Set callbacks to override bidi classes of new emoji
            ubidi_setClassCallback(
                    bidi, minikin::emojiBidiOverride, nullptr, nullptr, nullptr, &status);
            ubidi_setPara(bidi, chs, n, dir, NULL, &status);
            if (U_SUCCESS(status)) {
                for (int i = 0; i < n; ++i) {