summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilles Debunne <debunne@google.com>2011-12-08 17:58:24 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-12-08 17:58:24 -0800
commit316ca5059ebd7270a04da5649d25653c355e158d (patch)
tree758797e46ab40c386dd3cee31423d00c551b98dd
parent556e4ca54161be17333ec98fadc113485120a6e8 (diff)
parentc1f44830809f0a8526855f13822702ea756214fa (diff)
downloadframeworks_base-316ca5059ebd7270a04da5649d25653c355e158d.zip
frameworks_base-316ca5059ebd7270a04da5649d25653c355e158d.tar.gz
frameworks_base-316ca5059ebd7270a04da5649d25653c355e158d.tar.bz2
Merge "Re-use SpanSets in TextLine" into ics-mr1
-rw-r--r--core/java/android/text/TextLine.java105
1 files changed, 48 insertions, 57 deletions
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index b73d900..b3df8ff 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -59,6 +59,12 @@ class TextLine {
private boolean mCharsValid;
private Spanned mSpanned;
private final TextPaint mWorkPaint = new TextPaint();
+ private final SpanSet<MetricAffectingSpan> mMetricAffectingSpanSpanSet =
+ new SpanSet<MetricAffectingSpan>(MetricAffectingSpan.class);
+ private final SpanSet<CharacterStyle> mCharacterStyleSpanSet =
+ new SpanSet<CharacterStyle>(CharacterStyle.class);
+ private final SpanSet<ReplacementSpan> mReplacementSpanSpanSet =
+ new SpanSet<ReplacementSpan>(ReplacementSpan.class);
private static final TextLine[] sCached = new TextLine[3];
@@ -119,7 +125,6 @@ class TextLine {
* @param hasTabs true if the line might contain tabs or emoji
* @param tabStops the tabStops. Can be null.
*/
- @SuppressWarnings("null")
void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
Directions directions, boolean hasTabs, TabStops tabStops) {
mPaint = paint;
@@ -135,12 +140,10 @@ class TextLine {
mSpanned = null;
boolean hasReplacement = false;
- SpanSet<ReplacementSpan> replacementSpans = null;
if (text instanceof Spanned) {
mSpanned = (Spanned) text;
- replacementSpans = new SpanSet<ReplacementSpan>(mSpanned, start, limit,
- ReplacementSpan.class);
- hasReplacement = replacementSpans.numberOfSpans > 0;
+ mReplacementSpanSpanSet.init(mSpanned, start, limit);
+ hasReplacement = mReplacementSpanSpanSet.numberOfSpans > 0;
}
mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
@@ -158,9 +161,8 @@ class TextLine {
// zero-width characters.
char[] chars = mChars;
for (int i = start, inext; i < limit; i = inext) {
- // replacementSpans cannot be null if hasReplacement is true
- inext = replacementSpans.getNextTransition(i, limit);
- if (replacementSpans.hasSpansIntersecting(i, inext)) {
+ inext = mReplacementSpanSpanSet.getNextTransition(i, limit);
+ if (mReplacementSpanSpanSet.hasSpansIntersecting(i, inext)) {
// transition into a span
chars[i - start] = '\ufffc';
for (int j = i - start + 1, e = inext - start; j < e; ++j) {
@@ -854,21 +856,30 @@ class TextLine {
}
private static class SpanSet<E> {
- final int numberOfSpans;
- final E[] spans;
- final int[] spanStarts;
- final int[] spanEnds;
- final int[] spanFlags;
+ int numberOfSpans;
+ E[] spans;
+ int[] spanStarts;
+ int[] spanEnds;
+ int[] spanFlags;
+ final Class<? extends E> classType;
+
+ SpanSet(Class<? extends E> type) {
+ classType = type;
+ numberOfSpans = 0;
+ }
@SuppressWarnings("unchecked")
- SpanSet(Spanned spanned, int start, int limit, Class<? extends E> type) {
- final E[] allSpans = spanned.getSpans(start, limit, type);
+ public void init(Spanned spanned, int start, int limit) {
+ final E[] allSpans = spanned.getSpans(start, limit, classType);
final int length = allSpans.length;
- // These arrays may end up being too large because of empty spans
- spans = (E[]) Array.newInstance(type, length);
- spanStarts = new int[length];
- spanEnds = new int[length];
- spanFlags = new int[length];
+
+ if (length > 0 && (spans == null || spans.length < length)) {
+ // These arrays may end up being too large because of empty spans
+ spans = (E[]) Array.newInstance(classType, length);
+ spanStarts = new int[length];
+ spanEnds = new int[length];
+ spanFlags = new int[length];
+ }
int count = 0;
for (int i = 0; i < length; i++) {
@@ -879,30 +890,11 @@ class TextLine {
if (spanStart == spanEnd) continue;
final int spanFlag = spanned.getSpanFlags(span);
- final int priority = spanFlag & Spanned.SPAN_PRIORITY;
- if (priority != 0 && count != 0) {
- int j;
-
- for (j = 0; j < count; j++) {
- final int otherPriority = spanFlags[j] & Spanned.SPAN_PRIORITY;
- if (priority > otherPriority) break;
- }
-
- System.arraycopy(spans, j, spans, j + 1, count - j);
- System.arraycopy(spanStarts, j, spanStarts, j + 1, count - j);
- System.arraycopy(spanEnds, j, spanEnds, j + 1, count - j);
- System.arraycopy(spanFlags, j, spanFlags, j + 1, count - j);
- spans[j] = span;
- spanStarts[j] = spanStart;
- spanEnds[j] = spanEnd;
- spanFlags[j] = spanFlag;
- } else {
- spans[i] = span;
- spanStarts[i] = spanStart;
- spanEnds[i] = spanEnd;
- spanFlags[i] = spanFlag;
- }
+ spans[i] = span;
+ spanStarts[i] = spanStart;
+ spanEnds[i] = spanEnd;
+ spanFlags[i] = spanFlag;
count++;
}
@@ -970,10 +962,8 @@ class TextLine {
y, bottom, fmi, needWidth || mlimit < measureLimit);
}
- final SpanSet<MetricAffectingSpan> metricAffectingSpans = new SpanSet<MetricAffectingSpan>(
- mSpanned, mStart + start, mStart + limit, MetricAffectingSpan.class);
- final SpanSet<CharacterStyle> characterStyleSpans = new SpanSet<CharacterStyle>(
- mSpanned, mStart + start, mStart + limit, CharacterStyle.class);
+ mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
+ mCharacterStyleSpanSet.init(mSpanned, mStart + start, mStart + limit);
// Shaping needs to take into account context up to metric boundaries,
// but rendering needs to take into account character style boundaries.
@@ -985,17 +975,18 @@ class TextLine {
TextPaint wp = mWorkPaint;
wp.set(mPaint);
- inext = metricAffectingSpans.getNextTransition(mStart + i, mStart + limit) - mStart;
+ inext = mMetricAffectingSpanSpanSet.getNextTransition(mStart + i, mStart + limit) -
+ mStart;
int mlimit = Math.min(inext, measureLimit);
ReplacementSpan replacement = null;
- for (int j = 0; j < metricAffectingSpans.numberOfSpans; j++) {
+ for (int j = 0; j < mMetricAffectingSpanSpanSet.numberOfSpans; j++) {
// Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT
// empty by construction. This special case in getSpans() explains the >= & <= tests
- if ((metricAffectingSpans.spanStarts[j] >= mStart + mlimit) ||
- (metricAffectingSpans.spanEnds[j] <= mStart + i)) continue;
- MetricAffectingSpan span = metricAffectingSpans.spans[j];
+ if ((mMetricAffectingSpanSpanSet.spanStarts[j] >= mStart + mlimit) ||
+ (mMetricAffectingSpanSpanSet.spanEnds[j] <= mStart + i)) continue;
+ MetricAffectingSpan span = mMetricAffectingSpanSpanSet.spans[j];
if (span instanceof ReplacementSpan) {
replacement = (ReplacementSpan)span;
} else {
@@ -1016,16 +1007,16 @@ class TextLine {
y, bottom, fmi, needWidth || mlimit < measureLimit);
} else {
for (int j = i, jnext; j < mlimit; j = jnext) {
- jnext = characterStyleSpans.getNextTransition(mStart + j, mStart + mlimit) -
+ jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
mStart;
wp.set(mPaint);
- for (int k = 0; k < characterStyleSpans.numberOfSpans; k++) {
+ for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
// Intentionally using >= and <= as explained above
- if ((characterStyleSpans.spanStarts[k] >= mStart + jnext) ||
- (characterStyleSpans.spanEnds[k] <= mStart + j)) continue;
+ if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+ (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
- CharacterStyle span = characterStyleSpans.spans[k];
+ CharacterStyle span = mCharacterStyleSpanSet.spans[k];
span.updateDrawState(wp);
}