diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 686e8f5327e85..c133cf2b30a00 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -618,7 +618,9 @@ extends Layout * - is class HY: a breakpoint * except when followed by a digit. * - * Ideographs are class ID: breakpoints when adjacent. + * Ideographs are class ID: breakpoints when adjacent, + * except for NS (non-starters), which can be broken + * after but not before. */ if (c == ' ' || c == '\t' || @@ -627,8 +629,8 @@ extends Layout (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || ((c == '/' || c == '-') && (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || - (c >= FIRST_CJK && isIdeographic(c) && - j + 1 < next && isIdeographic(chs[j + 1 - start]))) { + (c >= FIRST_CJK && isIdeographic(c, true) && + j + 1 < next && isIdeographic(chs[j + 1 - start], false))) { okwidth = w; ok = j + 1; @@ -807,8 +809,12 @@ extends Layout * as being Ideographic (class ID) by the Unicode Line Breaking Algorithm * (http://www.unicode.org/unicode/reports/tr14/), and is therefore OK * to break between a pair of. + * + * @param includeNonStarters also return true for category NS + * (non-starters), which can be broken + * after but not before. */ - private static final boolean isIdeographic(char c) { + private static final boolean isIdeographic(char c, boolean includeNonStarters) { if (c >= '\u2E80' && c <= '\u2FFF') { return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS } @@ -816,9 +822,52 @@ extends Layout return true; // IDEOGRAPHIC SPACE } if (c >= '\u3040' && c <= '\u309F') { + if (!includeNonStarters) { + switch (c) { + case '\u3041': // # HIRAGANA LETTER SMALL A + case '\u3043': // # HIRAGANA LETTER SMALL I + case '\u3045': // # HIRAGANA LETTER SMALL U + case '\u3047': // # HIRAGANA LETTER SMALL E + case '\u3049': // # HIRAGANA LETTER SMALL O + case '\u3063': // # HIRAGANA LETTER SMALL TU + case '\u3083': // # HIRAGANA LETTER SMALL YA + case '\u3085': // # HIRAGANA LETTER SMALL YU + case '\u3087': // # HIRAGANA LETTER SMALL YO + case '\u308E': // # HIRAGANA LETTER SMALL WA + case '\u3095': // # HIRAGANA LETTER SMALL KA + case '\u3096': // # HIRAGANA LETTER SMALL KE + case '\u309B': // # KATAKANA-HIRAGANA VOICED SOUND MARK + case '\u309C': // # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + case '\u309D': // # HIRAGANA ITERATION MARK + case '\u309E': // # HIRAGANA VOICED ITERATION MARK + return false; + } + } return true; // Hiragana (except small characters) } if (c >= '\u30A0' && c <= '\u30FF') { + if (!includeNonStarters) { + switch (c) { + case '\u30A0': // # KATAKANA-HIRAGANA DOUBLE HYPHEN + case '\u30A1': // # KATAKANA LETTER SMALL A + case '\u30A3': // # KATAKANA LETTER SMALL I + case '\u30A5': // # KATAKANA LETTER SMALL U + case '\u30A7': // # KATAKANA LETTER SMALL E + case '\u30A9': // # KATAKANA LETTER SMALL O + case '\u30C3': // # KATAKANA LETTER SMALL TU + case '\u30E3': // # KATAKANA LETTER SMALL YA + case '\u30E5': // # KATAKANA LETTER SMALL YU + case '\u30E7': // # KATAKANA LETTER SMALL YO + case '\u30EE': // # KATAKANA LETTER SMALL WA + case '\u30F5': // # KATAKANA LETTER SMALL KA + case '\u30F6': // # KATAKANA LETTER SMALL KE + case '\u30FB': // # KATAKANA MIDDLE DOT + case '\u30FC': // # KATAKANA-HIRAGANA PROLONGED SOUND MARK + case '\u30FD': // # KATAKANA ITERATION MARK + case '\u30FE': // # KATAKANA VOICED ITERATION MARK + return false; + } + } return true; // Katakana (except small characters) } if (c >= '\u3400' && c <= '\u4DB5') {