Merge "Fix inefficient CursorAnchorInfo#hashCode()." into nyc-dev
am: a8c81c1
* commit 'a8c81c1a804cad61735753ff87ebb7bbf1a57383':
Fix inefficient CursorAnchorInfo#hashCode().
Change-Id: I7d9f82b77ad2eed036446bd072ba91ebf1972377
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.view.inputmethod;
|
package android.view.inputmethod;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -25,6 +26,7 @@ import android.text.SpannedString;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
|
import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +37,11 @@ import java.util.Objects;
|
|||||||
* actually inserted.</p>
|
* actually inserted.</p>
|
||||||
*/
|
*/
|
||||||
public final class CursorAnchorInfo implements Parcelable {
|
public final class CursorAnchorInfo implements Parcelable {
|
||||||
|
/**
|
||||||
|
* The pre-computed hash code.
|
||||||
|
*/
|
||||||
|
private final int mHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index of the first character of the selected text (inclusive). {@code -1} when there is
|
* The index of the first character of the selected text (inclusive). {@code -1} when there is
|
||||||
* no text selection.
|
* no text selection.
|
||||||
@@ -100,7 +107,8 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
* Transformation matrix that is applied to any positional information of this class to
|
* Transformation matrix that is applied to any positional information of this class to
|
||||||
* transform local coordinates into screen coordinates.
|
* transform local coordinates into screen coordinates.
|
||||||
*/
|
*/
|
||||||
private final Matrix mMatrix;
|
@NonNull
|
||||||
|
private final float[] mMatrixValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
|
* Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
|
||||||
@@ -121,6 +129,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
public static final int FLAG_IS_RTL = 0x04;
|
public static final int FLAG_IS_RTL = 0x04;
|
||||||
|
|
||||||
public CursorAnchorInfo(final Parcel source) {
|
public CursorAnchorInfo(final Parcel source) {
|
||||||
|
mHashCode = source.readInt();
|
||||||
mSelectionStart = source.readInt();
|
mSelectionStart = source.readInt();
|
||||||
mSelectionEnd = source.readInt();
|
mSelectionEnd = source.readInt();
|
||||||
mComposingTextStart = source.readInt();
|
mComposingTextStart = source.readInt();
|
||||||
@@ -131,8 +140,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
mInsertionMarkerBaseline = source.readFloat();
|
mInsertionMarkerBaseline = source.readFloat();
|
||||||
mInsertionMarkerBottom = source.readFloat();
|
mInsertionMarkerBottom = source.readFloat();
|
||||||
mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
|
mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
|
||||||
mMatrix = new Matrix();
|
mMatrixValues = source.createFloatArray();
|
||||||
mMatrix.setValues(source.createFloatArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,6 +151,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(mHashCode);
|
||||||
dest.writeInt(mSelectionStart);
|
dest.writeInt(mSelectionStart);
|
||||||
dest.writeInt(mSelectionEnd);
|
dest.writeInt(mSelectionEnd);
|
||||||
dest.writeInt(mComposingTextStart);
|
dest.writeInt(mComposingTextStart);
|
||||||
@@ -153,27 +162,12 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
dest.writeFloat(mInsertionMarkerBaseline);
|
dest.writeFloat(mInsertionMarkerBaseline);
|
||||||
dest.writeFloat(mInsertionMarkerBottom);
|
dest.writeFloat(mInsertionMarkerBottom);
|
||||||
dest.writeParcelable(mCharacterBoundsArray, flags);
|
dest.writeParcelable(mCharacterBoundsArray, flags);
|
||||||
final float[] matrixArray = new float[9];
|
dest.writeFloatArray(mMatrixValues);
|
||||||
mMatrix.getValues(matrixArray);
|
|
||||||
dest.writeFloatArray(matrixArray);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(){
|
public int hashCode(){
|
||||||
final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
|
return mHashCode;
|
||||||
+ mInsertionMarkerBaseline + mInsertionMarkerBottom;
|
|
||||||
int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
|
|
||||||
hash *= 31;
|
|
||||||
hash += mInsertionMarkerFlags;
|
|
||||||
hash *= 31;
|
|
||||||
hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
|
|
||||||
hash *= 31;
|
|
||||||
hash += Objects.hashCode(mComposingText);
|
|
||||||
hash *= 31;
|
|
||||||
hash += Objects.hashCode(mCharacterBoundsArray);
|
|
||||||
hash *= 31;
|
|
||||||
hash += Objects.hashCode(mMatrix);
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,13 +196,13 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
if (hashCode() != that.hashCode()) {
|
if (hashCode() != that.hashCode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check fields that are not covered by hashCode() first.
|
||||||
|
|
||||||
if (mSelectionStart != that.mSelectionStart || mSelectionEnd != that.mSelectionEnd) {
|
if (mSelectionStart != that.mSelectionStart || mSelectionEnd != that.mSelectionEnd) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mComposingTextStart != that.mComposingTextStart
|
|
||||||
|| !Objects.equals(mComposingText, that.mComposingText)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
|
if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
|
||||||
|| !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
|
|| !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
|
||||||
|| !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
|
|| !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
|
||||||
@@ -216,18 +210,35 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
|
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
|
if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Objects.equals(mMatrix, that.mMatrix)) {
|
|
||||||
|
// Following fields are (partially) covered by hashCode().
|
||||||
|
|
||||||
|
if (mComposingTextStart != that.mComposingTextStart
|
||||||
|
|| !Objects.equals(mComposingText, that.mComposingText)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do not use Arrays.equals(float[], float[]) to keep the previous behavior regarding
|
||||||
|
// NaN, 0.0f, and -0.0f.
|
||||||
|
if (mMatrixValues.length != that.mMatrixValues.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mMatrixValues.length; ++i) {
|
||||||
|
if (mMatrixValues[i] != that.mMatrixValues[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
|
return "CursorAnchorInfo{mHashCode=" + mHashCode
|
||||||
|
+ " mSelection=" + mSelectionStart + "," + mSelectionEnd
|
||||||
+ " mComposingTextStart=" + mComposingTextStart
|
+ " mComposingTextStart=" + mComposingTextStart
|
||||||
+ " mComposingText=" + Objects.toString(mComposingText)
|
+ " mComposingText=" + Objects.toString(mComposingText)
|
||||||
+ " mInsertionMarkerFlags=" + mInsertionMarkerFlags
|
+ " mInsertionMarkerFlags=" + mInsertionMarkerFlags
|
||||||
@@ -236,7 +247,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
|
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
|
||||||
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
|
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
|
||||||
+ " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
|
+ " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
|
||||||
+ " mMatrix=" + Objects.toString(mMatrix)
|
+ " mMatrix=" + Arrays.toString(mMatrixValues)
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +265,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
private float mInsertionMarkerBottom = Float.NaN;
|
private float mInsertionMarkerBottom = Float.NaN;
|
||||||
private int mInsertionMarkerFlags = 0;
|
private int mInsertionMarkerFlags = 0;
|
||||||
private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
|
private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
|
||||||
private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
|
private float[] mMatrixValues = null;
|
||||||
private boolean mMatrixInitialized = false;
|
private boolean mMatrixInitialized = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,7 +360,10 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
* is interpreted as an identity matrix.
|
* is interpreted as an identity matrix.
|
||||||
*/
|
*/
|
||||||
public Builder setMatrix(final Matrix matrix) {
|
public Builder setMatrix(final Matrix matrix) {
|
||||||
mMatrix.set(matrix != null ? matrix : Matrix.IDENTITY_MATRIX);
|
if (mMatrixValues == null) {
|
||||||
|
mMatrixValues = new float[9];
|
||||||
|
}
|
||||||
|
(matrix != null ? matrix : Matrix.IDENTITY_MATRIX).getValues(mMatrixValues);
|
||||||
mMatrixInitialized = true;
|
mMatrixInitialized = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -391,7 +405,6 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
mInsertionMarkerTop = Float.NaN;
|
mInsertionMarkerTop = Float.NaN;
|
||||||
mInsertionMarkerBaseline = Float.NaN;
|
mInsertionMarkerBaseline = Float.NaN;
|
||||||
mInsertionMarkerBottom = Float.NaN;
|
mInsertionMarkerBottom = Float.NaN;
|
||||||
mMatrix.set(Matrix.IDENTITY_MATRIX);
|
|
||||||
mMatrixInitialized = false;
|
mMatrixInitialized = false;
|
||||||
if (mCharacterBoundsArrayBuilder != null) {
|
if (mCharacterBoundsArrayBuilder != null) {
|
||||||
mCharacterBoundsArrayBuilder.reset();
|
mCharacterBoundsArrayBuilder.reset();
|
||||||
@@ -411,7 +424,18 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
|
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
|
||||||
mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
|
mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
|
||||||
builder.mCharacterBoundsArrayBuilder.build() : null;
|
builder.mCharacterBoundsArrayBuilder.build() : null;
|
||||||
mMatrix = new Matrix(builder.mMatrix);
|
mMatrixValues = new float[9];
|
||||||
|
if (builder.mMatrixInitialized) {
|
||||||
|
System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9);
|
||||||
|
} else {
|
||||||
|
Matrix.IDENTITY_MATRIX.getValues(mMatrixValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -527,7 +551,9 @@ public final class CursorAnchorInfo implements Parcelable {
|
|||||||
* @return a new instance (copy) of the transformation matrix.
|
* @return a new instance (copy) of the transformation matrix.
|
||||||
*/
|
*/
|
||||||
public Matrix getMatrix() {
|
public Matrix getMatrix() {
|
||||||
return new Matrix(mMatrix);
|
final Matrix matrix = new Matrix();
|
||||||
|
matrix.setValues(mMatrixValues);
|
||||||
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user