diff options
author | Gilles Debunne <debunne@google.com> | 2011-12-08 17:58:24 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-12-08 17:58:24 -0800 |
commit | 316ca5059ebd7270a04da5649d25653c355e158d (patch) | |
tree | 758797e46ab40c386dd3cee31423d00c551b98dd | |
parent | 556e4ca54161be17333ec98fadc113485120a6e8 (diff) | |
parent | c1f44830809f0a8526855f13822702ea756214fa (diff) | |
download | frameworks_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.java | 105 |
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); } |