171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka/* 271538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka * Copyright (C) 2012 The Android Open Source Project 371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka * 48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License. 68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at 771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka * 88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka * 1071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software 118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and 148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License. 1571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka */ 1671538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 1771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataokapackage com.android.inputmethod.latin; 1871538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 1915f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaokaimport com.android.inputmethod.annotations.UsedForTesting; 20e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.ResizableIntArray; 2115f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka 22f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataokaimport android.util.Log; 23f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka 247247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka// TODO: This class is not thread-safe. 25a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class InputPointers { 26f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka private static final String TAG = InputPointers.class.getSimpleName(); 2757f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka private final int mDefaultCapacity; 289370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private final ResizableIntArray mXCoordinates; 299370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private final ResizableIntArray mYCoordinates; 309370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private final ResizableIntArray mPointerIds; 319370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private final ResizableIntArray mTimes; 3257f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka 3357f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka public InputPointers(int defaultCapacity) { 3457f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka mDefaultCapacity = defaultCapacity; 359370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mXCoordinates = new ResizableIntArray(defaultCapacity); 369370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mYCoordinates = new ResizableIntArray(defaultCapacity); 379370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mPointerIds = new ResizableIntArray(defaultCapacity); 389370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mTimes = new ResizableIntArray(defaultCapacity); 3957f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka } 4071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 4171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public void addPointer(int index, int x, int y, int pointerId, int time) { 4271538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mXCoordinates.add(index, x); 4371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mYCoordinates.add(index, y); 4471538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mPointerIds.add(index, pointerId); 4571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mTimes.add(index, time); 4671538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 4771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 4815f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @UsedForTesting 4915f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka void addPointer(int x, int y, int pointerId, int time) { 5071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mXCoordinates.add(x); 5171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mYCoordinates.add(y); 5271538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mPointerIds.add(pointerId); 5371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mTimes.add(time); 5471538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 5571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 5671538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public void set(InputPointers ip) { 5771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mXCoordinates.set(ip.mXCoordinates); 5871538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mYCoordinates.set(ip.mYCoordinates); 5971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mPointerIds.set(ip.mPointerIds); 6071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mTimes.set(ip.mTimes); 6171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 6271538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 6371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public void copy(InputPointers ip) { 6471538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mXCoordinates.copy(ip.mXCoordinates); 6571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mYCoordinates.copy(ip.mYCoordinates); 6671538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mPointerIds.copy(ip.mPointerIds); 6771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka mTimes.copy(ip.mTimes); 6871538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 6971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 701087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka /** 711087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka * Append the pointers in the specified {@link InputPointers} to the end of this. 727247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka * @param src the source {@link InputPointers} to read the data from. 731087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka * @param startPos the starting index of the pointers in {@code src}. 741087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka * @param length the number of pointers to be appended. 751087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka */ 7615f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @UsedForTesting 7715f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka void append(InputPointers src, int startPos, int length) { 789580c467f96c542c66af86a2c376612ba4d91434Tadashi G. Takaoka if (length == 0) { 799580c467f96c542c66af86a2c376612ba4d91434Tadashi G. Takaoka return; 809580c467f96c542c66af86a2c376612ba4d91434Tadashi G. Takaoka } 817247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka mXCoordinates.append(src.mXCoordinates, startPos, length); 827247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka mYCoordinates.append(src.mYCoordinates, startPos, length); 837247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka mPointerIds.append(src.mPointerIds, startPos, length); 847247bff6d6d488640ac752127148e7746c43469dTadashi G. Takaoka mTimes.append(src.mTimes, startPos, length); 851087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka } 861087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka 877519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka /** 887519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray} 897519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * to the end of this. 907519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param pointerId the pointer id of the source. 917519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param times the source {@link ResizableIntArray} to read the event times from. 927519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from. 937519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from. 947519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param startPos the starting index of the data in {@code times} and etc. 957519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka * @param length the number of data to be appended. 967519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka */ 977519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka public void append(int pointerId, ResizableIntArray times, ResizableIntArray xCoordinates, 987519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka ResizableIntArray yCoordinates, int startPos, int length) { 997519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka if (length == 0) { 1007519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka return; 1017519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka } 1027519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka mXCoordinates.append(xCoordinates, startPos, length); 1037519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka mYCoordinates.append(yCoordinates, startPos, length); 10464a26b4389abb273afff7699a8c86596defd85bfTadashi G. Takaoka mPointerIds.fill(pointerId, mPointerIds.getLength(), length); 1057519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka mTimes.append(times, startPos, length); 1067519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka } 1077519091f7c15c50a9a1e50d82fa92400335852ecTadashi G. Takaoka 108e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi /** 109e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi * Shift to the left by elementCount, discarding elementCount pointers at the start. 110e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi * @param elementCount how many elements to shift. 111e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi */ 112e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi public void shift(final int elementCount) { 113e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi mXCoordinates.shift(elementCount); 114e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi mYCoordinates.shift(elementCount); 115e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi mPointerIds.shift(elementCount); 116e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi mTimes.shift(elementCount); 117e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi } 118e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi 11971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public void reset() { 12057f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka final int defaultCapacity = mDefaultCapacity; 12157f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka mXCoordinates.reset(defaultCapacity); 12257f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka mYCoordinates.reset(defaultCapacity); 12357f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka mPointerIds.reset(defaultCapacity); 12457f7de0ba664187e13bcea5adff7f5f65eddd823Tadashi G. Takaoka mTimes.reset(defaultCapacity); 12571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 12671538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 12771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public int getPointerSize() { 12871538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka return mXCoordinates.getLength(); 12971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 13071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 13171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public int[] getXCoordinates() { 1321087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka return mXCoordinates.getPrimitiveArray(); 13371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 13471538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 13571538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public int[] getYCoordinates() { 1361087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka return mYCoordinates.getPrimitiveArray(); 13771538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 13871538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 13971538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public int[] getPointerIds() { 1401087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka return mPointerIds.getPrimitiveArray(); 14171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 14271538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka 14371538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka public int[] getTimes() { 144f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka if (LatinImeLogger.sDBG) { 145f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka if (!isValidTimeStamps()) { 146f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka throw new RuntimeException("Time stamps are invalid."); 147f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 148f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 1491087c53f5a6ced093eb4e71f88cff19e89819d73Tadashi G. Takaoka return mTimes.getPrimitiveArray(); 15071538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka } 15164ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka 15264ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka @Override 15364ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka public String toString() { 15464ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes 15564ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka + " x=" + mXCoordinates + " y=" + mYCoordinates; 15664ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka } 157f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka 158f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka private boolean isValidTimeStamps() { 159f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka final int[] times = mTimes.getPrimitiveArray(); 160f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka for (int i = 1; i < getPointerSize(); ++i) { 161f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka if (times[i] < times[i - 1]) { 162f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka // dump 163f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka for (int j = 0; j < times.length; ++j) { 164f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka Log.d(TAG, "--- (" + j + ") " + times[j]); 165f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 166f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka return false; 167f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 168f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 169f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka return true; 170f1074c508e70b3489dc85c036f7ed49d3196ba47Satoshi Kataoka } 17171538b08e4e08d556f700ad344562ca2c7b74d82Satoshi Kataoka} 172