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

Commit c1463ecc authored by Victor Chang's avatar Victor Chang
Browse files

Fix max directionality in AndroidCharacter.getDirectionalities

U_CHAR_DIRECTION_COUNT has been used for boundary check for conversion
of directionality between ICU and Libcore.
However, the max directionality in ICU has been incresed from 18 to 22 since Unicode 6.3
https://github.com/unicode-org/icu/commit/2982958b06e#diff-c46912f650de1f607d39dd8d81fb4b57

But the max directionality has not been chagned in libcore, and thus it
will return undefined value in directionality_map.

Also, this commit also replaces @Deprecated API U_EA_COUNT
by u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH).

Bug: 120073244
Bug: 117094880
Test: AndroidCharacterTest
Change-Id: I39918bdd4b06d0f1e95ad923594a28a0afc82b9e
parent fb9335b8
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -25,9 +25,10 @@
#include "unicode/uchar.h"

#define PROPERTY_UNDEFINED (-1)
#define JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY 18

// ICU => JDK mapping
static int directionality_map[U_CHAR_DIRECTION_COUNT] = {
static int directionality_map[JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY + 1] = {
    0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0)
    1, // U_RIGHT_TO_LEFT (1) => DIRECTIONALITY_RIGHT_TO_LEFT (1)
    3, // U_EUROPEAN_NUMBER (2) => DIRECTIONALITY_EUROPEAN_NUMBER (3)
@@ -75,7 +76,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
            int c = 0x00010000 + ((src[i] - 0xD800) << 10) +
                                 (src[i + 1] & 0x3FF);
            int dir = u_charDirection(c);
            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
            if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY)
                dir = PROPERTY_UNDEFINED;
            else
                dir = directionality_map[dir];
@@ -85,7 +86,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
        } else {
            int c = src[i];
            int dir = u_charDirection(c);
            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
            if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY)
                dest[i] = PROPERTY_UNDEFINED;
            else
                dest[i] = directionality_map[dir];
@@ -96,7 +97,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input)
{
    int width = u_getIntPropertyValue(input, UCHAR_EAST_ASIAN_WIDTH);
    if (width < 0 || width >= U_EA_COUNT)
    if (width < 0 || width > u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH))
        width = PROPERTY_UNDEFINED;

    return width;
@@ -121,6 +122,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
        return;
    }

    int maxWidth = u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH);
    for (int i = 0; i < count; i++) {
        const int srci = start + i;
        if (src[srci] >= 0xD800 && src[srci] <= 0xDBFF &&
@@ -129,7 +131,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
            int c = 0x00010000 + ((src[srci] - 0xD800) << 10) +
                                 (src[srci + 1] & 0x3FF);
            int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
            if (width < 0 || width >= U_EA_COUNT)
            if (width < 0 || width > maxWidth)
                width = PROPERTY_UNDEFINED;

            dest[i++] = width;
@@ -137,7 +139,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
        } else {
            int c = src[srci];
            int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
            if (width < 0 || width >= U_EA_COUNT)
            if (width < 0 || width > maxWidth)
                width = PROPERTY_UNDEFINED;

            dest[i] = width;
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,d
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import static org.junit.Assert.assertArrayEquals;

import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;

import org.junit.Test;

@Presubmit
@SmallTest
public class AndroidCharacterTest {

    @Test
    public void testGetDirectionalities_nonSupplementaryCharacters() {
        int size = Character.MAX_VALUE + 1
                - (Character.MAX_SURROGATE - Character.MIN_SURROGATE + 1);
        char[] chars = new char[size];
        byte[] java_lang_results = new byte[size];
        int index = 0;
        for (int cp = 0; cp <= Character.MAX_VALUE; cp++) {
            // Exempt unassigned code point due to b/120074586
            if (Character.getType(cp) != Character.UNASSIGNED) {
                if (cp < Character.MIN_SURROGATE || cp > Character.MAX_SURROGATE) {
                    chars[index] = (char) cp;
                    java_lang_results[index] = Character.getDirectionality(cp);
                    index++;
                }
            }
        }

        byte[] android_text_results = new byte[size];
        AndroidCharacter.getDirectionalities(chars, android_text_results, index);
        assertArrayEquals(java_lang_results, android_text_results);
    }

    @Test
    public void testGetDirectionalities_supplementaryCharacters() {
        int maxNumberOfChars = Character.MAX_CODE_POINT - Character.MIN_SUPPLEMENTARY_CODE_POINT
                + 1;
        int size = maxNumberOfChars * 2;
        char[] chars = new char[size];
        byte[] java_lang_results = new byte[size];
        int index = 0;
        for (int cp = Character.MIN_SUPPLEMENTARY_CODE_POINT; cp <= Character.MAX_CODE_POINT;
                cp++) {
            // Exempt unassigned code point due to b/120074586
            if (Character.getType(cp) != Character.UNASSIGNED) {
                chars[index] = Character.highSurrogate(cp);
                chars[index + 1] = Character.lowSurrogate(cp);
                java_lang_results[index] = java_lang_results[index + 1] = Character
                        .getDirectionality(cp);
                index += 2;
            }
        }

        byte[] android_text_results = new byte[size];
        AndroidCharacter.getDirectionalities(chars, android_text_results, index);
        assertArrayEquals(java_lang_results, android_text_results);
    }
}