diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java index 2e638aaf3..6b489da30 100644 --- a/java/src/com/android/inputmethod/latin/InputPointers.java +++ b/java/src/com/android/inputmethod/latin/InputPointers.java @@ -16,14 +16,16 @@ package com.android.inputmethod.latin; +import android.util.Log; + import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.utils.ResizableIntArray; -import android.util.Log; - // TODO: This class is not thread-safe. public final class InputPointers { private static final String TAG = InputPointers.class.getSimpleName(); + private static final boolean DEBUG_TIME = false; + private final int mDefaultCapacity; private final ResizableIntArray mXCoordinates; private final ResizableIntArray mYCoordinates; @@ -38,10 +40,29 @@ public final class InputPointers { mTimes = new ResizableIntArray(defaultCapacity); } + private void fillWithLastTimeUntil(final int index) { + final int fromIndex = mTimes.getLength(); + // Fill the gap with the latest time. + // See {@link #getTime(int)} and {@link #isValidTimeStamps()}. + if (fromIndex <= 0) { + return; + } + final int fillLength = index - fromIndex + 1; + if (fillLength <= 0) { + return; + } + final int lastTime = mTimes.get(fromIndex - 1); + mTimes.fill(lastTime, fromIndex, fillLength); + } + + // TODO: Rename this method to addPointerAt public void addPointer(int index, int x, int y, int pointerId, int time) { mXCoordinates.add(index, x); mYCoordinates.add(index, y); mPointerIds.add(index, pointerId); + if (LatinImeLogger.sDBG || DEBUG_TIME) { + fillWithLastTimeUntil(index); + } mTimes.add(index, time); } @@ -67,23 +88,6 @@ public final class InputPointers { mTimes.copy(ip.mTimes); } - /** - * Append the pointers in the specified {@link InputPointers} to the end of this. - * @param src the source {@link InputPointers} to read the data from. - * @param startPos the starting index of the pointers in {@code src}. - * @param length the number of pointers to be appended. - */ - @UsedForTesting - void append(InputPointers src, int startPos, int length) { - if (length == 0) { - return; - } - mXCoordinates.append(src.mXCoordinates, startPos, length); - mYCoordinates.append(src.mYCoordinates, startPos, length); - mPointerIds.append(src.mPointerIds, startPos, length); - mTimes.append(src.mTimes, startPos, length); - } - /** * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray} * to the end of this. @@ -141,7 +145,7 @@ public final class InputPointers { } public int[] getTimes() { - if (LatinImeLogger.sDBG) { + if (LatinImeLogger.sDBG || DEBUG_TIME) { if (!isValidTimeStamps()) { throw new RuntimeException("Time stamps are invalid."); } @@ -157,10 +161,11 @@ public final class InputPointers { private boolean isValidTimeStamps() { final int[] times = mTimes.getPrimitiveArray(); - for (int i = 1; i < getPointerSize(); ++i) { + final int size = getPointerSize(); + for (int i = 1; i < size; ++i) { if (times[i] < times[i - 1]) { // dump - for (int j = 0; j < times.length; ++j) { + for (int j = 0; j < size; ++j) { Log.d(TAG, "--- (" + j + ") " + times[j]); } return false; diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/InputPointersTests.java index 5095f9606..4c67d1927 100644 --- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java +++ b/tests/src/com/android/inputmethod/latin/InputPointersTests.java @@ -55,14 +55,22 @@ public class InputPointersTests extends AndroidTestCase { final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final int limit = src.getXCoordinates().length * 2 + 10; for (int i = 0; i < limit; i++) { - src.addPointer(i, i * 2, i * 3, i * 4); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + src.addPointer(x, y, pointerId, time); assertEquals("size after add " + i, i + 1, src.getPointerSize()); } for (int i = 0; i < limit; i++) { - assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]); - assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]); - assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]); - assertEquals("times at " + i, i * 4, src.getTimes()[i]); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]); + assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]); + assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]); + assertEquals("times at " + i, time, src.getTimes()[i]); } } @@ -70,14 +78,22 @@ public class InputPointersTests extends AndroidTestCase { final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final int limit = 1000, step = 100; for (int i = 0; i < limit; i += step) { - src.addPointer(i, i, i * 2, i * 3, i * 4); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + src.addPointer(i, x, y, pointerId, time); assertEquals("size after add at " + i, i + 1, src.getPointerSize()); } for (int i = 0; i < limit; i += step) { - assertEquals("xCoordinates at " + i, i, src.getXCoordinates()[i]); - assertEquals("yCoordinates at " + i, i * 2, src.getYCoordinates()[i]); - assertEquals("pointerIds at " + i, i * 3, src.getPointerIds()[i]); - assertEquals("times at " + i, i * 4, src.getTimes()[i]); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]); + assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]); + assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]); + assertEquals("times at " + i, time, src.getTimes()[i]); } } @@ -85,7 +101,11 @@ public class InputPointersTests extends AndroidTestCase { final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final int limit = src.getXCoordinates().length * 2 + 10; for (int i = 0; i < limit; i++) { - src.addPointer(i, i * 2, i * 3, i * 4); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + src.addPointer(x, y, pointerId, time); } final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); dst.set(src); @@ -100,7 +120,11 @@ public class InputPointersTests extends AndroidTestCase { final InputPointers src = new InputPointers(DEFAULT_CAPACITY); final int limit = 100; for (int i = 0; i < limit; i++) { - src.addPointer(i, i * 2, i * 3, i * 4); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + src.addPointer(x, y, pointerId, time); } final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); dst.copy(src); @@ -121,106 +145,135 @@ public class InputPointersTests extends AndroidTestCase { } public void testAppend() { - final InputPointers src = new InputPointers(DEFAULT_CAPACITY); - final int srcLen = 100; - for (int i = 0; i < srcLen; i++) { - src.addPointer(i, i * 2, i * 3, i * 4); - } - final int dstLen = 50; + final int dstLength = 50; final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); - for (int i = 0; i < dstLen; i++) { - final int value = -i - 1; - dst.addPointer(value * 4, value * 3, value * 2, value); + for (int i = 0; i < dstLength; i++) { + final int x = i * 4; + final int y = i * 3; + final int pointerId = i * 2; + final int time = i; + dst.addPointer(x, y, pointerId, time); } final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY); dstCopy.copy(dst); - dst.append(src, 0, 0); - assertEquals("size after append zero", dstLen, dst.getPointerSize()); - assertIntArrayEquals("xCoordinates after append zero", - dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); - assertIntArrayEquals("yCoordinates after append zero", - dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); - assertIntArrayEquals("pointerIds after append zero", - dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); - assertIntArrayEquals("times after append zero", - dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); + final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY); + final ResizableIntArray srcYCoords = new ResizableIntArray(DEFAULT_CAPACITY); + final ResizableIntArray srcPointerIds = new ResizableIntArray(DEFAULT_CAPACITY); + final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY); + final int srcLength = 100; + final int srcPointerId = 10; + for (int i = 0; i < srcLength; i++) { + final int x = i; + final int y = i * 2; + // The time value must be larger than dst. + final int time = i * 4 + dstLength; + srcXCoords.add(x); + srcYCoords.add(y); + srcPointerIds.add(srcPointerId); + srcTimes.add(time); + } - dst.append(src, 0, srcLen); - assertEquals("size after append", dstLen + srcLen, dst.getPointerSize()); + final int startPos = 0; + dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, + startPos, 0 /* length */); + assertEquals("size after append zero", dstLength, dst.getPointerSize()); + assertIntArrayEquals("xCoordinates after append zero", + dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength); + assertIntArrayEquals("yCoordinates after append zero", + dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength); + assertIntArrayEquals("pointerIds after append zero", + dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength); + assertIntArrayEquals("times after append zero", + dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength); + + dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, + startPos, srcLength); + assertEquals("size after append", dstLength + srcLength, dst.getPointerSize()); assertTrue("primitive length after append", - dst.getPointerIds().length >= dstLen + srcLen); + dst.getPointerIds().length >= dstLength + srcLength); assertIntArrayEquals("original xCoordinates values after append", - dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); + dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength); assertIntArrayEquals("original yCoordinates values after append", - dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); + dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength); assertIntArrayEquals("original pointerIds values after append", - dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); + dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength); assertIntArrayEquals("original times values after append", - dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); + dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength); assertIntArrayEquals("appended xCoordinates values after append", - src.getXCoordinates(), 0, dst.getXCoordinates(), dstLen, srcLen); + srcXCoords.getPrimitiveArray(), startPos, dst.getXCoordinates(), + dstLength, srcLength); assertIntArrayEquals("appended yCoordinates values after append", - src.getYCoordinates(), 0, dst.getYCoordinates(), dstLen, srcLen); + srcYCoords.getPrimitiveArray(), startPos, dst.getYCoordinates(), + dstLength, srcLength); assertIntArrayEquals("appended pointerIds values after append", - src.getPointerIds(), 0, dst.getPointerIds(), dstLen, srcLen); + srcPointerIds.getPrimitiveArray(), startPos, dst.getPointerIds(), + dstLength, srcLength); assertIntArrayEquals("appended times values after append", - src.getTimes(), 0, dst.getTimes(), dstLen, srcLen); + srcTimes.getPrimitiveArray(), startPos, dst.getTimes(), dstLength, srcLength); } public void testAppendResizableIntArray() { - final int srcLen = 100; + final int dstLength = 50; + final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); + for (int i = 0; i < dstLength; i++) { + final int x = i * 4; + final int y = i * 3; + final int pointerId = i * 2; + final int time = i; + dst.addPointer(x, y, pointerId, time); + } + final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY); + dstCopy.copy(dst); + + final int srcLength = 100; final int srcPointerId = 1; - final int[] srcPointerIds = new int[srcLen]; + final int[] srcPointerIds = new int[srcLength]; Arrays.fill(srcPointerIds, srcPointerId); final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY); final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY); final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY); - for (int i = 0; i < srcLen; i++) { - srcTimes.add(i * 2); - srcXCoords.add(i * 3); - srcYCoords.add(i * 4); + for (int i = 0; i < srcLength; i++) { + // The time value must be larger than dst. + final int time = i * 2 + dstLength; + final int x = i * 3; + final int y = i * 4; + srcTimes.add(time); + srcXCoords.add(x); + srcYCoords.add(y); } - final int dstLen = 50; - final InputPointers dst = new InputPointers(DEFAULT_CAPACITY); - for (int i = 0; i < dstLen; i++) { - final int value = -i - 1; - dst.addPointer(value * 4, value * 3, value * 2, value); - } - final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY); - dstCopy.copy(dst); dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0); - assertEquals("size after append zero", dstLen, dst.getPointerSize()); + assertEquals("size after append zero", dstLength, dst.getPointerSize()); assertIntArrayEquals("xCoordinates after append zero", - dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); + dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength); assertIntArrayEquals("yCoordinates after append zero", - dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); + dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength); assertIntArrayEquals("pointerIds after append zero", - dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); + dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength); assertIntArrayEquals("times after append zero", - dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); + dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength); - dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLen); - assertEquals("size after append", dstLen + srcLen, dst.getPointerSize()); + dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLength); + assertEquals("size after append", dstLength + srcLength, dst.getPointerSize()); assertTrue("primitive length after append", - dst.getPointerIds().length >= dstLen + srcLen); + dst.getPointerIds().length >= dstLength + srcLength); assertIntArrayEquals("original xCoordinates values after append", - dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLen); + dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength); assertIntArrayEquals("original yCoordinates values after append", - dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLen); + dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength); assertIntArrayEquals("original pointerIds values after append", - dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLen); + dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength); assertIntArrayEquals("original times values after append", - dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLen); + dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength); assertIntArrayEquals("appended xCoordinates values after append", - srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLen, srcLen); + srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLength, srcLength); assertIntArrayEquals("appended yCoordinates values after append", - srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLen, srcLen); + srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLength, srcLength); assertIntArrayEquals("appended pointerIds values after append", - srcPointerIds, 0, dst.getPointerIds(), dstLen, srcLen); + srcPointerIds, 0, dst.getPointerIds(), dstLength, srcLength); assertIntArrayEquals("appended times values after append", - srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLen, srcLen); + srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLength, srcLength); } // TODO: Consolidate this method with @@ -250,14 +303,24 @@ public class InputPointersTests extends AndroidTestCase { final int limit = 100; final int shiftAmount = 20; for (int i = 0; i < limit; i++) { - src.addPointer(i, i * 2, i * 3, i * 4); + final int x = i; + final int y = i * 2; + final int pointerId = i * 3; + final int time = i * 4; + src.addPointer(x, y, pointerId, time); } src.shift(shiftAmount); + assertEquals("length after shift", src.getPointerSize(), limit - shiftAmount); for (int i = 0; i < limit - shiftAmount; ++i) { - assertEquals("xCoordinates at " + i, i + shiftAmount, src.getXCoordinates()[i]); - assertEquals("yCoordinates at " + i, (i + shiftAmount) * 2, src.getYCoordinates()[i]); - assertEquals("pointerIds at " + i, (i + shiftAmount) * 3, src.getPointerIds()[i]); - assertEquals("times at " + i, (i + shiftAmount) * 4, src.getTimes()[i]); + final int oldIndex = i + shiftAmount; + final int x = oldIndex; + final int y = oldIndex * 2; + final int pointerId = oldIndex * 3; + final int time = oldIndex * 4; + assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]); + assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]); + assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]); + assertEquals("times at " + i, time, src.getTimes()[i]); } } }