1c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa/*
2c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * Copyright (C) 2014 The Android Open Source Project
3c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa *
4c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * use this file except in compliance with the License. You may obtain a copy of
6c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * the License at
7c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa *
8c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * http://www.apache.org/licenses/LICENSE-2.0
9c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa *
10c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * Unless required by applicable law or agreed to in writing, software
11c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * License for the specific language governing permissions and limitations under
14c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * the License.
15c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa */
16c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
17c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawapackage android.view.inputmethod;
18c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
19c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.graphics.RectF;
20c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.os.Parcel;
21c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.os.Parcelable;
22c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
23c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport java.util.Arrays;
24c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
25c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa/**
26c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * An implementation of SparseArray specialized for {@link android.graphics.RectF}.
27c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * <p>
28c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * As this is a sparse array, it represents an array of {@link RectF} most of which are null. This
29c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * class could be in some other packages like android.graphics or android.util but currently
30c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * belong to android.view.inputmethod because this class is hidden and used only in input method
31c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * framework.
32c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * </p>
33c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * @hide
34c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa */
35c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawapublic final class SparseRectFArray implements Parcelable {
36c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
37c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * The keys, in ascending order, of those {@link RectF} that are not null. For example,
38c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code [null, null, null, Rect1, null, Rect2]} would be represented by {@code [3,5]}.
39c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @see #mCoordinates
40c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
41c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final int[] mKeys;
42c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
43c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
44c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Stores coordinates of the rectangles, in the order of
45c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code rects[mKeys[0]].left}, {@code rects[mKeys[0]].top},
46c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code rects[mKeys[0]].right}, {@code rects[mKeys[0]].bottom},
47c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code rects[mKeys[1]].left}, {@code rects[mKeys[1]].top},
48c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code rects[mKeys[1]].right}, {@code rects[mKeys[1]].bottom},
49c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code rects[mKeys[2]].left}, {@code rects[mKeys[2]].top}, ....
50c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
51c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final float[] mCoordinates;
52c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
530b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa    /**
540b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa     * Stores visibility information.
550b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa     */
560b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa    private final int[] mFlagsArray;
570b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa
58c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public SparseRectFArray(final Parcel source) {
59c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mKeys = source.createIntArray();
60c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mCoordinates = source.createFloatArray();
610b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        mFlagsArray = source.createIntArray();
62c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
63c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
64c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
65c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Used to package this object into a {@link Parcel}.
66c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     *
67c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @param dest The {@link Parcel} to be written.
68c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @param flags The flags used for parceling.
69c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
70c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
71c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public void writeToParcel(Parcel dest, int flags) {
72c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeIntArray(mKeys);
73c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloatArray(mCoordinates);
740b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        dest.writeIntArray(mFlagsArray);
75c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
76c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
77c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
78c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int hashCode() {
79c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        // TODO: Improve the hash function.
80c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (mKeys == null || mKeys.length == 0) {
81c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return 0;
82c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
83c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        int hash = mKeys.length;
84c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        // For performance reasons, only the first rectangle is used for the hash code now.
85c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        for (int i = 0; i < 4; i++) {
86c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            hash *= 31;
87c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            hash += mCoordinates[i];
88c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
890b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        hash *= 31;
900b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        hash += mFlagsArray[0];
91c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return hash;
92c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
93c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
94c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
95c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public boolean equals(Object obj){
96c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (obj == null) {
97c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
98c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
99c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (this == obj) {
100c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return true;
101c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
102c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (!(obj instanceof SparseRectFArray)) {
103c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
104c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
105c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final SparseRectFArray that = (SparseRectFArray) obj;
106c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
1070b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates)
1080b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                && Arrays.equals(mFlagsArray, that.mFlagsArray);
109c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
110c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
111c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
112c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public String toString() {
1130b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        if (mKeys == null || mCoordinates == null || mFlagsArray == null) {
114c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return "SparseRectFArray{}";
115c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
116c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final StringBuilder sb = new StringBuilder();
117c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        sb.append("SparseRectFArray{");
118c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        for (int i = 0; i < mKeys.length; i++) {
119c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (i != 0) {
120c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                sb.append(", ");
121c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
122c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            final int baseIndex = i * 4;
123c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(mKeys[i]);
124c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(":[");
125c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(mCoordinates[baseIndex + 0]);
126c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(",");
127c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(mCoordinates[baseIndex + 1]);
128c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append("],[");
129c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(mCoordinates[baseIndex + 2]);
130c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(",");
131c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            sb.append(mCoordinates[baseIndex + 3]);
1320b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            sb.append("]:flagsArray=");
1330b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            sb.append(mFlagsArray[i]);
134c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
135c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        sb.append("}");
136c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return sb.toString();
137c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
138c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
139c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
140c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Builder for {@link SparseRectFArray}. This class is not designed to be thread-safe.
141c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @hide
142c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
143c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public static final class SparseRectFArrayBuilder {
144c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
145c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Throws {@link IllegalArgumentException} to make sure that this class is correctly used.
146c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param key key to be checked.
147c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
148c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private void checkIndex(final int key) {
149c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mCount == 0) {
150c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                return;
151c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
152c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mKeys[mCount - 1] >= key) {
153c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                throw new IllegalArgumentException("key must be greater than all existing keys.");
154c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
155c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
156c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
157c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
158c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Extends the internal array if necessary.
159c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
160c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private void ensureBufferSize() {
161c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mKeys == null) {
162c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mKeys = new int[INITIAL_SIZE];
163c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
164c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mCoordinates == null) {
165c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates = new float[INITIAL_SIZE * 4];
166c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
1670b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            if (mFlagsArray == null) {
1680b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                mFlagsArray = new int[INITIAL_SIZE];
1690b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            }
170c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            final int requiredIndexArraySize = mCount + 1;
171c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mKeys.length <= requiredIndexArraySize) {
172c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                final int[] newArray = new int[requiredIndexArraySize * 2];
173c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                System.arraycopy(mKeys, 0, newArray, 0, mCount);
174c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mKeys = newArray;
175c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
176c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            final int requiredCoordinatesArraySize = (mCount + 1) * 4;
177c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mCoordinates.length <= requiredCoordinatesArraySize) {
178c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                final float[] newArray = new float[requiredCoordinatesArraySize * 2];
179c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4);
180c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates = newArray;
181c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
1820b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            final int requiredFlagsArraySize = requiredIndexArraySize;
1830b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            if (mFlagsArray.length <= requiredFlagsArraySize) {
1840b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                final int[] newArray = new int[requiredFlagsArraySize * 2];
1850b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                System.arraycopy(mFlagsArray, 0, newArray, 0, mCount);
1860b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                mFlagsArray = newArray;
1870b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            }
188c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
189c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
190c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
191c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Puts the rectangle with an integer key.
192c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param key the key to be associated with the rectangle. It must be greater than all
193c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * existing keys that have been previously specified.
194c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param left left of the rectangle.
195c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param top top of the rectangle.
196c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param right right of the rectangle.
197c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param bottom bottom of the rectangle.
1980b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa         * @param flags an arbitrary integer value to be associated with this rectangle.
199c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @return the receiver object itself for chaining method calls.
200c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @throws IllegalArgumentException If the index is not greater than all of existing keys.
201c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
202c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public SparseRectFArrayBuilder append(final int key,
2030b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                final float left, final float top, final float right, final float bottom,
2040b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                final int flags) {
205c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            checkIndex(key);
206c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            ensureBufferSize();
207c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            final int baseCoordinatesIndex = mCount * 4;
208c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates[baseCoordinatesIndex + 0] = left;
209c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates[baseCoordinatesIndex + 1] = top;
210c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates[baseCoordinatesIndex + 2] = right;
211c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates[baseCoordinatesIndex + 3] = bottom;
2120b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            final int flagsIndex = mCount;
2130b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            mFlagsArray[flagsIndex] = flags;
214c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mKeys[mCount] = key;
215c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            ++mCount;
216c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return this;
217c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
218c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private int mCount = 0;
219c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private int[] mKeys = null;
220c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private float[] mCoordinates = null;
2210b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        private int[] mFlagsArray = null;
222c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        private static int INITIAL_SIZE = 16;
223c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
224b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa        public boolean isEmpty() {
225b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa            return mCount <= 0;
226b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa        }
227b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa
228c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
229c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @return {@link SparseRectFArray} using parameters in this {@link SparseRectFArray}.
230c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
231c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public SparseRectFArray build() {
232c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return new SparseRectFArray(this);
233c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
234c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
235c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public void reset() {
236c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            if (mCount == 0) {
237c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mKeys = null;
238c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates = null;
2390b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                mFlagsArray = null;
240c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
241c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCount = 0;
242c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
243c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
244c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
245c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private SparseRectFArray(final SparseRectFArrayBuilder builder) {
246c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (builder.mCount == 0) {
247c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mKeys = null;
248c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates = null;
2490b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            mFlagsArray = null;
250c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        } else {
251c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mKeys = new int[builder.mCount];
252c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mCoordinates = new float[builder.mCount * 4];
2530b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            mFlagsArray = new int[builder.mCount];
254c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount);
255c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4);
2560b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            System.arraycopy(builder.mFlagsArray, 0, mFlagsArray, 0, builder.mCount);
257c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
258c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
259c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
260c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public RectF get(final int index) {
261c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (mKeys == null) {
262c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return null;
263c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
264c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (index < 0) {
265c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return null;
266c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
267c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final int arrayIndex = Arrays.binarySearch(mKeys, index);
268c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (arrayIndex < 0) {
269c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return null;
270c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
271c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final int baseCoordIndex = arrayIndex * 4;
272c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return new RectF(mCoordinates[baseCoordIndex],
273c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates[baseCoordIndex + 1],
274c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates[baseCoordIndex + 2],
275c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                mCoordinates[baseCoordIndex + 3]);
276c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
277c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
2780b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa    public int getFlags(final int index, final int valueIfKeyNotFound) {
2790b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        if (mKeys == null) {
2800b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            return valueIfKeyNotFound;
2810b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        }
2820b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        if (index < 0) {
2830b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            return valueIfKeyNotFound;
2840b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        }
2850b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        final int arrayIndex = Arrays.binarySearch(mKeys, index);
2860b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        if (arrayIndex < 0) {
2870b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa            return valueIfKeyNotFound;
2880b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        }
2890b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        return mFlagsArray[arrayIndex];
2900b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa    }
2910b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa
292c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
293c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Used to make this class parcelable.
294c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
295c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public static final Parcelable.Creator<SparseRectFArray> CREATOR =
296c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            new Parcelable.Creator<SparseRectFArray>() {
297c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                @Override
298c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                public SparseRectFArray createFromParcel(Parcel source) {
299c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                    return new SparseRectFArray(source);
300c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                }
301c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                @Override
302c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                public SparseRectFArray[] newArray(int size) {
303c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                    return new SparseRectFArray[size];
304c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                }
305c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            };
306c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
307c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
308c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int describeContents() {
309c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return 0;
310c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
311c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa}
312c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
313