From e4410a135ba4fbafa6594181eff50fe5145194b3 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Thu, 25 Apr 2019 18:49:16 -0700 Subject: [PATCH] Add an @hide way to adjust CursorAnchorInfo for another Matrix This is a preparation to support CursorAnchorInfo API in ActivityView. In order to enable the system to automatically adjust CursorAnchorInfo object between the IME client and IME, there needs to be an @hide method to create a new CursorAnchorInfo instance with applying an additional coordinate transformation Matrix, which is what this CL does. This CL also cleans up CursorAnchorInfoTest.java as most of test there were already moved to CTS [1]. Anyway, this is a mechanical change. There should be no behavior change in existing methods in CursorAnchorInfo. [1]: Ib758bddff34b4722b39c94e7ad4e8f8da2bb8b92 c4ef1d6ec22dc2af2ed339fd4e78075903783be0 Bug: 115693908 Test: atest CtsInputMethodTestCases:CursorAnchorInfoTest Test: atest FrameworksCoreTests:CursorAnchorInfoTest Change-Id: Ic7f9057623ffc61ec7a6121735dc39adecf4649d --- .../view/inputmethod/CursorAnchorInfo.java | 101 +++- .../inputmethod/CursorAnchorInfoTest.java | 451 +----------------- 2 files changed, 102 insertions(+), 450 deletions(-) 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()); } }