Fix bidi desired width calculation
Layout.getDesiredWidth measured text with TextDirectionHeuristics.LTR,
whereas the real calculations used the active direction heuristic set
in the TextView instance. This CL uses the same heuristics for both of
them by passing the value to Layout.getDesiredWidth function.
Bug: 28845953
Change-Id: I68d23f55fe5a86255d62e83bc62df38a047e4bca
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 0bd5071..7e64fa9 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -103,8 +103,12 @@
ArrayUtils.emptyArray(ParagraphStyle.class);
/**
- * Return how wide a layout must be in order to display the
- * specified text with one line per paragraph.
+ * Return how wide a layout must be in order to display the specified text with one line per
+ * paragraph.
+ *
+ * <p>As of O, Uses
+ * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR} as the default text direction heuristics. In
+ * the earlier versions uses {@link TextDirectionHeuristics#LTR} as the default.</p>
*/
public static float getDesiredWidth(CharSequence source,
TextPaint paint) {
@@ -112,12 +116,25 @@
}
/**
+ * Return how wide a layout must be in order to display the specified text slice with one
+ * line per paragraph.
+ *
+ * <p>As of O, Uses
+ * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR} as the default text direction heuristics. In
+ * the earlier versions uses {@link TextDirectionHeuristics#LTR} as the default.</p>
+ */
+ public static float getDesiredWidth(CharSequence source, int start, int end, TextPaint paint) {
+ return getDesiredWidth(source, start, end, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR);
+ }
+
+ /**
* Return how wide a layout must be in order to display the
* specified text slice with one line per paragraph.
+ *
+ * @hide
*/
- public static float getDesiredWidth(CharSequence source,
- int start, int end,
- TextPaint paint) {
+ public static float getDesiredWidth(CharSequence source, int start, int end, TextPaint paint,
+ TextDirectionHeuristic textDir) {
float need = 0;
int next;
@@ -128,7 +145,7 @@
next = end;
// note, omits trailing paragraph char
- float w = measurePara(paint, source, i, next);
+ float w = measurePara(paint, source, i, next, textDir);
if (w > need)
need = w;
@@ -1679,12 +1696,12 @@
}
/* package */
- static float measurePara(TextPaint paint, CharSequence text, int start, int end) {
-
+ static float measurePara(TextPaint paint, CharSequence text, int start, int end,
+ TextDirectionHeuristic textDir) {
MeasuredText mt = MeasuredText.obtain();
TextLine tl = TextLine.obtain();
try {
- mt.setPara(text, start, end, TextDirectionHeuristics.LTR, null);
+ mt.setPara(text, start, end, textDir, null);
Directions directions;
int dir;
if (mt.mEasy) {
@@ -1726,7 +1743,7 @@
}
}
tl.set(paint, text, start, end, dir, directions, hasTabs, tabStops);
- return margin + tl.metrics(null);
+ return margin + Math.abs(tl.metrics(null));
} finally {
TextLine.recycle(tl);
MeasuredText.recycle(mt);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index c4a1771..eb81e6f 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -889,8 +889,9 @@
? mSwitchTransformationMethod.getTransformation(text, this)
: text;
- return new StaticLayout(transformed, mTextPaint,
- (int) Math.ceil(Layout.getDesiredWidth(transformed, mTextPaint)),
+ int width = (int) Math.ceil(Layout.getDesiredWidth(transformed, 0,
+ transformed.length(), mTextPaint, getTextDirectionHeuristic()));
+ return new StaticLayout(transformed, mTextPaint, width,
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 72bfc88..014b1af 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7076,7 +7076,8 @@
if (boring == null || boring == UNKNOWN_BORING) {
if (des < 0) {
- des = (int) Math.ceil(Layout.getDesiredWidth(mTransformed, mTextPaint));
+ des = (int) Math.ceil(Layout.getDesiredWidth(mTransformed, 0,
+ mTransformed.length(), mTextPaint, mTextDir));
}
width = des;
} else {
@@ -7106,7 +7107,8 @@
if (hintBoring == null || hintBoring == UNKNOWN_BORING) {
if (hintDes < 0) {
- hintDes = (int) Math.ceil(Layout.getDesiredWidth(mHint, mTextPaint));
+ hintDes = (int) Math.ceil(Layout.getDesiredWidth(mHint, 0, mHint.length(),
+ mTextPaint, mTextDir));
}
hintWidth = hintDes;
} else {
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index de5e279..0e0c9b0 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -265,7 +265,8 @@
}
// Set the desired width of item
- lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), getPaint());
+ lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), 0, getText().length(),
+ getPaint(), getTextDirectionHeuristic());
return lp;
}