summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rwxr-xr-xcore/java/android/text/Layout.java35
-rwxr-xr-xcore/java/android/text/StaticLayout.java110
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) {