From 0b01e7fc58cdde00d8350285a3386c4209b72d78 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Tue, 8 Jul 2014 15:29:51 +0900 Subject: [PATCH] Polish new IME API for L: CursorAnchorInfo This CL allows application authors and input method authors to communicate with each other more precisely on the visibility of insertion marker and composing characters. Now we can describe the situation where the coordinates of them are available but they are overlapped by other UI elements. This change is based on feedbacks from internal customers of this preview API. Change-Id: I82eba0e844a6f8b99ba11a68fad272399034cc24 BUG: 16118303 --- api/current.txt | 12 +- .../view/inputmethod/CursorAnchorInfo.java | 85 +++++++++- .../view/inputmethod/SparseRectFArray.java | 51 +++++- core/java/android/widget/Editor.java | 30 ++-- .../src/android/os/CursorAnchorInfoTest.java | 157 ++++++++++++++---- .../src/android/os/SparseRectFArrayTest.java | 147 ++++++++++------ 6 files changed, 370 insertions(+), 112 deletions(-) diff --git a/api/current.txt b/api/current.txt index 49cf1966984ed..0e793ae81776e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -34936,6 +34936,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(); @@ -34945,17 +34946,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); } diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java index 434b1aa7fd843..04d875d4f1334 100644 --- a/core/java/android/view/inputmethod/CursorAnchorInfo.java +++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java @@ -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 @@ -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(); @@ -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); @@ -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); @@ -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)) { @@ -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 @@ -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. - *

- * Editor authors should not call this method for characters that are invisible. - *

* * @param index index of the character in Java chars units. Must be specified in * ascending order across successive calls. @@ -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; @@ -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; @@ -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; @@ -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. @@ -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. @@ -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. @@ -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. @@ -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. diff --git a/core/java/android/view/inputmethod/SparseRectFArray.java b/core/java/android/view/inputmethod/SparseRectFArray.java index d4ec9d0253a52..484fe46ffbb18 100644 --- a/core/java/android/view/inputmethod/SparseRectFArray.java +++ b/core/java/android/view/inputmethod/SparseRectFArray.java @@ -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(); } /** @@ -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 @@ -79,6 +86,8 @@ public final class SparseRectFArray implements Parcelable { hash *= 31; hash += mCoordinates[i]; } + hash *= 31; + hash += mFlagsArray[0]; return hash; } @@ -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(); @@ -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(); @@ -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]; @@ -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; + } } /** @@ -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; @@ -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; @@ -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() { @@ -211,6 +236,7 @@ public final class SparseRectFArray implements Parcelable { if (mCount == 0) { mKeys = null; mCoordinates = null; + mFlagsArray = null; } mCount = 0; } @@ -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); } } @@ -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. */ diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 13a0849d55043..170a3163cb029 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -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)) { - // 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); + // 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, characterRectFlags); } } @@ -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)) { - builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop, - insertionMarkerBaseline, insertionMarkerBottom); - } + final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop) + || !isPositionVisible(insertionMarkerX, insertionMarkerBottom); + builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop, + insertionMarkerBaseline, insertionMarkerBottom, isClipped); } imm.updateCursorAnchorInfo(mTextView, builder.build()); diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java index 3d677c6eda583..cc4a7c4f24e83 100644 --- a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java +++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java @@ -26,17 +26,21 @@ import android.view.inputmethod.CursorAnchorInfo.Builder; import java.util.Objects; +import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE; +import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE; +import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE; +import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE; +import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED; + public class CursorAnchorInfoTest extends InstrumentationTestCase { - // null represents a character that is invisible, for example because it's overlapped by some - // other UI elements. private static final RectF[] MANY_RECTS = new RectF[] { - null, + new RectF(101.0f, 201.0f, 301.0f, 401.0f), new RectF(102.0f, 202.0f, 302.0f, 402.0f), new RectF(103.0f, 203.0f, 303.0f, 403.0f), new RectF(104.0f, 204.0f, 304.0f, 404.0f), new RectF(105.0f, 205.0f, 305.0f, 405.0f), new RectF(106.0f, 206.0f, 306.0f, 406.0f), - null, + new RectF(107.0f, 207.0f, 307.0f, 407.0f), new RectF(108.0f, 208.0f, 308.0f, 408.0f), new RectF(109.0f, 209.0f, 309.0f, 409.0f), new RectF(110.0f, 210.0f, 310.0f, 410.0f), @@ -47,8 +51,29 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { new RectF(115.0f, 215.0f, 315.0f, 415.0f), new RectF(116.0f, 216.0f, 316.0f, 416.0f), new RectF(117.0f, 217.0f, 317.0f, 417.0f), - null, - null, + new RectF(118.0f, 218.0f, 318.0f, 418.0f), + new RectF(119.0f, 219.0f, 319.0f, 419.0f), + }; + private static final int[] MANY_FLAGS_ARRAY = new int[] { + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_INVISIBLE, + CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_NOT_FEASIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_FULLY_VISIBLE, + CHARACTER_RECT_TYPE_NOT_FEASIBLE, + CHARACTER_RECT_TYPE_NOT_FEASIBLE, }; @SmallTest @@ -57,6 +82,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END = 40; final int COMPOSING_TEXT_START = 32; final String COMPOSING_TEXT = "test"; + final boolean INSERTION_MARKER_CLIPPED = true; final float INSERTION_MARKER_HORIZONTAL = 10.5f; final float INSERTION_MARKER_TOP = 100.1f; final float INSERTION_MARKER_BASELINE = 110.4f; @@ -68,13 +94,13 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { builder.setSelectionRange(SELECTION_START, SELECTION_END) .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT) .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP, - INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM) + INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, + INSERTION_MARKER_CLIPPED) .setMatrix(TRANSFORM_MATRIX); for (int i = 0; i < MANY_RECTS.length; i++) { final RectF rect = MANY_RECTS[i]; - if (rect != null) { - builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom); - } + final int flags = MANY_FLAGS_ARRAY[i]; + builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags); } final CursorAnchorInfo info = builder.build(); @@ -82,6 +108,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText())); + assertTrue(info.isInsertionMarkerClipped()); assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline()); @@ -93,6 +120,14 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } assertNull(info.getCharacterRect(-1)); assertNull(info.getCharacterRect(MANY_RECTS.length + 1)); + for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { + final int expectedFlags = MANY_FLAGS_ARRAY[i]; + assertEquals(expectedFlags, info.getCharacterRectFlags(i)); + } + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, + info.getCharacterRectFlags(-1)); + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, + info.getCharacterRectFlags(MANY_RECTS.length + 1)); // Make sure that the builder can reproduce the same object. final CursorAnchorInfo info2 = builder.build(); @@ -100,6 +135,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info2.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText())); + assertTrue(info2.isInsertionMarkerClipped()); assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline()); @@ -111,6 +147,13 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } assertNull(info2.getCharacterRect(-1)); assertNull(info2.getCharacterRect(MANY_RECTS.length + 1)); + for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { + final int expectedFlags = MANY_FLAGS_ARRAY[i]; + assertEquals(expectedFlags, info2.getCharacterRectFlags(i)); + } + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1)); + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, + info2.getCharacterRectFlags(MANY_RECTS.length + 1)); assertEquals(info, info2); assertEquals(info.hashCode(), info2.hashCode()); @@ -120,6 +163,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(SELECTION_END, info3.getSelectionEnd()); assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart()); assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText())); + assertTrue(info3.isInsertionMarkerClipped()); assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal()); assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop()); assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline()); @@ -131,6 +175,13 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } assertNull(info3.getCharacterRect(-1)); assertNull(info3.getCharacterRect(MANY_RECTS.length + 1)); + for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { + final int expectedFlags = MANY_FLAGS_ARRAY[i]; + assertEquals(expectedFlags, info3.getCharacterRectFlags(i)); + } + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1)); + assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, + info3.getCharacterRectFlags(MANY_RECTS.length + 1)); assertEquals(info.hashCode(), info3.hashCode()); builder.reset(); @@ -139,6 +190,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals(-1, uninitializedInfo.getSelectionEnd()); assertEquals(-1, uninitializedInfo.getComposingTextStart()); assertNull(uninitializedInfo.getComposingText()); + assertFalse(uninitializedInfo.isInsertionMarkerClipped()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop()); assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline()); @@ -166,6 +218,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END1 = 7; final String COMPOSING_TEXT1 = "0123456789"; final int COMPOSING_TEXT_START1 = 0; + final boolean INSERTION_MARKER_CLIPPED1 = true; final float INSERTION_MARKER_HORIZONTAL1 = 10.5f; final float INSERTION_MARKER_TOP1 = 100.1f; final float INSERTION_MARKER_BASELINE1 = 110.4f; @@ -174,6 +227,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END2 = 8; final String COMPOSING_TEXT2 = "9876543210"; final int COMPOSING_TEXT_START2 = 3; + final boolean INSERTION_MARKER_CLIPPED2 = false; final float INSERTION_MARKER_HORIZONTAL2 = 14.5f; final float INSERTION_MARKER_TOP2 = 200.1f; final float INSERTION_MARKER_BASELINE2 = 210.4f; @@ -210,9 +264,11 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { // For insertion marker locations, {@link Float#NaN} is treated as if it was a number. assertEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - Float.NaN, Float.NaN, Float.NaN, Float.NaN).build(), + Float.NaN, Float.NaN, Float.NaN, Float.NaN, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - Float.NaN, Float.NaN, Float.NaN, Float.NaN).build()); + Float.NaN, Float.NaN, Float.NaN, Float.NaN, + INSERTION_MARKER_CLIPPED1).build()); // Check Matrix. assertEquals( @@ -233,52 +289,75 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { assertEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( Float.NaN, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build()); assertNotEquals( new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1).build(), + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2).build()); + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2, + INSERTION_MARKER_CLIPPED1).build()); + assertNotEquals( + new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( + INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED1).build(), + new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( + INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, + INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, + INSERTION_MARKER_CLIPPED2).build()); } @SmallTest @@ -315,6 +394,7 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { final int SELECTION_END = 40; final int COMPOSING_TEXT_START = 32; final String COMPOSING_TEXT = "test"; + final boolean INSERTION_MARKER_CLIPPED = true; final float INSERTION_MARKER_HORIZONTAL = 10.5f; final float INSERTION_MARKER_TOP = 100.1f; final float INSERTION_MARKER_BASELINE = 110.4f; @@ -330,25 +410,25 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { try { // Should succeed as coordinate transformation matrix is not required if no // positional information is specified. - new Builder().build(); + builder.build(); } catch (IllegalArgumentException ex) { assertTrue(false); } builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP, - INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM); + INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED); try { // Coordinate transformation matrix is required if no positional information is // specified. - new Builder().build(); + builder.build(); + assertTrue(false); } catch (IllegalArgumentException ex) { - assertTrue(true); } builder.setMatrix(TRANSFORM_MATRIX); try { // Should succeed as coordinate transformation matrix is required. - new Builder().build(); + builder.build(); } catch (IllegalArgumentException ex) { assertTrue(false); } @@ -358,12 +438,21 @@ public class CursorAnchorInfoTest extends InstrumentationTestCase { } @SmallTest - public void testBuilderAdd() throws Exception { + public void testBuilderAddCharacterRect() throws Exception { // A negative index should be rejected. try { - new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f); + new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f, + CHARACTER_RECT_TYPE_FULLY_VISIBLE); + assertTrue(false); + } catch (IllegalArgumentException ex) { + } + + // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed. + try { + new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f, + CHARACTER_RECT_TYPE_UNSPECIFIED); + assertTrue(false); } catch (IllegalArgumentException ex) { - assertTrue(true); } } diff --git a/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java index fae7230ac6ca7..47b0d2a26cdfa 100644 --- a/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java +++ b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java @@ -52,14 +52,22 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { @SmallTest public void testBuilder() throws Exception { final RectF TEMP_RECT = new RectF(10.0f, 20.0f, 30.0f, 40.0f); + final int TEMP_FLAGS = 0x1234; final SparseRectFArrayBuilder builder = new SparseRectFArrayBuilder(); - builder.append(100, TEMP_RECT.left, TEMP_RECT.top, TEMP_RECT.right, TEMP_RECT.bottom); + builder.append(100, TEMP_RECT.left, TEMP_RECT.top, TEMP_RECT.right, TEMP_RECT.bottom, + TEMP_FLAGS); assertNull(builder.build().get(-1)); assertNull(builder.build().get(0)); assertNull(builder.build().get(99)); + assertEquals(0, builder.build().getFlags(99, 0 /* valueIfKeyNotFound */)); + assertEquals(1, builder.build().getFlags(99, 1 /* valueIfKeyNotFound */)); assertEquals(TEMP_RECT, builder.build().get(100)); + assertEquals(TEMP_FLAGS, builder.build().getFlags(100, 0 /* valueIfKeyNotFound */)); + assertEquals(TEMP_FLAGS, builder.build().getFlags(100, 1 /* valueIfKeyNotFound */)); assertNull(builder.build().get(101)); + assertEquals(0, builder.build().getFlags(101, 0 /* valueIfKeyNotFound */)); + assertEquals(1, builder.build().getFlags(101, 1 /* valueIfKeyNotFound */)); // Test if {@link SparseRectFArrayBuilder#reset} resets its internal state. builder.reset(); @@ -69,28 +77,49 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { for (int i = 0; i < MANY_RECTS.length; i++) { final RectF rect = MANY_RECTS[i]; if (rect != null) { - builder.append(i, rect.left, rect.top, rect.right, rect.bottom); + builder.append(i, rect.left, rect.top, rect.right, rect.bottom, i); } } final SparseRectFArray array = builder.build(); for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF rect = MANY_RECTS[i]; - assertEquals(rect, array.get(i)); + final RectF expectedRect = MANY_RECTS[i]; + assertEquals(expectedRect, array.get(i)); + if (expectedRect != null) { + assertEquals(i, array.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(i, array.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } else { + assertEquals(0x1234, array.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(0x4321, array.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } } // Make sure the builder reproduces an equivalent object. final SparseRectFArray array2 = builder.build(); for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF rect = MANY_RECTS[i]; - assertEquals(rect, array2.get(i)); + final RectF expectedRect = MANY_RECTS[i]; + assertEquals(expectedRect, array2.get(i)); + if (expectedRect != null) { + assertEquals(i, array2.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(i, array2.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } else { + assertEquals(0x1234, array2.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(0x4321, array2.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } } assertEqualRects(array, array2); // Make sure the instance can be marshaled via {@link Parcel}. final SparseRectFArray array3 = cloneViaParcel(array); for (int i = 0; i < MANY_RECTS.length; i++) { - final RectF rect = MANY_RECTS[i]; - assertEquals(rect, array3.get(i)); + final RectF expectedRect = MANY_RECTS[i]; + assertEquals(expectedRect, array3.get(i)); + if (expectedRect != null) { + assertEquals(i, array3.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(i, array3.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } else { + assertEquals(0x1234, array3.getFlags(i, 0x1234 /* valueIfKeyNotFound */)); + assertEquals(0x4321, array3.getFlags(i, 0x4321 /* valueIfKeyNotFound */)); + } } assertEqualRects(array, array3); @@ -106,87 +135,93 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { new SparseRectFArrayBuilder().build()); assertEqualRects( - new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(), - new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build()); + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 1).build(), + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 1).build()); + assertEqualRects( + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0).build(), + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0).build()); assertNotEqualRects( - new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(), - new SparseRectFArrayBuilder().append(100, 2.0f, 2.0f, 3.0f, 4.0f).build()); + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0).build(), + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 1).build()); assertNotEqualRects( - new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(), - new SparseRectFArrayBuilder().append(101, 1.0f, 2.0f, 3.0f, 4.0f).build()); + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 1).build(), + new SparseRectFArrayBuilder().append(100, 2.0f, 2.0f, 3.0f, 4.0f, 1).build()); + assertNotEqualRects( + new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f, 1).build(), + new SparseRectFArrayBuilder().append(101, 1.0f, 2.0f, 3.0f, 4.0f, 1).build()); assertEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0).build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 1.0f, 0.0f, 0.0f, 0.0f, 0).build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 1.0f, 0.0f, 0.0f, 0.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(), + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(101, 0.0f, 0.0f, 0.0f, 0.0f, 0).build(), new SparseRectFArrayBuilder() - .append(100, 1.0f, 2.0f, 3.0f, 4.0f) - .append(102, 0.0f, 0.0f, 0.0f, 0.0f).build()); + .append(100, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(102, 0.0f, 0.0f, 0.0f, 0.0f, 0).build()); assertEqualRects( new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) - .append(1000, 0.0f, 0.0f, 0.0f, 0.0f) - .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(1000, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f, 0) .build(), new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) - .append(1000, 0.0f, 0.0f, 0.0f, 0.0f) - .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(1000, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f, 0) .build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) - .append(1000, 0.0f, 0.0f, 0.0f, 0.0f) - .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(1000, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f, 0) .build(), new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) .build()); assertNotEqualRects( new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) - .append(1000, 0.0f, 0.0f, 0.0f, 0.0f) - .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(1000, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f, 0) .build(), new SparseRectFArrayBuilder() - .append(1, 1.0f, 2.0f, 3.0f, 4.0f) - .append(1000, 1.0f, 0.0f, 0.0f, 0.0f) - .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f) + .append(1, 1.0f, 2.0f, 3.0f, 4.0f, 0) + .append(1000, 1.0f, 0.0f, 0.0f, 0.0f, 0) + .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f, 0) .build()); } @@ -194,13 +229,17 @@ public class SparseRectFArrayTest extends InstrumentationTestCase { public void testBuilderAppend() throws Exception { // Key should be appended in ascending order. try { - new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(0, 1, 2, 3, 4); + new SparseRectFArrayBuilder() + .append(10, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(0, 1.0f, 2.0f, 3.0f, 4.0f, 0); } catch (IllegalArgumentException ex) { assertTrue(true); } try { - new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(10, 1, 2, 3, 4); + new SparseRectFArrayBuilder() + .append(10, 0.0f, 0.0f, 0.0f, 0.0f, 0) + .append(10, 1.0f, 2.0f, 3.0f, 4.0f, 0); } catch (IllegalArgumentException ex) { assertTrue(true); }