Loading api/current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -34837,6 +34837,7 @@ package android.view.inputmethod { ctor public CursorAnchorInfo(android.os.Parcel); method public int describeContents(); method public android.graphics.RectF getCharacterRect(int); method public int getCharacterRectFlags(int); method public java.lang.CharSequence getComposingText(); method public int getComposingTextStart(); method public float getInsertionMarkerBaseline(); Loading @@ -34846,17 +34847,24 @@ package android.view.inputmethod { method public android.graphics.Matrix getMatrix(); method public int getSelectionEnd(); method public int getSelectionStart(); method public boolean isInsertionMarkerClipped(); method public void writeToParcel(android.os.Parcel, int); field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1 field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3 field public static final int CHARACTER_RECT_TYPE_MASK = 15; // 0xf field public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; // 0x4 field public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; // 0x2 field public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; // 0x0 field public static final android.os.Parcelable.Creator CREATOR; } public static final class CursorAnchorInfo.Builder { ctor public CursorAnchorInfo.Builder(); method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float); method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int); method public android.view.inputmethod.CursorAnchorInfo build(); method public void reset(); method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence); method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float); method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean); method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix); method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int); } core/java/android/view/inputmethod/CursorAnchorInfo.java +78 −7 Original line number Diff line number Diff line Loading @@ -44,6 +44,10 @@ public final class CursorAnchorInfo implements Parcelable { */ private final CharSequence mComposingText; /** * {@code True} if the insertion marker is partially or entirely clipped by other UI elements. */ private final boolean mInsertionMarkerClipped; /** * Horizontal position of the insertion marker, in the local coordinates that will be * transformed with the transformation matrix when rendered on the screen. This should be Loading Loading @@ -86,11 +90,36 @@ public final class CursorAnchorInfo implements Parcelable { */ private final Matrix mMatrix; public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this * character. Editor authors should not use this flag. */ public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible. */ public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible. */ public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible. */ public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle * for this character. Input method authors should ignore the returned rectangle. */ public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; public CursorAnchorInfo(final Parcel source) { mSelectionStart = source.readInt(); mSelectionEnd = source.readInt(); mComposingTextStart = source.readInt(); mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); mInsertionMarkerClipped = (source.readInt() != 0); mInsertionMarkerHorizontal = source.readFloat(); mInsertionMarkerTop = source.readFloat(); mInsertionMarkerBaseline = source.readFloat(); Loading @@ -112,6 +141,7 @@ public final class CursorAnchorInfo implements Parcelable { dest.writeInt(mSelectionEnd); dest.writeInt(mComposingTextStart); TextUtils.writeToParcel(mComposingText, dest, flags); dest.writeInt(mInsertionMarkerClipped ? 1 : 0); dest.writeFloat(mInsertionMarkerHorizontal); dest.writeFloat(mInsertionMarkerTop); dest.writeFloat(mInsertionMarkerBaseline); Loading @@ -129,6 +159,8 @@ public final class CursorAnchorInfo implements Parcelable { + mInsertionMarkerBaseline + mInsertionMarkerBottom; int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash); hash *= 31; hash += (mInsertionMarkerClipped ? 2 : 1); hash *= 31; hash += mSelectionStart + mSelectionEnd + mComposingTextStart; hash *= 31; hash += Objects.hashCode(mComposingText); Loading Loading @@ -172,7 +204,8 @@ public final class CursorAnchorInfo implements Parcelable { || !Objects.equals(mComposingText, that.mComposingText)) { return false; } if (!areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal) if (mInsertionMarkerClipped != that.mInsertionMarkerClipped || !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal) || !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop) || !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline) || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) { Loading @@ -195,6 +228,7 @@ public final class CursorAnchorInfo implements Parcelable { return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd + " mComposingTextStart=" + mComposingTextStart + " mComposingText=" + Objects.toString(mComposingText) + " mInsertionMarkerClipped=" + mInsertionMarkerClipped + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal + " mInsertionMarkerTop=" + mInsertionMarkerTop + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline Loading Loading @@ -256,25 +290,27 @@ public final class CursorAnchorInfo implements Parcelable { * @param lineBottom vertical position of the insertion marker, in the local coordinates * that will be transformed with the transformation matrix when rendered on the screen. This * should be calculated or compatible with {@link Layout#getLineBottom(int)}. * @param clipped {@code true} is the insertion marker is partially or entierly clipped by * other UI elements. */ public Builder setInsertionMarkerLocation(final float horizontalPosition, final float lineTop, final float lineBaseline, final float lineBottom){ final float lineTop, final float lineBaseline, final float lineBottom, final boolean clipped){ mInsertionMarkerHorizontal = horizontalPosition; mInsertionMarkerTop = lineTop; mInsertionMarkerBaseline = lineBaseline; mInsertionMarkerBottom = lineBottom; mInsertionMarkerClipped = clipped; return this; } private float mInsertionMarkerHorizontal = Float.NaN; private float mInsertionMarkerTop = Float.NaN; private float mInsertionMarkerBaseline = Float.NaN; private float mInsertionMarkerBottom = Float.NaN; private boolean mInsertionMarkerClipped = false; /** * Adds the bounding box of the character specified with the index. * <p> * Editor authors should not call this method for characters that are invisible. * </p> * * @param index index of the character in Java chars units. Must be specified in * ascending order across successive calls. Loading @@ -286,19 +322,27 @@ public final class CursorAnchorInfo implements Parcelable { * coordinates, that is, right edge for LTR text and left edge for RTL text. * @param trailingEdgeY y coordinate of the trailing edge of the character in local * coordinates. * @param flags type and flags for this character. See * {@link #CHARACTER_RECT_TYPE_FULLY_VISIBLE} for example. * @throws IllegalArgumentException If the index is a negative value, or not greater than * all of the previously called indices. */ public Builder addCharacterRect(final int index, final float leadingEdgeX, final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY) { final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY, final int flags) { if (index < 0) { throw new IllegalArgumentException("index must not be a negative integer."); } final int type = flags & CHARACTER_RECT_TYPE_MASK; if (type == CHARACTER_RECT_TYPE_UNSPECIFIED) { throw new IllegalArgumentException("Type except for " + "CHARACTER_RECT_TYPE_UNSPECIFIED must be specified."); } if (mCharacterRectBuilder == null) { mCharacterRectBuilder = new SparseRectFArrayBuilder(); } mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX, trailingEdgeY); trailingEdgeY, flags); return this; } private SparseRectFArrayBuilder mCharacterRectBuilder = null; Loading Loading @@ -346,6 +390,7 @@ public final class CursorAnchorInfo implements Parcelable { mSelectionEnd = -1; mComposingTextStart = -1; mComposingText = null; mInsertionMarkerClipped = false; mInsertionMarkerHorizontal = Float.NaN; mInsertionMarkerTop = Float.NaN; mInsertionMarkerBaseline = Float.NaN; Loading @@ -363,6 +408,7 @@ public final class CursorAnchorInfo implements Parcelable { mSelectionEnd = builder.mSelectionEnd; mComposingTextStart = builder.mComposingTextStart; mComposingText = builder.mComposingText; mInsertionMarkerClipped = builder.mInsertionMarkerClipped; mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal; mInsertionMarkerTop = builder.mInsertionMarkerTop; mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline; Loading Loading @@ -404,6 +450,14 @@ public final class CursorAnchorInfo implements Parcelable { return mComposingText; } /** * Returns the visibility of the insertion marker. * @return {@code true} if the insertion marker is partially or entirely clipped. */ public boolean isInsertionMarkerClipped() { return mInsertionMarkerClipped; } /** * Returns the horizontal start of the insertion marker, in the local coordinates that will * be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -415,6 +469,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerHorizontal() { return mInsertionMarkerHorizontal; } /** * Returns the vertical top position of the insertion marker, in the local coordinates that * will be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -424,6 +479,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerTop() { return mInsertionMarkerTop; } /** * Returns the vertical baseline position of the insertion marker, in the local coordinates * that will be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -433,6 +489,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerBaseline() { return mInsertionMarkerBaseline; } /** * Returns the vertical bottom position of the insertion marker, in the local coordinates * that will be transformed with {@link #getMatrix()} when rendered on the screen. Loading Loading @@ -466,6 +523,20 @@ public final class CursorAnchorInfo implements Parcelable { return mCharacterRects.get(index); } /** * Returns the flags associated with the character specified with the index. * @param index index of the character in a Java chars. * @return {@link #CHARACTER_RECT_TYPE_UNSPECIFIED} if no flag is specified. */ // TODO: Prepare a document about the expected behavior for surrogate pairs, combining // characters, and non-graphical chars. public int getCharacterRectFlags(final int index) { if (mCharacterRects == null) { return CHARACTER_RECT_TYPE_UNSPECIFIED; } return mCharacterRects.getFlags(index, CHARACTER_RECT_TYPE_UNSPECIFIED); } /** * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation * matrix that is to be applied other positional data in this class. Loading core/java/android/view/inputmethod/SparseRectFArray.java +47 −4 Original line number Diff line number Diff line Loading @@ -50,9 +50,15 @@ public final class SparseRectFArray implements Parcelable { */ private final float[] mCoordinates; /** * Stores visibility information. */ private final int[] mFlagsArray; public SparseRectFArray(final Parcel source) { mKeys = source.createIntArray(); mCoordinates = source.createFloatArray(); mFlagsArray = source.createIntArray(); } /** Loading @@ -65,6 +71,7 @@ public final class SparseRectFArray implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeIntArray(mKeys); dest.writeFloatArray(mCoordinates); dest.writeIntArray(mFlagsArray); } @Override Loading @@ -79,6 +86,8 @@ public final class SparseRectFArray implements Parcelable { hash *= 31; hash += mCoordinates[i]; } hash *= 31; hash += mFlagsArray[0]; return hash; } Loading @@ -95,12 +104,13 @@ public final class SparseRectFArray implements Parcelable { } final SparseRectFArray that = (SparseRectFArray) obj; return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates); return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates) && Arrays.equals(mFlagsArray, that.mFlagsArray); } @Override public String toString() { if (mKeys == null || mCoordinates == null) { if (mKeys == null || mCoordinates == null || mFlagsArray == null) { return "SparseRectFArray{}"; } final StringBuilder sb = new StringBuilder(); Loading @@ -119,7 +129,8 @@ public final class SparseRectFArray implements Parcelable { sb.append(mCoordinates[baseIndex + 2]); sb.append(","); sb.append(mCoordinates[baseIndex + 3]); sb.append("]"); sb.append("]:flagsArray="); sb.append(mFlagsArray[i]); } sb.append("}"); return sb.toString(); Loading Loading @@ -153,6 +164,9 @@ public final class SparseRectFArray implements Parcelable { if (mCoordinates == null) { mCoordinates = new float[INITIAL_SIZE * 4]; } if (mFlagsArray == null) { mFlagsArray = new int[INITIAL_SIZE]; } final int requiredIndexArraySize = mCount + 1; if (mKeys.length <= requiredIndexArraySize) { final int[] newArray = new int[requiredIndexArraySize * 2]; Loading @@ -165,6 +179,12 @@ public final class SparseRectFArray implements Parcelable { System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4); mCoordinates = newArray; } final int requiredFlagsArraySize = requiredIndexArraySize; if (mFlagsArray.length <= requiredFlagsArraySize) { final int[] newArray = new int[requiredFlagsArraySize * 2]; System.arraycopy(mFlagsArray, 0, newArray, 0, mCount); mFlagsArray = newArray; } } /** Loading @@ -175,11 +195,13 @@ public final class SparseRectFArray implements Parcelable { * @param top top of the rectangle. * @param right right of the rectangle. * @param bottom bottom of the rectangle. * @param flags an arbitrary integer value to be associated with this rectangle. * @return the receiver object itself for chaining method calls. * @throws IllegalArgumentException If the index is not greater than all of existing keys. */ public SparseRectFArrayBuilder append(final int key, final float left, final float top, final float right, final float bottom) { final float left, final float top, final float right, final float bottom, final int flags) { checkIndex(key); ensureBufferSize(); final int baseCoordinatesIndex = mCount * 4; Loading @@ -187,6 +209,8 @@ public final class SparseRectFArray implements Parcelable { mCoordinates[baseCoordinatesIndex + 1] = top; mCoordinates[baseCoordinatesIndex + 2] = right; mCoordinates[baseCoordinatesIndex + 3] = bottom; final int flagsIndex = mCount; mFlagsArray[flagsIndex] = flags; mKeys[mCount] = key; ++mCount; return this; Loading @@ -194,6 +218,7 @@ public final class SparseRectFArray implements Parcelable { private int mCount = 0; private int[] mKeys = null; private float[] mCoordinates = null; private int[] mFlagsArray = null; private static int INITIAL_SIZE = 16; public boolean isEmpty() { Loading @@ -211,6 +236,7 @@ public final class SparseRectFArray implements Parcelable { if (mCount == 0) { mKeys = null; mCoordinates = null; mFlagsArray = null; } mCount = 0; } Loading @@ -220,11 +246,14 @@ public final class SparseRectFArray implements Parcelable { if (builder.mCount == 0) { mKeys = null; mCoordinates = null; mFlagsArray = null; } else { mKeys = new int[builder.mCount]; mCoordinates = new float[builder.mCount * 4]; mFlagsArray = new int[builder.mCount]; System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount); System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4); System.arraycopy(builder.mFlagsArray, 0, mFlagsArray, 0, builder.mCount); } } Loading @@ -246,6 +275,20 @@ public final class SparseRectFArray implements Parcelable { mCoordinates[baseCoordIndex + 3]); } public int getFlags(final int index, final int valueIfKeyNotFound) { if (mKeys == null) { return valueIfKeyNotFound; } if (index < 0) { return valueIfKeyNotFound; } final int arrayIndex = Arrays.binarySearch(mKeys, index); if (arrayIndex < 0) { return valueIfKeyNotFound; } return mFlagsArray[arrayIndex]; } /** * Used to make this class parcelable. */ Loading core/java/android/widget/Editor.java +19 −11 Original line number Diff line number Diff line Loading @@ -3088,13 +3088,22 @@ public class Editor { final float bottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; // Take TextView's padding and scroll into account. if (isPositionVisible(left, top) && isPositionVisible(right, bottom)) { // TODO: Check right-top and left-bottom as well. final boolean leftTopVisible = isPositionVisible(left, top); final boolean rightBottomVisible = isPositionVisible(right, bottom); final int characterRectFlags; if (leftTopVisible && rightBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE; } else if (leftTopVisible || rightBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE; } else { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE; } // Here offset is the index in Java chars. // TODO: We must have a well-defined specification. For example, how // RTL, surrogate pairs, and composition letters are handled must be // documented. builder.addCharacterRect(offset, left, top, right, bottom); } builder.addCharacterRect(offset, left, top, right, bottom, characterRectFlags); } } Loading @@ -3111,11 +3120,10 @@ public class Editor { final float insertionMarkerBottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; // Take TextView's padding and scroll into account. if (isPositionVisible(insertionMarkerX, insertionMarkerTop) && isPositionVisible(insertionMarkerX, insertionMarkerBottom)) { final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop) || !isPositionVisible(insertionMarkerX, insertionMarkerBottom); builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop, insertionMarkerBaseline, insertionMarkerBottom); } insertionMarkerBaseline, insertionMarkerBottom, isClipped); } imm.updateCursorAnchorInfo(mTextView, builder.build()); Loading core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java +123 −34 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
api/current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -34837,6 +34837,7 @@ package android.view.inputmethod { ctor public CursorAnchorInfo(android.os.Parcel); method public int describeContents(); method public android.graphics.RectF getCharacterRect(int); method public int getCharacterRectFlags(int); method public java.lang.CharSequence getComposingText(); method public int getComposingTextStart(); method public float getInsertionMarkerBaseline(); Loading @@ -34846,17 +34847,24 @@ package android.view.inputmethod { method public android.graphics.Matrix getMatrix(); method public int getSelectionEnd(); method public int getSelectionStart(); method public boolean isInsertionMarkerClipped(); method public void writeToParcel(android.os.Parcel, int); field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1 field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3 field public static final int CHARACTER_RECT_TYPE_MASK = 15; // 0xf field public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; // 0x4 field public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; // 0x2 field public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; // 0x0 field public static final android.os.Parcelable.Creator CREATOR; } public static final class CursorAnchorInfo.Builder { ctor public CursorAnchorInfo.Builder(); method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float); method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int); method public android.view.inputmethod.CursorAnchorInfo build(); method public void reset(); method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence); method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float); method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean); method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix); method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int); }
core/java/android/view/inputmethod/CursorAnchorInfo.java +78 −7 Original line number Diff line number Diff line Loading @@ -44,6 +44,10 @@ public final class CursorAnchorInfo implements Parcelable { */ private final CharSequence mComposingText; /** * {@code True} if the insertion marker is partially or entirely clipped by other UI elements. */ private final boolean mInsertionMarkerClipped; /** * Horizontal position of the insertion marker, in the local coordinates that will be * transformed with the transformation matrix when rendered on the screen. This should be Loading Loading @@ -86,11 +90,36 @@ public final class CursorAnchorInfo implements Parcelable { */ private final Matrix mMatrix; public static final int CHARACTER_RECT_TYPE_MASK = 0x0f; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this * character. Editor authors should not use this flag. */ public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible. */ public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible. */ public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible. */ public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; /** * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle * for this character. Input method authors should ignore the returned rectangle. */ public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; public CursorAnchorInfo(final Parcel source) { mSelectionStart = source.readInt(); mSelectionEnd = source.readInt(); mComposingTextStart = source.readInt(); mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); mInsertionMarkerClipped = (source.readInt() != 0); mInsertionMarkerHorizontal = source.readFloat(); mInsertionMarkerTop = source.readFloat(); mInsertionMarkerBaseline = source.readFloat(); Loading @@ -112,6 +141,7 @@ public final class CursorAnchorInfo implements Parcelable { dest.writeInt(mSelectionEnd); dest.writeInt(mComposingTextStart); TextUtils.writeToParcel(mComposingText, dest, flags); dest.writeInt(mInsertionMarkerClipped ? 1 : 0); dest.writeFloat(mInsertionMarkerHorizontal); dest.writeFloat(mInsertionMarkerTop); dest.writeFloat(mInsertionMarkerBaseline); Loading @@ -129,6 +159,8 @@ public final class CursorAnchorInfo implements Parcelable { + mInsertionMarkerBaseline + mInsertionMarkerBottom; int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash); hash *= 31; hash += (mInsertionMarkerClipped ? 2 : 1); hash *= 31; hash += mSelectionStart + mSelectionEnd + mComposingTextStart; hash *= 31; hash += Objects.hashCode(mComposingText); Loading Loading @@ -172,7 +204,8 @@ public final class CursorAnchorInfo implements Parcelable { || !Objects.equals(mComposingText, that.mComposingText)) { return false; } if (!areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal) if (mInsertionMarkerClipped != that.mInsertionMarkerClipped || !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal) || !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop) || !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline) || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) { Loading @@ -195,6 +228,7 @@ public final class CursorAnchorInfo implements Parcelable { return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd + " mComposingTextStart=" + mComposingTextStart + " mComposingText=" + Objects.toString(mComposingText) + " mInsertionMarkerClipped=" + mInsertionMarkerClipped + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal + " mInsertionMarkerTop=" + mInsertionMarkerTop + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline Loading Loading @@ -256,25 +290,27 @@ public final class CursorAnchorInfo implements Parcelable { * @param lineBottom vertical position of the insertion marker, in the local coordinates * that will be transformed with the transformation matrix when rendered on the screen. This * should be calculated or compatible with {@link Layout#getLineBottom(int)}. * @param clipped {@code true} is the insertion marker is partially or entierly clipped by * other UI elements. */ public Builder setInsertionMarkerLocation(final float horizontalPosition, final float lineTop, final float lineBaseline, final float lineBottom){ final float lineTop, final float lineBaseline, final float lineBottom, final boolean clipped){ mInsertionMarkerHorizontal = horizontalPosition; mInsertionMarkerTop = lineTop; mInsertionMarkerBaseline = lineBaseline; mInsertionMarkerBottom = lineBottom; mInsertionMarkerClipped = clipped; return this; } private float mInsertionMarkerHorizontal = Float.NaN; private float mInsertionMarkerTop = Float.NaN; private float mInsertionMarkerBaseline = Float.NaN; private float mInsertionMarkerBottom = Float.NaN; private boolean mInsertionMarkerClipped = false; /** * Adds the bounding box of the character specified with the index. * <p> * Editor authors should not call this method for characters that are invisible. * </p> * * @param index index of the character in Java chars units. Must be specified in * ascending order across successive calls. Loading @@ -286,19 +322,27 @@ public final class CursorAnchorInfo implements Parcelable { * coordinates, that is, right edge for LTR text and left edge for RTL text. * @param trailingEdgeY y coordinate of the trailing edge of the character in local * coordinates. * @param flags type and flags for this character. See * {@link #CHARACTER_RECT_TYPE_FULLY_VISIBLE} for example. * @throws IllegalArgumentException If the index is a negative value, or not greater than * all of the previously called indices. */ public Builder addCharacterRect(final int index, final float leadingEdgeX, final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY) { final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY, final int flags) { if (index < 0) { throw new IllegalArgumentException("index must not be a negative integer."); } final int type = flags & CHARACTER_RECT_TYPE_MASK; if (type == CHARACTER_RECT_TYPE_UNSPECIFIED) { throw new IllegalArgumentException("Type except for " + "CHARACTER_RECT_TYPE_UNSPECIFIED must be specified."); } if (mCharacterRectBuilder == null) { mCharacterRectBuilder = new SparseRectFArrayBuilder(); } mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX, trailingEdgeY); trailingEdgeY, flags); return this; } private SparseRectFArrayBuilder mCharacterRectBuilder = null; Loading Loading @@ -346,6 +390,7 @@ public final class CursorAnchorInfo implements Parcelable { mSelectionEnd = -1; mComposingTextStart = -1; mComposingText = null; mInsertionMarkerClipped = false; mInsertionMarkerHorizontal = Float.NaN; mInsertionMarkerTop = Float.NaN; mInsertionMarkerBaseline = Float.NaN; Loading @@ -363,6 +408,7 @@ public final class CursorAnchorInfo implements Parcelable { mSelectionEnd = builder.mSelectionEnd; mComposingTextStart = builder.mComposingTextStart; mComposingText = builder.mComposingText; mInsertionMarkerClipped = builder.mInsertionMarkerClipped; mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal; mInsertionMarkerTop = builder.mInsertionMarkerTop; mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline; Loading Loading @@ -404,6 +450,14 @@ public final class CursorAnchorInfo implements Parcelable { return mComposingText; } /** * Returns the visibility of the insertion marker. * @return {@code true} if the insertion marker is partially or entirely clipped. */ public boolean isInsertionMarkerClipped() { return mInsertionMarkerClipped; } /** * Returns the horizontal start of the insertion marker, in the local coordinates that will * be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -415,6 +469,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerHorizontal() { return mInsertionMarkerHorizontal; } /** * Returns the vertical top position of the insertion marker, in the local coordinates that * will be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -424,6 +479,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerTop() { return mInsertionMarkerTop; } /** * Returns the vertical baseline position of the insertion marker, in the local coordinates * that will be transformed with {@link #getMatrix()} when rendered on the screen. Loading @@ -433,6 +489,7 @@ public final class CursorAnchorInfo implements Parcelable { public float getInsertionMarkerBaseline() { return mInsertionMarkerBaseline; } /** * Returns the vertical bottom position of the insertion marker, in the local coordinates * that will be transformed with {@link #getMatrix()} when rendered on the screen. Loading Loading @@ -466,6 +523,20 @@ public final class CursorAnchorInfo implements Parcelable { return mCharacterRects.get(index); } /** * Returns the flags associated with the character specified with the index. * @param index index of the character in a Java chars. * @return {@link #CHARACTER_RECT_TYPE_UNSPECIFIED} if no flag is specified. */ // TODO: Prepare a document about the expected behavior for surrogate pairs, combining // characters, and non-graphical chars. public int getCharacterRectFlags(final int index) { if (mCharacterRects == null) { return CHARACTER_RECT_TYPE_UNSPECIFIED; } return mCharacterRects.getFlags(index, CHARACTER_RECT_TYPE_UNSPECIFIED); } /** * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation * matrix that is to be applied other positional data in this class. Loading
core/java/android/view/inputmethod/SparseRectFArray.java +47 −4 Original line number Diff line number Diff line Loading @@ -50,9 +50,15 @@ public final class SparseRectFArray implements Parcelable { */ private final float[] mCoordinates; /** * Stores visibility information. */ private final int[] mFlagsArray; public SparseRectFArray(final Parcel source) { mKeys = source.createIntArray(); mCoordinates = source.createFloatArray(); mFlagsArray = source.createIntArray(); } /** Loading @@ -65,6 +71,7 @@ public final class SparseRectFArray implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeIntArray(mKeys); dest.writeFloatArray(mCoordinates); dest.writeIntArray(mFlagsArray); } @Override Loading @@ -79,6 +86,8 @@ public final class SparseRectFArray implements Parcelable { hash *= 31; hash += mCoordinates[i]; } hash *= 31; hash += mFlagsArray[0]; return hash; } Loading @@ -95,12 +104,13 @@ public final class SparseRectFArray implements Parcelable { } final SparseRectFArray that = (SparseRectFArray) obj; return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates); return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates) && Arrays.equals(mFlagsArray, that.mFlagsArray); } @Override public String toString() { if (mKeys == null || mCoordinates == null) { if (mKeys == null || mCoordinates == null || mFlagsArray == null) { return "SparseRectFArray{}"; } final StringBuilder sb = new StringBuilder(); Loading @@ -119,7 +129,8 @@ public final class SparseRectFArray implements Parcelable { sb.append(mCoordinates[baseIndex + 2]); sb.append(","); sb.append(mCoordinates[baseIndex + 3]); sb.append("]"); sb.append("]:flagsArray="); sb.append(mFlagsArray[i]); } sb.append("}"); return sb.toString(); Loading Loading @@ -153,6 +164,9 @@ public final class SparseRectFArray implements Parcelable { if (mCoordinates == null) { mCoordinates = new float[INITIAL_SIZE * 4]; } if (mFlagsArray == null) { mFlagsArray = new int[INITIAL_SIZE]; } final int requiredIndexArraySize = mCount + 1; if (mKeys.length <= requiredIndexArraySize) { final int[] newArray = new int[requiredIndexArraySize * 2]; Loading @@ -165,6 +179,12 @@ public final class SparseRectFArray implements Parcelable { System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4); mCoordinates = newArray; } final int requiredFlagsArraySize = requiredIndexArraySize; if (mFlagsArray.length <= requiredFlagsArraySize) { final int[] newArray = new int[requiredFlagsArraySize * 2]; System.arraycopy(mFlagsArray, 0, newArray, 0, mCount); mFlagsArray = newArray; } } /** Loading @@ -175,11 +195,13 @@ public final class SparseRectFArray implements Parcelable { * @param top top of the rectangle. * @param right right of the rectangle. * @param bottom bottom of the rectangle. * @param flags an arbitrary integer value to be associated with this rectangle. * @return the receiver object itself for chaining method calls. * @throws IllegalArgumentException If the index is not greater than all of existing keys. */ public SparseRectFArrayBuilder append(final int key, final float left, final float top, final float right, final float bottom) { final float left, final float top, final float right, final float bottom, final int flags) { checkIndex(key); ensureBufferSize(); final int baseCoordinatesIndex = mCount * 4; Loading @@ -187,6 +209,8 @@ public final class SparseRectFArray implements Parcelable { mCoordinates[baseCoordinatesIndex + 1] = top; mCoordinates[baseCoordinatesIndex + 2] = right; mCoordinates[baseCoordinatesIndex + 3] = bottom; final int flagsIndex = mCount; mFlagsArray[flagsIndex] = flags; mKeys[mCount] = key; ++mCount; return this; Loading @@ -194,6 +218,7 @@ public final class SparseRectFArray implements Parcelable { private int mCount = 0; private int[] mKeys = null; private float[] mCoordinates = null; private int[] mFlagsArray = null; private static int INITIAL_SIZE = 16; public boolean isEmpty() { Loading @@ -211,6 +236,7 @@ public final class SparseRectFArray implements Parcelable { if (mCount == 0) { mKeys = null; mCoordinates = null; mFlagsArray = null; } mCount = 0; } Loading @@ -220,11 +246,14 @@ public final class SparseRectFArray implements Parcelable { if (builder.mCount == 0) { mKeys = null; mCoordinates = null; mFlagsArray = null; } else { mKeys = new int[builder.mCount]; mCoordinates = new float[builder.mCount * 4]; mFlagsArray = new int[builder.mCount]; System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount); System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4); System.arraycopy(builder.mFlagsArray, 0, mFlagsArray, 0, builder.mCount); } } Loading @@ -246,6 +275,20 @@ public final class SparseRectFArray implements Parcelable { mCoordinates[baseCoordIndex + 3]); } public int getFlags(final int index, final int valueIfKeyNotFound) { if (mKeys == null) { return valueIfKeyNotFound; } if (index < 0) { return valueIfKeyNotFound; } final int arrayIndex = Arrays.binarySearch(mKeys, index); if (arrayIndex < 0) { return valueIfKeyNotFound; } return mFlagsArray[arrayIndex]; } /** * Used to make this class parcelable. */ Loading
core/java/android/widget/Editor.java +19 −11 Original line number Diff line number Diff line Loading @@ -3088,13 +3088,22 @@ public class Editor { final float bottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; // Take TextView's padding and scroll into account. if (isPositionVisible(left, top) && isPositionVisible(right, bottom)) { // TODO: Check right-top and left-bottom as well. final boolean leftTopVisible = isPositionVisible(left, top); final boolean rightBottomVisible = isPositionVisible(right, bottom); final int characterRectFlags; if (leftTopVisible && rightBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE; } else if (leftTopVisible || rightBottomVisible) { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE; } else { characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE; } // Here offset is the index in Java chars. // TODO: We must have a well-defined specification. For example, how // RTL, surrogate pairs, and composition letters are handled must be // documented. builder.addCharacterRect(offset, left, top, right, bottom); } builder.addCharacterRect(offset, left, top, right, bottom, characterRectFlags); } } Loading @@ -3111,11 +3120,10 @@ public class Editor { final float insertionMarkerBottom = layout.getLineBottom(line) + viewportToContentVerticalOffset; // Take TextView's padding and scroll into account. if (isPositionVisible(insertionMarkerX, insertionMarkerTop) && isPositionVisible(insertionMarkerX, insertionMarkerBottom)) { final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop) || !isPositionVisible(insertionMarkerX, insertionMarkerBottom); builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop, insertionMarkerBaseline, insertionMarkerBottom); } insertionMarkerBaseline, insertionMarkerBottom, isClipped); } imm.updateCursorAnchorInfo(mTextView, builder.build()); Loading
core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java +123 −34 File changed.Preview size limit exceeded, changes collapsed. Show changes