Fix bug #3388534 Long file names are improperly displayed when played
- force ellipsising when there are more lines found than maxLines
- do not care about lines when we have reached maxLines
- also fix relayouting when changing maxLines thru setMaxLines()
- do not allow START / MIDDLE ellipsis when there are multiple lines
(and print a log accordingly)
Change-Id: I90f5a7f5200a220aceee01fb7300bec2c4c3a075
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 14c71b2..788711d 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -23,6 +23,7 @@
import android.text.style.LineHeightSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.TabStopSpan;
+import android.util.Log;
import com.android.internal.util.ArrayUtils;
@@ -38,6 +39,8 @@
*/
public class StaticLayout extends Layout {
+ static final String TAG = "StaticLayout";
+
public StaticLayout(CharSequence source, TextPaint paint,
int width,
Alignment align, float spacingmult, float spacingadd,
@@ -75,7 +78,7 @@
float spacingmult, float spacingadd,
boolean includepad) {
this(source, bufstart, bufend, paint, outerwidth, align, textDir,
- spacingmult, spacingadd, includepad, null, 0);
+ spacingmult, spacingadd, includepad, null, 0, Integer.MAX_VALUE);
}
public StaticLayout(CharSequence source, int bufstart, int bufend,
@@ -86,7 +89,7 @@
TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
this(source, bufstart, bufend, paint, outerwidth, align,
TextDirectionHeuristics.FIRSTSTRONG_LTR,
- spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+ spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, Integer.MAX_VALUE);
}
/**
@@ -97,7 +100,7 @@
Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+ TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) {
super((ellipsize == null)
? source
: (source instanceof Spanned)
@@ -130,6 +133,7 @@
mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
mLineDirections = new Directions[
ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mMaximumVisibleLineCount = maxLines;
mMeasured = MeasuredText.obtain();
@@ -141,8 +145,8 @@
mFontMetricsInt = null;
}
- /* package */ StaticLayout(boolean ellipsize) {
- super(null, null, 0, null, 0, 0);
+ /* package */ StaticLayout(CharSequence text) {
+ super(text, null, 0, null, 0, 0);
mColumns = COLUMNS_ELLIPSIZE;
mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
@@ -394,6 +398,7 @@
okBottom = fitBottom;
}
} else {
+ final boolean moreChars = (j + 1 < spanEnd);
if (ok != here) {
// Log.e("text", "output ok " + here + " to " +ok);
@@ -411,7 +416,7 @@
ok == bufEnd, includepad, trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth, okWidth,
- paint);
+ paint, moreChars);
here = ok;
} else if (fit != here) {
@@ -427,7 +432,7 @@
fit == bufEnd, includepad, trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth, fitWidth,
- paint);
+ paint, moreChars);
here = fit;
} else {
@@ -449,7 +454,7 @@
trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth,
- widths[here - paraStart], paint);
+ widths[here - paraStart], paint, moreChars);
here = here + 1;
}
@@ -472,10 +477,13 @@
width = restWidth;
}
}
+ if (mLineCount >= mMaximumVisibleLineCount) {
+ break;
+ }
}
}
- if (paraEnd != here) {
+ if (paraEnd != here && mLineCount < mMaximumVisibleLineCount) {
if ((fitTop | fitBottom | fitDescent | fitAscent) == 0) {
paint.getFontMetricsInt(fm);
@@ -496,7 +504,7 @@
needMultiply, paraStart, chdirs, dir, easy,
paraEnd == bufEnd, includepad, trackpad,
chs, widths, paraStart,
- ellipsize, ellipsizedWidth, w, paint);
+ ellipsize, ellipsizedWidth, w, paint, paraEnd != bufEnd);
}
paraStart = paraEnd;
@@ -505,7 +513,8 @@
break;
}
- if (bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) {
+ if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) &&
+ mLineCount < mMaximumVisibleLineCount) {
// Log.e("text", "output last " + bufEnd);
paint.getFontMetricsInt(fm);
@@ -519,7 +528,7 @@
needMultiply, bufEnd, null, DEFAULT_DIR, true,
true, includepad, trackpad,
null, null, bufStart,
- ellipsize, ellipsizedWidth, 0, paint);
+ ellipsize, ellipsizedWidth, 0, paint, false);
}
}
@@ -624,7 +633,7 @@
boolean includePad, boolean trackPad,
char[] chs, float[] widths, int widthStart,
TextUtils.TruncateAt ellipsize, float ellipsisWidth,
- float textWidth, TextPaint paint) {
+ float textWidth, TextPaint paint, boolean moreChars) {
int j = mLineCount;
int off = j * mColumns;
int want = off + mColumns + TOP;
@@ -722,9 +731,10 @@
// If ellipsize is in marquee mode, do not apply ellipsis on the first line
if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
+ boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
calculateEllipsis(start, end, widths, widthStart,
ellipsisWidth, ellipsize, j,
- textWidth, paint);
+ textWidth, paint, forceEllipsis);
}
mLineCount++;
@@ -734,9 +744,9 @@
private void calculateEllipsis(int lineStart, int lineEnd,
float[] widths, int widthStart,
float avail, TextUtils.TruncateAt where,
- int line, float textWidth, TextPaint paint) {
-
- if (textWidth <= avail) {
+ int line, float textWidth, TextPaint paint,
+ boolean forceEllipsis) {
+ if (textWidth <= avail && !forceEllipsis) {
// Everything fits!
mLines[mColumns * line + ELLIPSIS_START] = 0;
mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
@@ -744,25 +754,33 @@
}
float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS);
- int ellipsisStart, ellipsisCount;
+ int ellipsisStart = 0;
+ int ellipsisCount = 0;
int len = lineEnd - lineStart;
+ // We only support start ellipsis on a single line
if (where == TextUtils.TruncateAt.START) {
- float sum = 0;
- int i;
+ if (mMaximumVisibleLineCount == 1) {
+ float sum = 0;
+ int i;
- for (i = len; i >= 0; i--) {
- float w = widths[i - 1 + lineStart - widthStart];
+ for (i = len; i >= 0; i--) {
+ float w = widths[i - 1 + lineStart - widthStart];
- if (w + sum + ellipsisWidth > avail) {
- break;
+ if (w + sum + ellipsisWidth > avail) {
+ break;
+ }
+
+ sum += w;
}
- sum += w;
+ ellipsisStart = 0;
+ ellipsisCount = i;
+ } else {
+ if (Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "Start Ellipsis only supported with one line");
+ }
}
-
- ellipsisStart = 0;
- ellipsisCount = i;
} else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
float sum = 0;
int i;
@@ -779,34 +797,45 @@
ellipsisStart = i;
ellipsisCount = len - i;
- } else /* where = TextUtils.TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
+ if (forceEllipsis && ellipsisCount == 0 && i > 0) {
+ ellipsisStart = i - 1;
+ ellipsisCount = 1;
+ }
+ } else {
+ // where = TextUtils.TruncateAt.MIDDLE We only support middle ellipsis on a single line
+ if (mMaximumVisibleLineCount == 1) {
+ float lsum = 0, rsum = 0;
+ int left = 0, right = len;
- float ravail = (avail - ellipsisWidth) / 2;
- for (right = len; right >= 0; right--) {
- float w = widths[right - 1 + lineStart - widthStart];
+ float ravail = (avail - ellipsisWidth) / 2;
+ for (right = len; right >= 0; right--) {
+ float w = widths[right - 1 + lineStart - widthStart];
- if (w + rsum > ravail) {
- break;
+ if (w + rsum > ravail) {
+ break;
+ }
+
+ rsum += w;
}
- rsum += w;
- }
+ float lavail = avail - ellipsisWidth - rsum;
+ for (left = 0; left < right; left++) {
+ float w = widths[left + lineStart - widthStart];
- float lavail = avail - ellipsisWidth - rsum;
- for (left = 0; left < right; left++) {
- float w = widths[left + lineStart - widthStart];
+ if (w + lsum > lavail) {
+ break;
+ }
- if (w + lsum > lavail) {
- break;
+ lsum += w;
}
- lsum += w;
+ ellipsisStart = left;
+ ellipsisCount = right - left;
+ } else {
+ if (Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "Middle Ellipsis only supported with one line");
+ }
}
-
- ellipsisStart = left;
- ellipsisCount = right - left;
}
mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
@@ -916,14 +945,6 @@
return mEllipsizedWidth;
}
- /**
- * @hide
- */
- @Override
- public void setMaximumVisibleLineCount(int lineCount) {
- mMaximumVisibleLineCount = lineCount;
- }
-
void prepare() {
mMeasured = MeasuredText.obtain();
}
@@ -949,7 +970,7 @@
private int[] mLines;
private Directions[] mLineDirections;
- private int mMaximumVisibleLineCount = 0;
+ private int mMaximumVisibleLineCount = Integer.MAX_VALUE;
private static final int START_MASK = 0x1FFFFFFF;
private static final int DIR_SHIFT = 30;