diff options
Diffstat (limited to 'core/java/android')
-rwxr-xr-x | core/java/android/text/Layout.java | 35 | ||||
-rwxr-xr-x | core/java/android/text/StaticLayout.java | 110 |
2 files changed, 79 insertions, 66 deletions
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 1211f41..112e007 100755 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1818,43 +1818,12 @@ public abstract class Layout { // are left-to-right, the others are right-to-left. So, for example, // a line that starts with a right-to-left run has 0 at mDirections[0], // since the 'first' (ltr) run is zero length. - // - // The code currently assumes that each run is adjacent to the previous - // one, progressing in the base line direction. This isn't sufficient - // to handle nested runs, for example numeric text in an rtl context - // in an ltr paragraph. /* package */ Directions(short[] dirs) { mDirections = dirs; } - static int baseDirection(Directions dir,int length) { - if (dir == DIRS_ALL_LEFT_TO_RIGHT) { - return DIR_LEFT_TO_RIGHT; - } else if (dir == DIRS_ALL_RIGHT_TO_LEFT) { - return DIR_RIGHT_TO_LEFT; - } - - int sum=0; - int lastSwitch=0; - int i=0; - while ((i+1) < dir.mDirections.length) { - sum+=dir.mDirections[i];//-lastSwitch; - sum-=dir.mDirections[i+1];//-dir.mDirections[i]; - lastSwitch=dir.mDirections[i+1]; - i+=2; - } - - if ((i+1)==dir.mDirections.length) { - sum+=dir.mDirections[i];//-lastSwitch); - } else if (i==dir.mDirections.length) { - sum-=length-lastSwitch; - } - - if (sum>=0) { - return DIR_LEFT_TO_RIGHT; - } else { - return DIR_RIGHT_TO_LEFT; - } + boolean hasRTL() { + return mDirections.length>1 && mDirections[1]>0; } } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index f8301d2..13768e4 100755 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -233,10 +233,20 @@ extends Layout } } + if (!easy) { + // XXX put override flags, etc. into chdirs + dir = bidi(dir >= 0 ? DIR_REQUEST_DEFAULT_LTR : DIR_REQUEST_DEFAULT_RTL, + chs, chdirs, n, false); + } + // Ensure that none of the underlying characters are treated // as viable breakpoints, and that the entire run gets the // same bidi direction. + final byte SOR = dir == DIR_LEFT_TO_RIGHT ? + Character.DIRECTIONALITY_LEFT_TO_RIGHT : + Character.DIRECTIONALITY_RIGHT_TO_LEFT; + if (source instanceof Spanned) { Spanned sp = (Spanned) source; ReplacementSpan[] spans = sp.getSpans(start, end, ReplacementSpan.class); @@ -246,14 +256,13 @@ extends Layout int b = sp.getSpanEnd(spans[y]); for (int x = a; x < b; x++) { + chdirs[x - start] = SOR; chs[x - start] = '\uFFFC'; } } } if (!easy) { - // XXX put override flags, etc. into chdirs - dir = bidi(dir, chs, chdirs, n, false); // Do mirroring for right-to-left segments @@ -638,26 +647,16 @@ extends Layout * Determine primary paragraph direction if not specified */ if (dir != DIR_REQUEST_LTR && dir != DIR_REQUEST_RTL) { - // set up default - dir = dir >= 0 ? DIR_LEFT_TO_RIGHT : DIR_RIGHT_TO_LEFT; + // Heuristic - LTR unless paragraph contains any RTL chars + dir = DIR_LEFT_TO_RIGHT; for (int j = 0; j < n; j++) { - int d = chInfo[j]; - - if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT) { - dir = DIR_LEFT_TO_RIGHT; - break; - } - if (d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) { + if (chInfo[j] == Character.DIRECTIONALITY_RIGHT_TO_LEFT) { dir = DIR_RIGHT_TO_LEFT; break; } } } - final byte SOR = dir == DIR_LEFT_TO_RIGHT ? - Character.DIRECTIONALITY_LEFT_TO_RIGHT : - Character.DIRECTIONALITY_RIGHT_TO_LEFT; - /* * XXX Explicit overrides should go here */ @@ -666,7 +665,11 @@ extends Layout * Weak type resolution */ - // dump(chdirs, n, "initial"); + final byte SOR = dir == DIR_LEFT_TO_RIGHT ? + Character.DIRECTIONALITY_LEFT_TO_RIGHT : + Character.DIRECTIONALITY_RIGHT_TO_LEFT; + + // dump(chInfo, n, "initial"); // W1 non spacing marks for (int j = 0; j < n; j++) { @@ -678,7 +681,7 @@ extends Layout } } - // dump(chdirs, n, "W1"); + // dump(chInfo, n, "W1"); // W2 european numbers byte cur = SOR; @@ -693,11 +696,10 @@ extends Layout if (cur == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC) chInfo[j] = Character.DIRECTIONALITY_ARABIC_NUMBER; - else chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT; } } - // dump(chdirs, n, "W2"); + // dump(chInfo, n, "W2"); // W3 arabic letters for (int j = 0; j < n; j++) { @@ -705,7 +707,7 @@ extends Layout chInfo[j] = Character.DIRECTIONALITY_RIGHT_TO_LEFT; } - // dump(chdirs, n, "W3"); + // dump(chInfo, n, "W3"); // W4 single separator between numbers for (int j = 1; j < n - 1; j++) { @@ -713,6 +715,9 @@ extends Layout byte prev = chInfo[j - 1]; byte next = chInfo[j + 1]; + boolean isSpace = Character.isWhitespace(chs[j]); + boolean nextIsSpace = Character.isWhitespace(chs[j + 1]); + if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR) { if (prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER && next == Character.DIRECTIONALITY_EUROPEAN_NUMBER) @@ -724,10 +729,31 @@ extends Layout if (prev == Character.DIRECTIONALITY_ARABIC_NUMBER && next == Character.DIRECTIONALITY_ARABIC_NUMBER) chInfo[j] = Character.DIRECTIONALITY_ARABIC_NUMBER; + // add condition for spaces following the separator + if (nextIsSpace && + ( prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER + || prev == Character.DIRECTIONALITY_ARABIC_NUMBER ) ) + chInfo[j] = SOR; + } + // add condition if the separator is a space + else if (isSpace && prev != SOR && + ( next == Character.DIRECTIONALITY_EUROPEAN_NUMBER + || next == Character.DIRECTIONALITY_ARABIC_NUMBER ) ) { + chInfo[j] = SOR; + for (int k=j+1; k < n; ++k) { + if (chInfo[k] == Character.DIRECTIONALITY_LEFT_TO_RIGHT) { + chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT; + break; + } + if (chInfo[k] == Character.DIRECTIONALITY_RIGHT_TO_LEFT) { + chInfo[j] = Character.DIRECTIONALITY_RIGHT_TO_LEFT; + break; + } + } } } - // dump(chdirs, n, "W4"); + // dump(chInfo, n, "W4"); // W5 european number terminators boolean adjacent = false; @@ -742,7 +768,7 @@ extends Layout adjacent = false; } - //dump(chdirs, n, "W5"); + //dump(chInfo, n, "W5"); // W5 european number terminators part 2, // W6 separators and terminators @@ -769,7 +795,7 @@ extends Layout } } - // dump(chdirs, n, "W6"); + // dump(chInfo, n, "W6"); // W7 strong direction of european numbers cur = SOR; @@ -785,7 +811,7 @@ extends Layout chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT; } - // dump(chdirs, n, "W7"); + // dump(chInfo, n, "W7"); // N1, N2 neutrals cur = SOR; @@ -795,9 +821,8 @@ extends Layout if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT || d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) { cur = d; - } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER) { - cur = Character.DIRECTIONALITY_RIGHT_TO_LEFT; - } else if (d == Character.DIRECTIONALITY_ARABIC_NUMBER) { + } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER || + d == Character.DIRECTIONALITY_ARABIC_NUMBER) { cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT; } else { byte dd = SOR; @@ -810,12 +835,10 @@ extends Layout dd == Character.DIRECTIONALITY_RIGHT_TO_LEFT) { break; } - if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER) { + if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER || + dd == Character.DIRECTIONALITY_ARABIC_NUMBER) { dd = Character.DIRECTIONALITY_LEFT_TO_RIGHT; break; - } else if (dd == Character.DIRECTIONALITY_ARABIC_NUMBER) { - dd = Character.DIRECTIONALITY_RIGHT_TO_LEFT; - break; } } @@ -830,7 +853,7 @@ extends Layout } } - // dump(chdirs, n, "final"); + // dump(chInfo, n, "final"); // extra: enforce that all tabs and surrogate characters go the // primary direction @@ -844,6 +867,26 @@ extends Layout } } + // Deal specifically with special operators (like '+',etc.) ahead of numbers/english inside RTL paragraphs + for (int j = 0; j < n; j++) { + switch(chs[j]) { + case '+': + // For the following chars it is logical to apply the fix, but it appears + // it customary only for the "+" and we need to behave similarly to other devices: + //case '*': + //case '/': + //case '@': + //case '#': + //case '$': + //case '%': + //case '^': + //case '&': + //case '_': + //case '\\': + chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT; + } + } + return dir; } @@ -1268,7 +1311,8 @@ extends Layout } public int getParagraphDirection(int line) { - return Directions.baseDirection(mLineDirections[line],getLineEnd(line)-getLineStart(line)); + // LTR unless paragraph contains RTL chars (anywhere) + return mLineDirections[line].hasRTL() ? DIR_RIGHT_TO_LEFT : DIR_LEFT_TO_RIGHT; } public boolean getLineContainsTab(int line) { |