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.Matrix;
20c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.graphics.RectF;
21c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.os.Parcel;
22c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.os.Parcelable;
23c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.text.Layout;
24a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawaimport android.text.SpannedString;
25a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawaimport android.text.TextUtils;
26c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
27c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
28c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawaimport java.util.Objects;
29c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
30c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa/**
31c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * Positional information about the text insertion point and characters in the composition string.
32c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa *
33c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * <p>This class encapsulates locations of the text insertion point and the composition string in
34c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * the screen coordinates so that IMEs can render their UI components near where the text is
35c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa * actually inserted.</p>
36c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa */
37c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawapublic final class CursorAnchorInfo implements Parcelable {
385f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    /**
395f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * The index of the first character of the selected text (inclusive). {@code -1} when there is
405f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * no text selection.
415f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
42c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final int mSelectionStart;
435f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    /**
445f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * The index of the first character of the selected text (exclusive). {@code -1} when there is
455f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * no text selection.
465f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
47c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final int mSelectionEnd;
4881f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa
495f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    /**
505f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * The index of the first character of the composing text (inclusive). {@code -1} when there is
515f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * no composing text.
525f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
5381f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa    private final int mComposingTextStart;
5481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa    /**
5581f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa     * The text, tracked as a composing region.
5681f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa     */
57a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa    private final CharSequence mComposingText;
58c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
59c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
60cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     * Flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for example.
610b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa     */
62cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    private final int mInsertionMarkerFlags;
630b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa    /**
64c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Horizontal position of the insertion marker, in the local coordinates that will be
65c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * transformed with the transformation matrix when rendered on the screen. This should be
66c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * calculated or compatible with {@link Layout#getPrimaryHorizontal(int)}. This can be
67c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} when no value is specified.
68c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
69c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final float mInsertionMarkerHorizontal;
70c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
71c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Vertical position of the insertion marker, in the local coordinates that will be
72c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * transformed with the transformation matrix when rendered on the screen. This should be
73c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * calculated or compatible with {@link Layout#getLineTop(int)}. This can be
74c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} when no value is specified.
75c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
76c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final float mInsertionMarkerTop;
77c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
78c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Vertical position of the insertion marker, in the local coordinates that will be
79c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * transformed with the transformation matrix when rendered on the screen. This should be
80c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * calculated or compatible with {@link Layout#getLineBaseline(int)}. This can be
81c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} when no value is specified.
82c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
83c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final float mInsertionMarkerBaseline;
84c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
85c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Vertical position of the insertion marker, in the local coordinates that will be
86c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * transformed with the transformation matrix when rendered on the screen. This should be
87c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * calculated or compatible with {@link Layout#getLineBottom(int)}. This can be
88c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} when no value is specified.
89c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
90c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final float mInsertionMarkerBottom;
91c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
92c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
93c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Container of rectangular position of characters, keyed with character index in a unit of
94c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Java chars, in the local coordinates that will be transformed with the transformation matrix
95c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * when rendered on the screen.
96c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
975f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    private final SparseRectFArray mCharacterBoundsArray;
98c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
99c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
100c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Transformation matrix that is applied to any positional information of this class to
101c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * transform local coordinates into screen coordinates.
102c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
103c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    private final Matrix mMatrix;
104c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
105cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    /**
1065f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
107cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     * insertion marker or character bounds have at least one visible region.
108cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     */
109cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
110cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa
111cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    /**
1125f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
113cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     * insertion marker or character bounds have at least one invisible (clipped) region.
114cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     */
115cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
116cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa
117cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    /**
1185f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
1195f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * insertion marker or character bounds is placed at right-to-left (RTL) character.
1205f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
1215f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    public static final int FLAG_IS_RTL = 0x04;
1225f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa
123c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public CursorAnchorInfo(final Parcel source) {
124c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mSelectionStart = source.readInt();
125c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mSelectionEnd = source.readInt();
12681f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        mComposingTextStart = source.readInt();
127a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa        mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
128cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        mInsertionMarkerFlags = source.readInt();
129c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerHorizontal = source.readFloat();
130c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerTop = source.readFloat();
131c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerBaseline = source.readFloat();
132c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerBottom = source.readFloat();
1335f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
134c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mMatrix = new Matrix();
135c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mMatrix.setValues(source.createFloatArray());
136c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
137c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
138c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
139c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Used to package this object into a {@link Parcel}.
140c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     *
141c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @param dest The {@link Parcel} to be written.
142c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @param flags The flags used for parceling.
143c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
144c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
145c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public void writeToParcel(Parcel dest, int flags) {
146c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeInt(mSelectionStart);
147c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeInt(mSelectionEnd);
14881f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        dest.writeInt(mComposingTextStart);
149a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa        TextUtils.writeToParcel(mComposingText, dest, flags);
150cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        dest.writeInt(mInsertionMarkerFlags);
151c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloat(mInsertionMarkerHorizontal);
152c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloat(mInsertionMarkerTop);
153c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloat(mInsertionMarkerBaseline);
154c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloat(mInsertionMarkerBottom);
1555f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        dest.writeParcelable(mCharacterBoundsArray, flags);
156c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final float[] matrixArray = new float[9];
157c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mMatrix.getValues(matrixArray);
158c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        dest.writeFloatArray(matrixArray);
159c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
160c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
161c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
162c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int hashCode(){
16381f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
16481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa                + mInsertionMarkerBaseline + mInsertionMarkerBottom;
165c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
16681f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash *= 31;
167cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        hash += mInsertionMarkerFlags;
1680b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa        hash *= 31;
16981f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
17081f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash *= 31;
17181f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash += Objects.hashCode(mComposingText);
17281f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash *= 31;
1735f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        hash += Objects.hashCode(mCharacterBoundsArray);
17481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash *= 31;
17581f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        hash += Objects.hashCode(mMatrix);
176c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return hash;
177c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
178c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
179eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa    /**
180eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * Compares two float values. Returns {@code true} if {@code a} and {@code b} are
181eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * {@link Float#NaN} at the same time.
182eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     */
183eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa    private static boolean areSameFloatImpl(final float a, final float b) {
184eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        if (Float.isNaN(a) && Float.isNaN(b)) {
185eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa            return true;
186eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        }
187eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        return a == b;
188eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa    }
189eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa
190c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
191c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public boolean equals(Object obj){
192c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (obj == null) {
193c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
194c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
195c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (this == obj) {
196c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return true;
197c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
198c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (!(obj instanceof CursorAnchorInfo)) {
199c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
200c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
201c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        final CursorAnchorInfo that = (CursorAnchorInfo) obj;
202c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (hashCode() != that.hashCode()) {
203c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
204c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
205eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        if (mSelectionStart != that.mSelectionStart || mSelectionEnd != that.mSelectionEnd) {
206eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa            return false;
207eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        }
208eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        if (mComposingTextStart != that.mComposingTextStart
209eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa                || !Objects.equals(mComposingText, that.mComposingText)) {
210eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa            return false;
211eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa        }
212cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
2130b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                || !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
214eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa                || !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
215eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa                || !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline)
216eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa                || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
21781f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            return false;
21881f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        }
2195f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
220c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
221c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
222c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        if (!Objects.equals(mMatrix, that.mMatrix)) {
223c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return false;
224c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
225c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return true;
226c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
227c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
228c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
229c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public String toString() {
230c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
23181f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa                + " mComposingTextStart=" + mComposingTextStart
23281f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa                + " mComposingText=" + Objects.toString(mComposingText)
233cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa                + " mInsertionMarkerFlags=" + mInsertionMarkerFlags
234c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
235c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                + " mInsertionMarkerTop=" + mInsertionMarkerTop
236c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
237c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                + " mInsertionMarkerBottom=" + mInsertionMarkerBottom
2385f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
23981f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa                + " mMatrix=" + Objects.toString(mMatrix)
240c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa                + "}";
241c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
242c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
243c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
244c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
245c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
246c46b5f04aa2a9fd292c117d2824f70fcf06e86baYohei Yukawa    public static final class Builder {
2475f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private int mSelectionStart = -1;
2485f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private int mSelectionEnd = -1;
2495f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private int mComposingTextStart = -1;
2505f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private CharSequence mComposingText = null;
2515f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private float mInsertionMarkerHorizontal = Float.NaN;
2525f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private float mInsertionMarkerTop = Float.NaN;
2535f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private float mInsertionMarkerBaseline = Float.NaN;
2545f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private float mInsertionMarkerBottom = Float.NaN;
2555f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private int mInsertionMarkerFlags = 0;
2565f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
2575f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
2585f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        private boolean mMatrixInitialized = false;
2595f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa
260c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
261c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Sets the text range of the selection. Calling this can be skipped if there is no
262c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * selection.
263c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
264c46b5f04aa2a9fd292c117d2824f70fcf06e86baYohei Yukawa        public Builder setSelectionRange(final int newStart, final int newEnd) {
265c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mSelectionStart = newStart;
266c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mSelectionEnd = newEnd;
267c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return this;
268c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
269c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
270c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
27181f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa         * Sets the text range of the composing text. Calling this can be skipped if there is
27281f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa         * no composing text.
273bb9f624252174afa49359ed2a90ec06113adff35Yohei Yukawa         * @param composingTextStart index where the composing text starts.
27481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa         * @param composingText the entire composing text.
275c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
276bb9f624252174afa49359ed2a90ec06113adff35Yohei Yukawa        public Builder setComposingText(final int composingTextStart,
277bb9f624252174afa49359ed2a90ec06113adff35Yohei Yukawa            final CharSequence composingText) {
278bb9f624252174afa49359ed2a90ec06113adff35Yohei Yukawa            mComposingTextStart = composingTextStart;
27981f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            if (composingText == null) {
28081f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa                mComposingText = null;
28181f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            } else {
282a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa                // Make a snapshot of the given char sequence.
283a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa                mComposingText = new SpannedString(composingText);
28481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            }
285c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return this;
286c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
287c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
288c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
289c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Sets the location of the text insertion point (zero width cursor) as a rectangle in
290c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * local coordinates. Calling this can be skipped when there is no text insertion point;
291c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * however if there is an insertion point, editors must call this method.
292c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param horizontalPosition horizontal position of the insertion marker, in the local
293c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * coordinates that will be transformed with the transformation matrix when rendered on the
294c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * screen. This should be calculated or compatible with
295c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * {@link Layout#getPrimaryHorizontal(int)}.
296c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param lineTop vertical position of the insertion marker, in the local coordinates that
297c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * will be transformed with the transformation matrix when rendered on the screen. This
298c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * should be calculated or compatible with {@link Layout#getLineTop(int)}.
299c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param lineBaseline vertical position of the insertion marker, in the local coordinates
300c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * that will be transformed with the transformation matrix when rendered on the screen. This
301c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * should be calculated or compatible with {@link Layout#getLineBaseline(int)}.
302c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param lineBottom vertical position of the insertion marker, in the local coordinates
303c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * that will be transformed with the transformation matrix when rendered on the screen. This
304c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * should be calculated or compatible with {@link Layout#getLineBottom(int)}.
305cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa         * @param flags flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for
306cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa         * example.
307c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
308c46b5f04aa2a9fd292c117d2824f70fcf06e86baYohei Yukawa        public Builder setInsertionMarkerLocation(final float horizontalPosition,
3090b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa                final float lineTop, final float lineBaseline, final float lineBottom,
310cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa                final int flags){
311c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerHorizontal = horizontalPosition;
312c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerTop = lineTop;
313c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerBaseline = lineBaseline;
314c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerBottom = lineBottom;
315cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa            mInsertionMarkerFlags = flags;
316c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return this;
317c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
3185f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa
3195f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        /**
3205f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * Adds the bounding box of the character specified with the index.
3215f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         *
3225f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param index index of the character in Java chars units. Must be specified in
3235f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * ascending order across successive calls.
3245f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param left x coordinate of the left edge of the character in local coordinates.
3255f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param top y coordinate of the top edge of the character in local coordinates.
3265f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param right x coordinate of the right edge of the character in local coordinates.
3275f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param bottom y coordinate of the bottom edge of the character in local coordinates.
3285f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION},
3295f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be
3305f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * specified when necessary.
3315f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * @throws IllegalArgumentException If the index is a negative value, or not greater than
3325f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         * all of the previously called indices.
3335f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa         */
3345f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        public Builder addCharacterBounds(final int index, final float left, final float top,
3355f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                final float right, final float bottom, final int flags) {
3365f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            if (index < 0) {
3375f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                throw new IllegalArgumentException("index must not be a negative integer.");
3385f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            }
3395f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            if (mCharacterBoundsArrayBuilder == null) {
3405f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder();
3415f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            }
3425f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags);
3435f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            return this;
3445f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        }
345c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
346c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
347c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Sets the matrix that transforms local coordinates into screen coordinates.
348c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * @param matrix transformation matrix from local coordinates into screen coordinates. null
349c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * is interpreted as an identity matrix.
350c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
351c46b5f04aa2a9fd292c117d2824f70fcf06e86baYohei Yukawa        public Builder setMatrix(final Matrix matrix) {
352419b1b0498e33a556780be1702b444d54fcaa7ddYohei Yukawa            mMatrix.set(matrix != null ? matrix : Matrix.IDENTITY_MATRIX);
353b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa            mMatrixInitialized = true;
354c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return this;
355c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
356c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
357c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
358b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa         * @return {@link CursorAnchorInfo} using parameters in this {@link Builder}.
359b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa         * @throws IllegalArgumentException if one or more positional parameters are specified but
360b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa         * the coordinate transformation matrix is not provided via {@link #setMatrix(Matrix)}.
361c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
362c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public CursorAnchorInfo build() {
363b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa            if (!mMatrixInitialized) {
3645f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                // Coordinate transformation matrix is mandatory when at least one positional
3655f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                // parameter is specified.
3665f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null
3675f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                        && !mCharacterBoundsArrayBuilder.isEmpty());
3685f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                if (hasCharacterBounds
3695f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                        || !Float.isNaN(mInsertionMarkerHorizontal)
3705f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                        || !Float.isNaN(mInsertionMarkerTop)
3715f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                        || !Float.isNaN(mInsertionMarkerBaseline)
3725f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                        || !Float.isNaN(mInsertionMarkerBottom)) {
373b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa                    throw new IllegalArgumentException("Coordinate transformation matrix is " +
374b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa                            "required when positional parameters are specified.");
375b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa                }
376b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa            }
377c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return new CursorAnchorInfo(this);
378c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
379c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
380c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        /**
381c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * Resets the internal state so that this instance can be reused to build another
382c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         * instance of {@link CursorAnchorInfo}.
383c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa         */
384c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public void reset() {
385c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mSelectionStart = -1;
386c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mSelectionEnd = -1;
38781f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            mComposingTextStart = -1;
38881f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa            mComposingText = null;
389cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa            mInsertionMarkerFlags = 0;
390c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerHorizontal = Float.NaN;
391c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerTop = Float.NaN;
392c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerBaseline = Float.NaN;
393c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            mInsertionMarkerBottom = Float.NaN;
394419b1b0498e33a556780be1702b444d54fcaa7ddYohei Yukawa            mMatrix.set(Matrix.IDENTITY_MATRIX);
395b5268dcc17cd9ecb540b06ad59bd74188b57a069Yohei Yukawa            mMatrixInitialized = false;
3965f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            if (mCharacterBoundsArrayBuilder != null) {
3975f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                mCharacterBoundsArrayBuilder.reset();
398c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            }
399c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
400c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
401c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
402c46b5f04aa2a9fd292c117d2824f70fcf06e86baYohei Yukawa    private CursorAnchorInfo(final Builder builder) {
403c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mSelectionStart = builder.mSelectionStart;
404c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mSelectionEnd = builder.mSelectionEnd;
40581f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        mComposingTextStart = builder.mComposingTextStart;
40681f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        mComposingText = builder.mComposingText;
407cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        mInsertionMarkerFlags = builder.mInsertionMarkerFlags;
408c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
409c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerTop = builder.mInsertionMarkerTop;
410c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
411c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
4125f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
4135f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa                builder.mCharacterBoundsArrayBuilder.build() : null;
414419b1b0498e33a556780be1702b444d54fcaa7ddYohei Yukawa        mMatrix = new Matrix(builder.mMatrix);
415c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
416c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
417c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
418c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the index where the selection starts.
419eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * @return {@code -1} if there is no selection.
420c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
421c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int getSelectionStart() {
422c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mSelectionStart;
423c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
424c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
425c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
426c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the index where the selection ends.
427eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * @return {@code -1} if there is no selection.
428c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
429c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int getSelectionEnd() {
430c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mSelectionEnd;
431c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
432c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
433c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
43481f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa     * Returns the index where the composing text starts.
435eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * @return {@code -1} if there is no composing text.
436c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
43781f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa    public int getComposingTextStart() {
43881f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        return mComposingTextStart;
439c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
440c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
441c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
44281f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa     * Returns the entire composing text.
443eea0b8b051e916051d0d09da3f41f9ec4d508bffYohei Yukawa     * @return {@code null} if there is no composition.
444c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
445a1fda005f9583486f4372ecbb0eec503ee9cece8Yohei Yukawa    public CharSequence getComposingText() {
44681f4cb3f858f46a4d9b793c4d326b9bf6aca868dYohei Yukawa        return mComposingText;
447c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
448c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
449c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
450cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     * Returns the flag of the insertion marker.
451cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     * @return the flag of the insertion marker. {@code 0} if no flag is specified.
452cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa     */
453cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    public int getInsertionMarkerFlags() {
454cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa        return mInsertionMarkerFlags;
455cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    }
456cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa
457cc24e2b6a2a429d70b75c6810a5cfd8816ce03adYohei Yukawa    /**
458c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the horizontal start of the insertion marker, in the local coordinates that will
459c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * be transformed with {@link #getMatrix()} when rendered on the screen.
460c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @return x coordinate that is compatible with {@link Layout#getPrimaryHorizontal(int)}.
461c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Pay special care to RTL/LTR handling.
462c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} if not specified.
463c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @see Layout#getPrimaryHorizontal(int)
464c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
465c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public float getInsertionMarkerHorizontal() {
466c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mInsertionMarkerHorizontal;
467c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
4680b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa
469c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
470c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the vertical top position of the insertion marker, in the local coordinates that
471c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * will be transformed with {@link #getMatrix()} when rendered on the screen.
472c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @return y coordinate that is compatible with {@link Layout#getLineTop(int)}.
473c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} if not specified.
474c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
475c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public float getInsertionMarkerTop() {
476c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mInsertionMarkerTop;
477c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
4780b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa
479c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
480c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the vertical baseline position of the insertion marker, in the local coordinates
481c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
482c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @return y coordinate that is compatible with {@link Layout#getLineBaseline(int)}.
483c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} if not specified.
484c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
485c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public float getInsertionMarkerBaseline() {
486c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mInsertionMarkerBaseline;
487c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
4880b01e7fc58cdde00d8350285a3386c4209b72d78Yohei Yukawa
489c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
490c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns the vertical bottom position of the insertion marker, in the local coordinates
491c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
492c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @return y coordinate that is compatible with {@link Layout#getLineBottom(int)}.
493c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * {@code java.lang.Float.NaN} if not specified.
494c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
495c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public float getInsertionMarkerBottom() {
496c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return mInsertionMarkerBottom;
497c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
498c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
499c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
500c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns a new instance of {@link RectF} that indicates the location of the character
501c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * specified with the index.
5025f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * @param index index of the character in a Java chars.
5035f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * @return the character bounds in local coordinates as a new instance of {@link RectF}.
5045f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
5055f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    public RectF getCharacterBounds(final int index) {
5065f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        if (mCharacterBoundsArray == null) {
5075f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            return null;
5085f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        }
5095f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        return mCharacterBoundsArray.get(index);
5105f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    }
5115f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa
5125f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    /**
5135f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * Returns the flags associated with the character bounds specified with the index.
5145f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * @param index index of the character in a Java chars.
5155f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     * @return {@code 0} if no flag is specified.
5165f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa     */
5175f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa    public int getCharacterBoundsFlags(final int index) {
5185f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        if (mCharacterBoundsArray == null) {
5195f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa            return 0;
520c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
5215f183f0671dfa1d87ca6d741deb457170c432493Yohei Yukawa        return mCharacterBoundsArray.getFlags(index, 0);
522c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
523c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
524c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
525c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
526c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * matrix that is to be applied other positional data in this class.
527c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * @return a new instance (copy) of the transformation matrix.
528c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
529c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public Matrix getMatrix() {
530c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return new Matrix(mMatrix);
531c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
532c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
533c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    /**
534c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     * Used to make this class parcelable.
535c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa     */
536c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public static final Parcelable.Creator<CursorAnchorInfo> CREATOR
537c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            = new Parcelable.Creator<CursorAnchorInfo>() {
538c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        @Override
539c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public CursorAnchorInfo createFromParcel(Parcel source) {
540c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return new CursorAnchorInfo(source);
541c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
542c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
543c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        @Override
544c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        public CursorAnchorInfo[] newArray(int size) {
545c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa            return new CursorAnchorInfo[size];
546c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        }
547c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    };
548c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa
549c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    @Override
550c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    public int describeContents() {
551c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa        return 0;
552c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa    }
553c2ddd6023688db5ecf6c586e05f55e262b4a802eYohei Yukawa}
554