Merge "Re-use SpanSets in TextLine" into ics-mr1
This commit is contained in:
committed by
Android (Google) Code Review
commit
316ca5059e
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user