Merge "Add BidiFormatter utility"

This commit is contained in:
Fabrice Di Meglio
2013-02-12 23:36:44 +00:00
committed by Android (Google) Code Review
4 changed files with 1304 additions and 75 deletions

View File

@@ -22273,6 +22273,21 @@ package android.text {
method public int getTopPadding();
}
public abstract interface TextDirectionHeuristic {
method public abstract boolean isRtl(char[], int, int);
method public abstract boolean isRtl(java.lang.CharSequence, int, int);
}
public class TextDirectionHeuristics {
ctor public TextDirectionHeuristics();
field public static final android.text.TextDirectionHeuristic ANYRTL_LTR;
field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_LTR;
field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_RTL;
field public static final android.text.TextDirectionHeuristic LOCALE;
field public static final android.text.TextDirectionHeuristic LTR;
field public static final android.text.TextDirectionHeuristic RTL;
}
public class TextPaint extends android.graphics.Paint {
ctor public TextPaint();
ctor public TextPaint(int);
@@ -22364,6 +22379,48 @@ package android.text {
}
package android.text.bidi {
public final class BidiFormatter {
method public java.lang.String dirAttr(java.lang.String);
method public java.lang.String dirAttr(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String dirAttr(boolean);
method public java.lang.String dirAttrValue(java.lang.String);
method public java.lang.String dirAttrValue(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String dirAttrValue(boolean);
method public java.lang.String endEdge();
method public static android.text.bidi.BidiFormatter getInstance(boolean);
method public static android.text.bidi.BidiFormatter getInstance(java.util.Locale);
method public boolean getStereoReset();
method public boolean isRtl(java.lang.String);
method public boolean isRtlContext();
method public java.lang.String mark();
method public java.lang.String markAfter(java.lang.String);
method public java.lang.String markAfter(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String markBefore(java.lang.String);
method public java.lang.String markBefore(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
method public java.lang.String spanWrap(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String spanWrap(java.lang.String, boolean);
method public java.lang.String spanWrap(java.lang.String);
method public java.lang.String startEdge();
method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic, boolean);
method public java.lang.String unicodeWrap(java.lang.String, android.text.TextDirectionHeuristic);
method public java.lang.String unicodeWrap(java.lang.String, boolean);
method public java.lang.String unicodeWrap(java.lang.String);
}
public static final class BidiFormatter.Builder {
ctor public BidiFormatter.Builder();
ctor public BidiFormatter.Builder(boolean);
ctor public BidiFormatter.Builder(java.util.Locale);
method public android.text.bidi.BidiFormatter build();
method public android.text.bidi.BidiFormatter.Builder setTextDirectionHeuristic(android.text.TextDirectionHeuristic);
method public android.text.bidi.BidiFormatter.Builder stereoReset(boolean);
}
}
package android.text.format {
public class DateFormat {

View File

@@ -17,10 +17,30 @@
package android.text;
/**
* Interface for objects that guess at the paragraph direction by examining text.
*
* @hide
* Interface for objects that use a heuristic for guessing at the paragraph direction by examining text.
*/
public interface TextDirectionHeuristic {
boolean isRtl(char[] text, int start, int count);
/**
* Guess if a chars array is in the RTL direction or not.
*
* @param array the char array.
* @param start start index, inclusive.
* @param count the length to check, must not be negative and not greater than
* {@code array.length - start}.
* @return true if all chars in the range are to be considered in a RTL direction,
* false otherwise.
*/
boolean isRtl(char[] array, int start, int count);
/**
* Guess if a {@code CharSequence} is in the RTL direction or not.
*
* @param cs the CharSequence.
* @param start start index, inclusive.
* @param count the length to check, must not be negative and not greater than
* {@code CharSequence.length() - start}.
* @return true if all chars in the range are to be considered in a RTL direction,
* false otherwise.
*/
boolean isRtl(CharSequence cs, int start, int count);
}

View File

@@ -19,43 +19,45 @@ package android.text;
import android.view.View;
import java.nio.CharBuffer;
/**
* Some objects that implement TextDirectionHeuristic.
*
* @hide
*/
public class TextDirectionHeuristics {
/** Always decides that the direction is left to right. */
/**
* Always decides that the direction is left to right.
*/
public static final TextDirectionHeuristic LTR =
new TextDirectionHeuristicInternal(null /* no algorithm */, false);
/** Always decides that the direction is right to left. */
/**
* Always decides that the direction is right to left.
*/
public static final TextDirectionHeuristic RTL =
new TextDirectionHeuristicInternal(null /* no algorithm */, true);
/**
* Determines the direction based on the first strong directional character,
* including bidi format chars, falling back to left to right if it
* finds none. This is the default behavior of the Unicode Bidirectional
* Algorithm.
* Determines the direction based on the first strong directional character, including bidi
* format chars, falling back to left to right if it finds none. This is the default behavior
* of the Unicode Bidirectional Algorithm.
*/
public static final TextDirectionHeuristic FIRSTSTRONG_LTR =
new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, false);
/**
* Determines the direction based on the first strong directional character,
* including bidi format chars, falling back to right to left if it
* finds none. This is similar to the default behavior of the Unicode
* Bidirectional Algorithm, just with different fallback behavior.
* Determines the direction based on the first strong directional character, including bidi
* format chars, falling back to right to left if it finds none. This is similar to the default
* behavior of the Unicode Bidirectional Algorithm, just with different fallback behavior.
*/
public static final TextDirectionHeuristic FIRSTSTRONG_RTL =
new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
/**
* If the text contains any strong right to left non-format character, determines
* that the direction is right to left, falling back to left to right if it
* finds none.
* If the text contains any strong right to left non-format character, determines that the
* direction is right to left, falling back to left to right if it finds none.
*/
public static final TextDirectionHeuristic ANYRTL_LTR =
new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
@@ -65,8 +67,39 @@ public class TextDirectionHeuristics {
*/
public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
private static enum TriState {
TRUE, FALSE, UNKNOWN;
/**
* State constants for taking care about true / false / unknown
*/
private static final int STATE_TRUE = 0;
private static final int STATE_FALSE = 1;
private static final int STATE_UNKNOWN = 2;
private static int isRtlText(int directionality) {
switch (directionality) {
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
return STATE_FALSE;
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
return STATE_TRUE;
default:
return STATE_UNKNOWN;
}
}
private static int isRtlTextOrFormat(int directionality) {
switch (directionality) {
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
return STATE_FALSE;
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
return STATE_TRUE;
default:
return STATE_UNKNOWN;
}
}
/**
@@ -87,21 +120,26 @@ public class TextDirectionHeuristics {
abstract protected boolean defaultIsRtl();
@Override
public boolean isRtl(char[] chars, int start, int count) {
if (chars == null || start < 0 || count < 0 || chars.length - count < start) {
public boolean isRtl(char[] array, int start, int count) {
return isRtl(CharBuffer.wrap(array), start, count);
}
@Override
public boolean isRtl(CharSequence cs, int start, int count) {
if (cs == null || start < 0 || count < 0 || cs.length() - count < start) {
throw new IllegalArgumentException();
}
if (mAlgorithm == null) {
return defaultIsRtl();
}
return doCheck(chars, start, count);
return doCheck(cs, start, count);
}
private boolean doCheck(char[] chars, int start, int count) {
switch(mAlgorithm.checkRtl(chars, start, count)) {
case TRUE:
private boolean doCheck(CharSequence cs, int start, int count) {
switch(mAlgorithm.checkRtl(cs, start, count)) {
case STATE_TRUE:
return true;
case FALSE:
case STATE_FALSE:
return false;
default:
return defaultIsRtl();
@@ -124,58 +162,26 @@ public class TextDirectionHeuristics {
}
}
private static TriState isRtlText(int directionality) {
switch (directionality) {
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
return TriState.FALSE;
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
return TriState.TRUE;
default:
return TriState.UNKNOWN;
}
}
private static TriState isRtlTextOrFormat(int directionality) {
switch (directionality) {
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
case Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:
return TriState.FALSE;
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
return TriState.TRUE;
default:
return TriState.UNKNOWN;
}
}
/**
* Interface for an algorithm to guess the direction of a paragraph of text.
*
*/
private static interface TextDirectionAlgorithm {
/**
* Returns whether the range of text is RTL according to the algorithm.
*
*/
TriState checkRtl(char[] text, int start, int count);
int checkRtl(CharSequence cs, int start, int count);
}
/**
* Algorithm that uses the first strong directional character to determine
* the paragraph direction. This is the standard Unicode Bidirectional
* algorithm.
*
* Algorithm that uses the first strong directional character to determine the paragraph
* direction. This is the standard Unicode Bidirectional algorithm.
*/
private static class FirstStrong implements TextDirectionAlgorithm {
@Override
public TriState checkRtl(char[] text, int start, int count) {
TriState result = TriState.UNKNOWN;
for (int i = start, e = start + count; i < e && result == TriState.UNKNOWN; ++i) {
result = isRtlTextOrFormat(Character.getDirectionality(text[i]));
public int checkRtl(CharSequence cs, int start, int count) {
int result = STATE_UNKNOWN;
for (int i = start, e = start + count; i < e && result == STATE_UNKNOWN; ++i) {
result = isRtlTextOrFormat(Character.getDirectionality(cs.charAt(i)));
}
return result;
}
@@ -190,25 +196,24 @@ public class TextDirectionHeuristics {
* Algorithm that uses the presence of any strong directional non-format
* character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
* direction of text.
*
*/
private static class AnyStrong implements TextDirectionAlgorithm {
private final boolean mLookForRtl;
@Override
public TriState checkRtl(char[] text, int start, int count) {
public int checkRtl(CharSequence cs, int start, int count) {
boolean haveUnlookedFor = false;
for (int i = start, e = start + count; i < e; ++i) {
switch (isRtlText(Character.getDirectionality(text[i]))) {
case TRUE:
switch (isRtlText(Character.getDirectionality(cs.charAt(i)))) {
case STATE_TRUE:
if (mLookForRtl) {
return TriState.TRUE;
return STATE_TRUE;
}
haveUnlookedFor = true;
break;
case FALSE:
case STATE_FALSE:
if (!mLookForRtl) {
return TriState.FALSE;
return STATE_FALSE;
}
haveUnlookedFor = true;
break;
@@ -217,9 +222,9 @@ public class TextDirectionHeuristics {
}
}
if (haveUnlookedFor) {
return mLookForRtl ? TriState.FALSE : TriState.TRUE;
return mLookForRtl ? STATE_FALSE : STATE_TRUE;
}
return TriState.UNKNOWN;
return STATE_UNKNOWN;
}
private AnyStrong(boolean lookForRtl) {

File diff suppressed because it is too large Load Diff