diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/text/StaticLayout.java | 123 |
1 files changed, 106 insertions, 17 deletions
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 3aad4aae7160..814326c3ba3f 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -161,9 +161,6 @@ public class StaticLayout extends Layout { float spacingadd, boolean includepad, boolean trackpad, float ellipsizedWidth, TextUtils.TruncateAt ellipsize) { - int[] breakOpp = null; - final String localeLanguageTag = paint.getTextLocale().toLanguageTag(); - mLineCount = 0; int v = 0; @@ -178,6 +175,8 @@ public class StaticLayout extends Layout { if (source instanceof Spanned) spanned = (Spanned) source; + int DEFAULT_DIR = DIR_LEFT_TO_RIGHT; // XXX + int paraEnd; for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); @@ -244,9 +243,6 @@ public class StaticLayout extends Layout { int dir = measured.mDir; boolean easy = measured.mEasy; - breakOpp = nLineBreakOpportunities(localeLanguageTag, chs, paraEnd - paraStart, breakOpp); - int breakOppIndex = 0; - int width = firstWidth; float w = 0; @@ -359,12 +355,15 @@ public class StaticLayout extends Layout { if (fmBottom > fitBottom) fitBottom = fmBottom; - while (breakOpp[breakOppIndex] != -1 - && breakOpp[breakOppIndex] < j - paraStart + 1) { - breakOppIndex++; - } - boolean isLineBreak = breakOppIndex < breakOpp.length && - breakOpp[breakOppIndex] == j - paraStart + 1; + // From the Unicode Line Breaking Algorithm (at least approximately) + boolean isLineBreak = isSpaceOrTab || + // / is class SY and - is class HY, except when followed by a digit + ((c == CHAR_SLASH || c == CHAR_HYPHEN) && + (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) || + // Ideographs are class ID: breakpoints when adjacent, except for NS + // (non-starters), which can be broken after but not before + (c >= CHAR_FIRST_CJK && isIdeographic(c, true) && + j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false)); if (isLineBreak) { okWidth = w; @@ -492,6 +491,97 @@ public class StaticLayout extends Layout { } } + /** + * Returns true if the specified character is one of those specified + * 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, boolean includeNonStarters) { + if (c >= '\u2E80' && c <= '\u2FFF') { + return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS + } + if (c == '\u3000') { + 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') { + return true; // CJK UNIFIED IDEOGRAPHS EXTENSION A + } + if (c >= '\u4E00' && c <= '\u9FBB') { + return true; // CJK UNIFIED IDEOGRAPHS + } + if (c >= '\uF900' && c <= '\uFAD9') { + return true; // CJK COMPATIBILITY IDEOGRAPHS + } + if (c >= '\uA000' && c <= '\uA48F') { + return true; // YI SYLLABLES + } + if (c >= '\uA490' && c <= '\uA4CF') { + return true; // YI RADICALS + } + if (c >= '\uFE62' && c <= '\uFE66') { + return true; // SMALL PLUS SIGN to SMALL EQUALS SIGN + } + if (c >= '\uFF10' && c <= '\uFF19') { + return true; // WIDE DIGITS + } + + return false; + } + private int out(CharSequence text, int start, int end, int above, int below, int top, int bottom, int v, float spacingmult, float spacingadd, @@ -840,11 +930,6 @@ public class StaticLayout extends Layout { mMeasured = MeasuredText.recycle(mMeasured); } - // returns an array with terminal sentinel value -1 to indicate end - // this is so that arrays can be recycled instead of allocating new arrays - // every time - private static native int[] nLineBreakOpportunities(String locale, char[] text, int length, int[] recycle); - private int mLineCount; private int mTopPadding, mBottomPadding; private int mColumns; @@ -870,9 +955,13 @@ public class StaticLayout extends Layout { private static final int TAB_INCREMENT = 20; // same as Layout, but that's private + private static final char CHAR_FIRST_CJK = '\u2E80'; + private static final char CHAR_NEW_LINE = '\n'; private static final char CHAR_TAB = '\t'; private static final char CHAR_SPACE = ' '; + private static final char CHAR_SLASH = '/'; + private static final char CHAR_HYPHEN = '-'; private static final char CHAR_ZWSP = '\u200B'; private static final double EXTRA_ROUNDING = 0.5; |
