diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java index ee5b3ecc76825..21ead4c62366c 100644 --- a/core/java/android/view/inputmethod/CursorAnchorInfo.java +++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java @@ -17,6 +17,7 @@ package android.view.inputmethod; import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Matrix; import android.graphics.RectF; import android.os.Parcel; @@ -388,7 +389,7 @@ public final class CursorAnchorInfo implements Parcelable { "required when positional parameters are specified."); } } - return new CursorAnchorInfo(this); + return CursorAnchorInfo.create(this); } /** @@ -412,30 +413,90 @@ public final class CursorAnchorInfo implements Parcelable { } } - private CursorAnchorInfo(final Builder builder) { - mSelectionStart = builder.mSelectionStart; - mSelectionEnd = builder.mSelectionEnd; - mComposingTextStart = builder.mComposingTextStart; - mComposingText = builder.mComposingText; - mInsertionMarkerFlags = builder.mInsertionMarkerFlags; - mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal; - mInsertionMarkerTop = builder.mInsertionMarkerTop; - mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline; - mInsertionMarkerBottom = builder.mInsertionMarkerBottom; - mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ? - builder.mCharacterBoundsArrayBuilder.build() : null; - mMatrixValues = new float[9]; + private static CursorAnchorInfo create(Builder builder) { + final SparseRectFArray characterBoundsArray = + builder.mCharacterBoundsArrayBuilder != null + ? builder.mCharacterBoundsArrayBuilder.build() + : null; + final float[] matrixValues = new float[9]; if (builder.mMatrixInitialized) { - System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9); + System.arraycopy(builder.mMatrixValues, 0, matrixValues, 0, 9); } else { - Matrix.IDENTITY_MATRIX.getValues(mMatrixValues); + Matrix.IDENTITY_MATRIX.getValues(matrixValues); } + return new CursorAnchorInfo(builder.mSelectionStart, builder.mSelectionEnd, + builder.mComposingTextStart, builder.mComposingText, builder.mInsertionMarkerFlags, + builder.mInsertionMarkerHorizontal, builder.mInsertionMarkerTop, + builder.mInsertionMarkerBaseline, builder.mInsertionMarkerBottom, + characterBoundsArray, matrixValues); + } + + private CursorAnchorInfo(int selectionStart, int selectionEnd, int composingTextStart, + @Nullable CharSequence composingText, int insertionMarkerFlags, + float insertionMarkerHorizontal, float insertionMarkerTop, + float insertionMarkerBaseline, float insertionMarkerBottom, + @Nullable SparseRectFArray characterBoundsArray, @NonNull float[] matrixValues) { + mSelectionStart = selectionStart; + mSelectionEnd = selectionEnd; + mComposingTextStart = composingTextStart; + mComposingText = composingText; + mInsertionMarkerFlags = insertionMarkerFlags; + mInsertionMarkerHorizontal = insertionMarkerHorizontal; + mInsertionMarkerTop = insertionMarkerTop; + mInsertionMarkerBaseline = insertionMarkerBaseline; + mInsertionMarkerBottom = insertionMarkerBottom; + mCharacterBoundsArray = characterBoundsArray; + mMatrixValues = matrixValues; + // To keep hash function simple, we only use some complex objects for hash. - int hash = Objects.hashCode(mComposingText); - hash *= 31; - hash += Arrays.hashCode(mMatrixValues); - mHashCode = hash; + int hashCode = Objects.hashCode(mComposingText); + hashCode *= 31; + hashCode += Arrays.hashCode(matrixValues); + mHashCode = hashCode; + } + + /** + * Creates a new instance of {@link CursorAnchorInfo} by applying {@code parentMatrix} to + * the coordinate transformation matrix. + * + * @param original {@link CursorAnchorInfo} to be cloned from. + * @param parentMatrix {@link Matrix} to be applied to {@code original.getMatrix()} + * @return A new instance of {@link CursorAnchorInfo} whose {@link CursorAnchorInfo#getMatrix()} + * returns {@code parentMatrix * original.getMatrix()}. + * @hide + */ + public static CursorAnchorInfo createForAdditionalParentMatrix(CursorAnchorInfo original, + @NonNull Matrix parentMatrix) { + return new CursorAnchorInfo(original.mSelectionStart, original.mSelectionEnd, + original.mComposingTextStart, original.mComposingText, + original.mInsertionMarkerFlags, original.mInsertionMarkerHorizontal, + original.mInsertionMarkerTop, original.mInsertionMarkerBaseline, + original.mInsertionMarkerBottom, original.mCharacterBoundsArray, + computeMatrixValues(parentMatrix, original)); + } + + /** + * Returns a float array that represents {@link Matrix} elements for + * {@code parentMatrix * info.getMatrix()}. + * + * @param parentMatrix {@link Matrix} to be multiplied. + * @param info {@link CursorAnchorInfo} to provide {@link Matrix} to be multiplied. + * @return {@code parentMatrix * info.getMatrix()}. + */ + private static float[] computeMatrixValues(@NonNull Matrix parentMatrix, + @NonNull CursorAnchorInfo info) { + if (parentMatrix.isIdentity()) { + return info.mMatrixValues; + } + + final Matrix newMatrix = new Matrix(); + newMatrix.setValues(info.mMatrixValues); + newMatrix.postConcat(parentMatrix); + + final float[] matrixValues = new float[9]; + newMatrix.getValues(matrixValues); + return matrixValues; } /** diff --git a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java index ace6611a52c56..833530d760290 100644 --- a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java @@ -16,19 +16,9 @@ package android.view.inputmethod; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; -import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import android.graphics.Matrix; -import android.graphics.RectF; -import android.os.Parcel; -import android.text.TextUtils; import android.view.inputmethod.CursorAnchorInfo.Builder; import androidx.test.filters.SmallTest; @@ -37,437 +27,38 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.Objects; - @SmallTest @RunWith(AndroidJUnit4.class) public class CursorAnchorInfoTest { - private static final float EPSILON = 0.0000001f; - - private static final RectF[] MANY_BOUNDS = new RectF[] { - 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), - 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), - new RectF(111.0f, 211.0f, 311.0f, 411.0f), - new RectF(112.0f, 212.0f, 312.0f, 412.0f), - new RectF(113.0f, 213.0f, 313.0f, 413.0f), - new RectF(114.0f, 214.0f, 314.0f, 414.0f), - 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), - 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[] { - FLAG_HAS_INVISIBLE_REGION, - FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL, - FLAG_HAS_VISIBLE_REGION, - FLAG_HAS_INVISIBLE_REGION, - FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL, - }; - @Test - public void testBuilder() throws Exception { - final int SELECTION_START = 30; - final int SELECTION_END = 40; - final int COMPOSING_TEXT_START = 32; - final String COMPOSING_TEXT = "test"; - final int INSERTION_MARKER_FLAGS = - FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL; - final float INSERTION_MARKER_HORIZONTAL = 10.5f; - final float INSERTION_MARKER_TOP = 100.1f; - final float INSERTION_MARKER_BASELINE = 110.4f; - final float INSERTION_MARKER_BOTOM = 111.0f; - - Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX); - TRANSFORM_MATRIX.setScale(10.0f, 20.0f); - + public void testCreateForAdditionalParentMatrix() { + final Matrix originalMatrix = new Matrix(); + originalMatrix.setTranslate(10.0f, 20.0f); final Builder builder = new Builder(); - 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_FLAGS) - .setMatrix(TRANSFORM_MATRIX); - for (int i = 0; i < MANY_BOUNDS.length; i++) { - final RectF bounds = MANY_BOUNDS[i]; - final int flags = MANY_FLAGS_ARRAY[i]; - builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom, - flags); - } + builder.setMatrix(originalMatrix); - final CursorAnchorInfo info = builder.build(); - assertEquals(SELECTION_START, info.getSelectionStart()); - assertEquals(SELECTION_END, info.getSelectionEnd()); - assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart()); - assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText())); - assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal(), EPSILON); - assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop(), EPSILON); - assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline(), EPSILON); - assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom(), EPSILON); - assertEquals(TRANSFORM_MATRIX, info.getMatrix()); - for (int i = 0; i < MANY_BOUNDS.length; i++) { - final RectF expectedBounds = MANY_BOUNDS[i]; - assertEquals(expectedBounds, info.getCharacterBounds(i)); - } - assertNull(info.getCharacterBounds(-1)); - assertNull(info.getCharacterBounds(MANY_BOUNDS.length + 1)); - for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { - final int expectedFlags = MANY_FLAGS_ARRAY[i]; - assertEquals(expectedFlags, info.getCharacterBoundsFlags(i)); - } - assertEquals(0, info.getCharacterBoundsFlags(-1)); - assertEquals(0, info.getCharacterBoundsFlags(MANY_BOUNDS.length + 1)); + final CursorAnchorInfo originalInstance = builder.build(); - // Make sure that the builder can reproduce the same object. - final CursorAnchorInfo info2 = builder.build(); - assertEquals(SELECTION_START, info2.getSelectionStart()); - assertEquals(SELECTION_END, info2.getSelectionEnd()); - assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart()); - assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText())); - assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal(), EPSILON); - assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop(), EPSILON); - assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline(), EPSILON); - assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom(), EPSILON); - assertEquals(TRANSFORM_MATRIX, info2.getMatrix()); - for (int i = 0; i < MANY_BOUNDS.length; i++) { - final RectF expectedBounds = MANY_BOUNDS[i]; - assertEquals(expectedBounds, info2.getCharacterBounds(i)); - } - assertNull(info2.getCharacterBounds(-1)); - assertNull(info2.getCharacterBounds(MANY_BOUNDS.length + 1)); - for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { - final int expectedFlags = MANY_FLAGS_ARRAY[i]; - assertEquals(expectedFlags, info2.getCharacterBoundsFlags(i)); - } - assertEquals(0, info2.getCharacterBoundsFlags(-1)); - assertEquals(0, info2.getCharacterBoundsFlags(MANY_BOUNDS.length + 1)); - assertEquals(info, info2); - assertEquals(info.hashCode(), info2.hashCode()); + assertEquals(originalMatrix, originalInstance.getMatrix()); - // Make sure that object can be marshaled via {@link Parsel}. - final CursorAnchorInfo info3 = cloneViaParcel(info2); - assertEquals(SELECTION_START, info3.getSelectionStart()); - assertEquals(SELECTION_END, info3.getSelectionEnd()); - assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart()); - assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText())); - assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags()); - assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal(), EPSILON); - assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop(), EPSILON); - assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline(), EPSILON); - assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom(), EPSILON); - assertEquals(TRANSFORM_MATRIX, info3.getMatrix()); - for (int i = 0; i < MANY_BOUNDS.length; i++) { - final RectF expectedBounds = MANY_BOUNDS[i]; - assertEquals(expectedBounds, info3.getCharacterBounds(i)); - } - assertNull(info3.getCharacterBounds(-1)); - assertNull(info3.getCharacterBounds(MANY_BOUNDS.length + 1)); - for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) { - final int expectedFlags = MANY_FLAGS_ARRAY[i]; - assertEquals(expectedFlags, info3.getCharacterBoundsFlags(i)); - } - assertEquals(0, info3.getCharacterBoundsFlags(-1)); - assertEquals(0, info3.getCharacterBoundsFlags(MANY_BOUNDS.length + 1)); - assertEquals(info.hashCode(), info3.hashCode()); + final Matrix additionalParentMatrix = new Matrix(); + additionalParentMatrix.setTranslate(1.0f, 2.0f); + + final Matrix newMatrix = new Matrix(originalMatrix); + newMatrix.postConcat(additionalParentMatrix); builder.reset(); - final CursorAnchorInfo uninitializedInfo = builder.build(); - assertEquals(-1, uninitializedInfo.getSelectionStart()); - assertEquals(-1, uninitializedInfo.getSelectionEnd()); - assertEquals(-1, uninitializedInfo.getComposingTextStart()); - assertNull(uninitializedInfo.getComposingText()); - assertEquals(0, uninitializedInfo.getInsertionMarkerFlags()); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal(), EPSILON); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop(), EPSILON); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline(), EPSILON); - assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom(), EPSILON); - assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix()); - } + builder.setMatrix(newMatrix); + // An instance created by the standard Builder class. + final CursorAnchorInfo newInstanceByBuilder = builder.build(); - private static void assertNotEquals(final CursorAnchorInfo reference, - final CursorAnchorInfo actual) { - assertFalse(Objects.equals(reference, actual)); - } + // An instance created by an @hide method. + final CursorAnchorInfo newInstanceByMethod = + CursorAnchorInfo.createForAdditionalParentMatrix( + originalInstance, additionalParentMatrix); - @Test - public void testEquality() throws Exception { - final Matrix MATRIX1 = new Matrix(); - MATRIX1.setTranslate(10.0f, 20.0f); - final Matrix MATRIX2 = new Matrix(); - MATRIX2.setTranslate(110.0f, 120.0f); - final Matrix NAN_MATRIX = new Matrix(); - NAN_MATRIX.setValues(new float[]{ - Float.NaN, Float.NaN, Float.NaN, - Float.NaN, Float.NaN, Float.NaN, - Float.NaN, Float.NaN, Float.NaN}); - final int SELECTION_START1 = 2; - final int SELECTION_END1 = 7; - final String COMPOSING_TEXT1 = "0123456789"; - final int COMPOSING_TEXT_START1 = 0; - final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION; - final float INSERTION_MARKER_HORIZONTAL1 = 10.5f; - final float INSERTION_MARKER_TOP1 = 100.1f; - final float INSERTION_MARKER_BASELINE1 = 110.4f; - final float INSERTION_MARKER_BOTOM1 = 111.0f; - final int SELECTION_START2 = 4; - final int SELECTION_END2 = 8; - final String COMPOSING_TEXT2 = "9876543210"; - final int COMPOSING_TEXT_START2 = 3; - final int INSERTION_MARKER_FLAGS2 = - FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL; - final float INSERTION_MARKER_HORIZONTAL2 = 14.5f; - final float INSERTION_MARKER_TOP2 = 200.1f; - final float INSERTION_MARKER_BASELINE2 = 210.4f; - final float INSERTION_MARKER_BOTOM2 = 211.0f; - - // Default instance should be equal. - assertEquals(new Builder().build(), new Builder().build()); - - assertEquals( - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(), - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build()); - assertNotEquals( - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(), - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END2).build()); - assertNotEquals( - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(), - new Builder().setSelectionRange(SELECTION_START2, SELECTION_END1).build()); - assertNotEquals( - new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(), - new Builder().setSelectionRange(SELECTION_START2, SELECTION_END2).build()); - assertEquals( - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(), - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build()); - assertNotEquals( - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(), - new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT1).build()); - assertNotEquals( - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(), - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT2).build()); - assertNotEquals( - new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(), - new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT2).build()); - - // 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, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - Float.NaN, Float.NaN, Float.NaN, Float.NaN, - INSERTION_MARKER_FLAGS1).build()); - - // Check Matrix. - assertEquals( - new Builder().setMatrix(MATRIX1).build(), - new Builder().setMatrix(MATRIX1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).build(), - new Builder().setMatrix(MATRIX2).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).build(), - new Builder().setMatrix(NAN_MATRIX).build()); - // Unlike insertion marker locations, {@link Float#NaN} in the matrix is treated as just a - // NaN as usual (NaN == NaN -> false). - assertNotEquals( - new Builder().setMatrix(NAN_MATRIX).build(), - new Builder().setMatrix(NAN_MATRIX).build()); - - assertEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - Float.NaN, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2, - INSERTION_MARKER_FLAGS1).build()); - assertNotEquals( - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS1).build(), - new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation( - INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1, - INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1, - INSERTION_MARKER_FLAGS2).build()); - } - - @Test - public void testMatrixIsCopied() throws Exception { - final Matrix MATRIX1 = new Matrix(); - MATRIX1.setTranslate(10.0f, 20.0f); - final Matrix MATRIX2 = new Matrix(); - MATRIX2.setTranslate(110.0f, 120.0f); - final Matrix MATRIX3 = new Matrix(); - MATRIX3.setTranslate(210.0f, 220.0f); - final Matrix matrix = new Matrix(); - final Builder builder = new Builder(); - - matrix.set(MATRIX1); - builder.setMatrix(matrix); - matrix.postRotate(90.0f); - - final CursorAnchorInfo firstInstance = builder.build(); - assertEquals(MATRIX1, firstInstance.getMatrix()); - matrix.set(MATRIX2); - builder.setMatrix(matrix); - final CursorAnchorInfo secondInstance = builder.build(); - assertEquals(MATRIX1, firstInstance.getMatrix()); - assertEquals(MATRIX2, secondInstance.getMatrix()); - - matrix.set(MATRIX3); - assertEquals(MATRIX1, firstInstance.getMatrix()); - assertEquals(MATRIX2, secondInstance.getMatrix()); - } - - @Test - public void testMatrixIsRequired() throws Exception { - final int SELECTION_START = 30; - final int SELECTION_END = 40; - final int COMPOSING_TEXT_START = 32; - final String COMPOSING_TEXT = "test"; - final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION; - final float INSERTION_MARKER_HORIZONTAL = 10.5f; - final float INSERTION_MARKER_TOP = 100.1f; - final float INSERTION_MARKER_BASELINE = 110.4f; - final float INSERTION_MARKER_BOTOM = 111.0f; - Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX); - TRANSFORM_MATRIX.setScale(10.0f, 20.0f); - - final Builder builder = new Builder(); - // Check twice to make sure if Builder#reset() works as expected. - for (int repeatCount = 0; repeatCount < 2; ++repeatCount) { - builder.setSelectionRange(SELECTION_START, SELECTION_END) - .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT); - try { - // Should succeed as coordinate transformation matrix is not required if no - // positional information is specified. - builder.build(); - } catch (IllegalArgumentException ex) { - assertTrue(false); - } - - builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP, - INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS); - try { - // Coordinate transformation matrix is required if no positional information is - // specified. - builder.build(); - assertTrue(false); - } catch (IllegalArgumentException ex) { - } - - builder.setMatrix(TRANSFORM_MATRIX); - try { - // Should succeed as coordinate transformation matrix is required. - builder.build(); - } catch (IllegalArgumentException ex) { - assertTrue(false); - } - - builder.reset(); - } - } - - @Test - public void testBuilderAddCharacterBounds() throws Exception { - // A negative index should be rejected. - try { - new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION); - assertTrue(false); - } catch (IllegalArgumentException ex) { - } - } - - private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) { - Parcel parcel = null; - try { - parcel = Parcel.obtain(); - src.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - return new CursorAnchorInfo(parcel); - } finally { - if (parcel != null) { - parcel.recycle(); - } - } + assertEquals(newMatrix, newInstanceByBuilder.getMatrix()); + assertEquals(newMatrix, newInstanceByMethod.getMatrix()); + assertEquals(newInstanceByBuilder.hashCode(), newInstanceByMethod.hashCode()); } }