summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget/TextView.java
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2011-07-15 09:49:48 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-07-15 09:49:48 -0700
commit50e95eba5c7cf70a0ecbc50c0cf5b700201aa67f (patch)
tree30bd9123b3c61be3f6fb163572e16fa24716c399 /core/java/android/widget/TextView.java
parent38143a682274dd5f9212d9092ed3553f2ec3e88c (diff)
parentcb379120456d8065d742021fc5c66748fc8a11a8 (diff)
downloadframeworks_base-50e95eba5c7cf70a0ecbc50c0cf5b700201aa67f.zip
frameworks_base-50e95eba5c7cf70a0ecbc50c0cf5b700201aa67f.tar.gz
frameworks_base-50e95eba5c7cf70a0ecbc50c0cf5b700201aa67f.tar.bz2
Merge "Implement textDirection heuristic selection."
Diffstat (limited to 'core/java/android/widget/TextView.java')
-rw-r--r--core/java/android/widget/TextView.java200
1 files changed, 48 insertions, 152 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1f67cd6..640ab18 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -59,6 +59,13 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
+import android.text.TextDirectionHeuristic;
+import android.text.TextDirectionHeuristics;
+import android.text.TextDirectionHeuristics.AnyStrong;
+import android.text.TextDirectionHeuristics.CharCount;
+import android.text.TextDirectionHeuristics.FirstStrong;
+import android.text.TextDirectionHeuristics.TextDirectionAlgorithm;
+import android.text.TextDirectionHeuristics.TextDirectionHeuristicImpl;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -5992,14 +5999,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Layout.Alignment alignment = getLayoutAlignment();
boolean shouldEllipsize = mEllipsize != null && mInput == null;
+ if (mTextDir == null) {
+ resolveTextDirection();
+ }
if (mText instanceof Spannable) {
mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w,
- alignment, mSpacingMult,
+ alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mInput == null ? mEllipsize : null,
ellipsisWidth);
} else {
if (boring == UNKNOWN_BORING) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
+ boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
if (boring != null) {
mBoring = boring;
}
@@ -6036,23 +6046,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else if (shouldEllipsize) {
mLayout = new StaticLayout(mTransformed,
0, mTransformed.length(),
- mTextPaint, w, alignment, mSpacingMult,
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
ellipsisWidth);
} else {
mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
mIncludePad);
}
} else if (shouldEllipsize) {
mLayout = new StaticLayout(mTransformed,
0, mTransformed.length(),
- mTextPaint, w, alignment, mSpacingMult,
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
ellipsisWidth);
} else {
mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
mIncludePad);
}
}
@@ -6064,7 +6074,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (shouldEllipsize) hintWidth = w;
if (hintBoring == UNKNOWN_BORING) {
- hintBoring = BoringLayout.isBoring(mHint, mTextPaint,
+ hintBoring = BoringLayout.isBoring(mHint, mTextPaint, mTextDir,
mHintBoring);
if (hintBoring != null) {
mHintBoring = hintBoring;
@@ -6102,23 +6112,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else if (shouldEllipsize) {
mHintLayout = new StaticLayout(mHint,
0, mHint.length(),
- mTextPaint, hintWidth, alignment, mSpacingMult,
+ mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
ellipsisWidth);
} else {
mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult, mSpacingAdd,
+ hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
mIncludePad);
}
} else if (shouldEllipsize) {
mHintLayout = new StaticLayout(mHint,
0, mHint.length(),
- mTextPaint, hintWidth, alignment, mSpacingMult,
+ mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
ellipsisWidth);
} else {
mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult, mSpacingAdd,
+ hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
mIncludePad);
}
}
@@ -6219,6 +6229,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
BoringLayout.Metrics boring = UNKNOWN_BORING;
BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
+ if (mTextDir == null) {
+ resolveTextDirection();
+ }
+
int des = -1;
boolean fromexisting = false;
@@ -6231,7 +6245,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
if (des < 0) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint, mBoring);
+ boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
if (boring != null) {
mBoring = boring;
}
@@ -10439,11 +10453,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mInBatchEditControllers;
}
+ private class TextViewDirectionHeuristic extends TextDirectionHeuristicImpl {
+ private TextViewDirectionHeuristic(TextDirectionAlgorithm algorithm) {
+ super(algorithm);
+ }
+ @Override
+ protected boolean defaultIsRtl() {
+ return getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ }
+ }
+
/**
* Resolve the text direction.
*
* Text direction of paragraphs in a TextView is determined using a heuristic. If the correct
- * text direction cannot be determined by the heuristic, the view’s resolved layout direction
+ * text direction cannot be determined by the heuristic, the view's resolved layout direction
* determines the direction.
*
* This heuristic and result is applied individually to each paragraph in a TextView, based on
@@ -10452,157 +10476,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
@Override
protected void resolveTextDirection() {
- int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
- switch(mTextDirection) {
+ super.resolveTextDirection();
+
+ int textDir = getResolvedTextDirection();
+ switch (textDir) {
default:
- case TEXT_DIRECTION_INHERIT:
- // Try to the text direction from the parent layout. If not possible, then we will
- // use the default layout direction to decide later
- if (mParent != null && mParent instanceof ViewGroup) {
- resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
- }
- break;
case TEXT_DIRECTION_FIRST_STRONG:
- resolvedTextDirection = getTextDirectionFromFirstStrong(mText);
+ mTextDir = new TextViewDirectionHeuristic(FirstStrong.INSTANCE);
break;
case TEXT_DIRECTION_ANY_RTL:
- resolvedTextDirection = getTextDirectionFromAnyRtl(mText);
+ mTextDir = new TextViewDirectionHeuristic(AnyStrong.INSTANCE_RTL);
break;
case TEXT_DIRECTION_CHAR_COUNT:
- resolvedTextDirection = getTextDirectionFromCharCount(mText);
+ mTextDir = new TextViewDirectionHeuristic(CharCount.INSTANCE_DEFAULT);
break;
case TEXT_DIRECTION_LTR:
- resolvedTextDirection = TEXT_DIRECTION_LTR;
+ mTextDir = TextDirectionHeuristics.LTR;
break;
case TEXT_DIRECTION_RTL:
- resolvedTextDirection = TEXT_DIRECTION_RTL;
+ mTextDir = TextDirectionHeuristics.RTL;
break;
}
- // if we have been so far unable to get the text direction from the heuristics, then we are
- // falling back using the layout direction
- if (resolvedTextDirection == TEXT_DIRECTION_UNDEFINED) {
- switch(getResolvedLayoutDirection()) {
- default:
- case LAYOUT_DIRECTION_LTR:
- resolvedTextDirection = TEXT_DIRECTION_LTR;
- break;
- case LAYOUT_DIRECTION_RTL:
- resolvedTextDirection = TEXT_DIRECTION_RTL;
- break;
- }
- }
- mResolvedTextDirection = resolvedTextDirection;
- }
-
- /**
- * Get text direction following the "first strong" heuristic.
- *
- * @param cs the CharSequence used to get the text direction.
- *
- * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
- * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
- */
- private static int getTextDirectionFromFirstStrong(final CharSequence cs) {
- final int length = cs.length();
- if (length == 0) {
- return TEXT_DIRECTION_UNDEFINED;
- }
- for(int i = 0; i < length; i++) {
- final char c = cs.charAt(i);
- final byte dir = Character.getDirectionality(c);
- if (isStrongLtrChar(dir)) {
- return TEXT_DIRECTION_LTR;
- } else if (isStrongRtlChar(dir)) {
- return TEXT_DIRECTION_RTL;
- }
- }
- return TEXT_DIRECTION_UNDEFINED;
- }
-
- /**
- * Get text direction following the "any RTL" heuristic.
- *
- * @param cs the CharSequence used to get the text direction.
- *
- * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
- * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
- */
- private static int getTextDirectionFromAnyRtl(final CharSequence cs) {
- final int length = cs.length();
- if (length == 0) {
- return TEXT_DIRECTION_UNDEFINED;
- }
- boolean foundStrongLtr = false;
- boolean foundStrongRtl = false;
- for(int i = 0; i < length; i++) {
- final char c = cs.charAt(i);
- final byte dir = Character.getDirectionality(c);
- if (isStrongLtrChar(dir)) {
- foundStrongLtr = true;
- } else if (isStrongRtlChar(dir)) {
- foundStrongRtl = true;
- break;
- }
- }
- if (foundStrongRtl) {
- return TEXT_DIRECTION_RTL;
- }
- if (foundStrongLtr) {
- return TEXT_DIRECTION_LTR;
- }
- return TEXT_DIRECTION_UNDEFINED;
- }
-
- /**
- * Get text direction following the "char count" heuristic.
- *
- * @param cs the CharSequence used to get the text direction.
- *
- * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
- * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
- */
- private int getTextDirectionFromCharCount(CharSequence cs) {
- final int length = cs.length();
- if (length == 0) {
- return TEXT_DIRECTION_UNDEFINED;
- }
- int countLtr = 0;
- int countRtl = 0;
- for(int i = 0; i < length; i++) {
- final char c = cs.charAt(i);
- final byte dir = Character.getDirectionality(c);
- if (isStrongLtrChar(dir)) {
- countLtr++;
- } else if (isStrongRtlChar(dir)) {
- countRtl++;
- }
- }
- final float percentLtr = ((float) countLtr) / (countLtr + countRtl);
- if (percentLtr > DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD) {
- return TEXT_DIRECTION_LTR;
- }
- final float percentRtl = ((float) countRtl) / (countLtr + countRtl);
- if (percentRtl > DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD) {
- return TEXT_DIRECTION_RTL;
- }
- return TEXT_DIRECTION_UNDEFINED;
- }
-
- /**
- * Return true if the char direction is corresponding to a "strong RTL char" following the
- * Unicode Bidirectional Algorithm (UBA).
- */
- private static boolean isStrongRtlChar(final byte dir) {
- return (dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
- dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC);
- }
-
- /**
- * Return true if the char direction is corresponding to a "strong LTR char" following the
- * Unicode Bidirectional Algorithm (UBA).
- */
- private static boolean isStrongLtrChar(final byte dir) {
- return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
}
/**
@@ -10768,6 +10662,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private BoringLayout mSavedLayout, mSavedHintLayout;
+ private TextDirectionHeuristic mTextDir = null;
+
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
private InputFilter[] mFilters = NO_FILTERS;
private static final Spanned EMPTY_SPANNED = new SpannedString("");