• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.text;
18 
19 import java.lang.reflect.Array;
20 
21 /**
22  * A cached set of spans. Caches the result of {@link Spanned#getSpans(int, int, Class)} and then
23  * provides faster access to {@link Spanned#nextSpanTransition(int, int, Class)}.
24  *
25  * Fields are left public for a convenient direct access.
26  *
27  * Note that empty spans are ignored by this class.
28  * @hide
29  */
30 public class SpanSet<E> {
31     private final Class<? extends E> classType;
32 
33     int numberOfSpans;
34     E[] spans;
35     int[] spanStarts;
36     int[] spanEnds;
37     int[] spanFlags;
38 
SpanSet(Class<? extends E> type)39     SpanSet(Class<? extends E> type) {
40         classType = type;
41         numberOfSpans = 0;
42     }
43 
44     @SuppressWarnings("unchecked")
init(Spanned spanned, int start, int limit)45     public void init(Spanned spanned, int start, int limit) {
46         final E[] allSpans = spanned.getSpans(start, limit, classType);
47         final int length = allSpans.length;
48 
49         if (length > 0 && (spans == null || spans.length < length)) {
50             // These arrays may end up being too large because of the discarded empty spans
51             spans = (E[]) Array.newInstance(classType, length);
52             spanStarts = new int[length];
53             spanEnds = new int[length];
54             spanFlags = new int[length];
55         }
56 
57         numberOfSpans = 0;
58         for (int i = 0; i < length; i++) {
59             final E span = allSpans[i];
60 
61             final int spanStart = spanned.getSpanStart(span);
62             final int spanEnd = spanned.getSpanEnd(span);
63             if (spanStart == spanEnd) continue;
64 
65             final int spanFlag = spanned.getSpanFlags(span);
66 
67             spans[numberOfSpans] = span;
68             spanStarts[numberOfSpans] = spanStart;
69             spanEnds[numberOfSpans] = spanEnd;
70             spanFlags[numberOfSpans] = spanFlag;
71 
72             numberOfSpans++;
73         }
74     }
75 
76     /**
77      * Returns true if there are spans intersecting the given interval.
78      * @param end must be strictly greater than start
79      */
hasSpansIntersecting(int start, int end)80     public boolean hasSpansIntersecting(int start, int end) {
81         for (int i = 0; i < numberOfSpans; i++) {
82             // equal test is valid since both intervals are not empty by construction
83             if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
84             return true;
85         }
86         return false;
87     }
88 
89     /**
90      * Similar to {@link Spanned#nextSpanTransition(int, int, Class)}
91      */
getNextTransition(int start, int limit)92     int getNextTransition(int start, int limit) {
93         for (int i = 0; i < numberOfSpans; i++) {
94             final int spanStart = spanStarts[i];
95             final int spanEnd = spanEnds[i];
96             if (spanStart > start && spanStart < limit) limit = spanStart;
97             if (spanEnd > start && spanEnd < limit) limit = spanEnd;
98         }
99         return limit;
100     }
101 
102     /**
103      * Removes all internal references to the spans to avoid memory leaks.
104      */
recycle()105     public void recycle() {
106         // The spans array is guaranteed to be not null when numberOfSpans is > 0
107         for (int i = 0; i < numberOfSpans; i++) {
108             spans[i] = null; // prevent a leak: no reference kept when TextLine is recycled
109         }
110     }
111 }
112