diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/text/SpanSet.java | 111 | ||||
-rw-r--r-- | core/java/android/text/TextLine.java | 74 |
2 files changed, 111 insertions, 74 deletions
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java new file mode 100644 index 0000000..3ca6033 --- /dev/null +++ b/core/java/android/text/SpanSet.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text; + +import java.lang.reflect.Array; + +/** + * A cached set of spans. Caches the result of {@link Spanned#getSpans(int, int, Class)} and then + * provides faster access to {@link Spanned#nextSpanTransition(int, int, Class)}. + * + * Fields are left public for a convenient direct access. + * + * Note that empty spans are ignored by this class. + * @hide + */ +public class SpanSet<E> { + private final Class<? extends E> classType; + + int numberOfSpans; + E[] spans; + int[] spanStarts; + int[] spanEnds; + int[] spanFlags; + + SpanSet(Class<? extends E> type) { + classType = type; + numberOfSpans = 0; + } + + @SuppressWarnings("unchecked") + public void init(Spanned spanned, int start, int limit) { + final E[] allSpans = spanned.getSpans(start, limit, classType); + final int length = allSpans.length; + + if (length > 0 && (spans == null || spans.length < length)) { + // These arrays may end up being too large because of the discarded empty spans + spans = (E[]) Array.newInstance(classType, length); + spanStarts = new int[length]; + spanEnds = new int[length]; + spanFlags = new int[length]; + } + + numberOfSpans = 0; + for (int i = 0; i < length; i++) { + final E span = allSpans[i]; + + final int spanStart = spanned.getSpanStart(span); + final int spanEnd = spanned.getSpanEnd(span); + if (spanStart == spanEnd) continue; + + final int spanFlag = spanned.getSpanFlags(span); + + spans[numberOfSpans] = span; + spanStarts[numberOfSpans] = spanStart; + spanEnds[numberOfSpans] = spanEnd; + spanFlags[numberOfSpans] = spanFlag; + + numberOfSpans++; + } + } + + /** + * Returns true if there are spans intersecting the given interval. + * @param end must be strictly greater than start + */ + public boolean hasSpansIntersecting(int start, int end) { + for (int i = 0; i < numberOfSpans; i++) { + // equal test is valid since both intervals are not empty by construction + if (spanStarts[i] >= end || spanEnds[i] <= start) continue; + return true; + } + return false; + } + + /** + * Similar to {@link Spanned#nextSpanTransition(int, int, Class)} + */ + int getNextTransition(int start, int limit) { + for (int i = 0; i < numberOfSpans; i++) { + final int spanStart = spanStarts[i]; + final int spanEnd = spanEnds[i]; + if (spanStart > start && spanStart < limit) limit = spanStart; + if (spanEnd > start && spanEnd < limit) limit = spanEnd; + } + return limit; + } + + /** + * Removes all internal references to the spans to avoid memory leaks. + */ + public void recycle() { + // The spans array is guaranteed to be not null when numberOfSpans is > 0 + for (int i = 0; i < numberOfSpans; i++) { + spans[i] = null; // prevent a leak: no reference kept when TextLine is recycled + } + } +} diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 1e8a2f7..0d2835a 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -30,8 +30,6 @@ import android.util.Log; import com.android.internal.util.ArrayUtils; -import java.lang.reflect.Array; - /** * Represents a line of styled text, for measuring in visual order and * for rendering. @@ -860,78 +858,6 @@ class TextLine { return runIsRtl ? -ret : ret; } - private static class SpanSet<E> { - 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") - public void init(Spanned spanned, int start, int limit) { - final E[] allSpans = spanned.getSpans(start, limit, classType); - final int length = allSpans.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]; - } - - numberOfSpans = 0; - for (int i = 0; i < length; i++) { - final E span = allSpans[i]; - - final int spanStart = spanned.getSpanStart(span); - final int spanEnd = spanned.getSpanEnd(span); - if (spanStart == spanEnd) continue; - - final int spanFlag = spanned.getSpanFlags(span); - - spans[numberOfSpans] = span; - spanStarts[numberOfSpans] = spanStart; - spanEnds[numberOfSpans] = spanEnd; - spanFlags[numberOfSpans] = spanFlag; - - numberOfSpans++; - } - } - - public boolean hasSpansIntersecting(int start, int end) { - for (int i = 0; i < numberOfSpans; i++) { - // equal test is valid since both intervals are not empty by construction - if (spanStarts[i] >= end || spanEnds[i] <= start) continue; - return true; - } - return false; - } - - int getNextTransition(int start, int limit) { - for (int i = 0; i < numberOfSpans; i++) { - final int spanStart = spanStarts[i]; - final int spanEnd = spanEnds[i]; - if (spanStart > start && spanStart < limit) limit = spanStart; - if (spanEnd > start && spanEnd < limit) limit = spanEnd; - } - return limit; - } - - public void recycle() { - // The spans array is guaranteed to be not null when numberOfSpans is > 0 - for (int i = 0; i < numberOfSpans; i++) { - spans[i] = null; // prevent a leak: no reference kept when TextLine is recycled - } - } - } - /** * Utility function for handling a unidirectional run. The run must not * contain tabs or emoji but can contain styles. |