1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.latin.common;
18 
19 import com.android.inputmethod.annotations.UsedForTesting;
20 
21 import javax.annotation.Nonnull;
22 
23 // TODO: This class is not thread-safe.
24 public final class InputPointers {
25     private static final boolean DEBUG_TIME = false;
26 
27     private final int mDefaultCapacity;
28     private final ResizableIntArray mXCoordinates;
29     private final ResizableIntArray mYCoordinates;
30     private final ResizableIntArray mPointerIds;
31     private final ResizableIntArray mTimes;
32 
InputPointers(final int defaultCapacity)33     public InputPointers(final int defaultCapacity) {
34         mDefaultCapacity = defaultCapacity;
35         mXCoordinates = new ResizableIntArray(defaultCapacity);
36         mYCoordinates = new ResizableIntArray(defaultCapacity);
37         mPointerIds = new ResizableIntArray(defaultCapacity);
38         mTimes = new ResizableIntArray(defaultCapacity);
39     }
40 
fillWithLastTimeUntil(final int index)41     private void fillWithLastTimeUntil(final int index) {
42         final int fromIndex = mTimes.getLength();
43         // Fill the gap with the latest time.
44         // See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
45         if (fromIndex <= 0) {
46             return;
47         }
48         final int fillLength = index - fromIndex + 1;
49         if (fillLength <= 0) {
50             return;
51         }
52         final int lastTime = mTimes.get(fromIndex - 1);
53         mTimes.fill(lastTime, fromIndex, fillLength);
54     }
55 
addPointerAt(final int index, final int x, final int y, final int pointerId, final int time)56     public void addPointerAt(final int index, final int x, final int y, final int pointerId,
57             final int time) {
58         mXCoordinates.addAt(index, x);
59         mYCoordinates.addAt(index, y);
60         mPointerIds.addAt(index, pointerId);
61         if (DEBUG_TIME) {
62             fillWithLastTimeUntil(index);
63         }
64         mTimes.addAt(index, time);
65     }
66 
67     @UsedForTesting
addPointer(final int x, final int y, final int pointerId, final int time)68     public void addPointer(final int x, final int y, final int pointerId, final int time) {
69         mXCoordinates.add(x);
70         mYCoordinates.add(y);
71         mPointerIds.add(pointerId);
72         mTimes.add(time);
73     }
74 
set(@onnull final InputPointers ip)75     public void set(@Nonnull final InputPointers ip) {
76         mXCoordinates.set(ip.mXCoordinates);
77         mYCoordinates.set(ip.mYCoordinates);
78         mPointerIds.set(ip.mPointerIds);
79         mTimes.set(ip.mTimes);
80     }
81 
copy(@onnull final InputPointers ip)82     public void copy(@Nonnull final InputPointers ip) {
83         mXCoordinates.copy(ip.mXCoordinates);
84         mYCoordinates.copy(ip.mYCoordinates);
85         mPointerIds.copy(ip.mPointerIds);
86         mTimes.copy(ip.mTimes);
87     }
88 
89     /**
90      * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
91      * to the end of this.
92      * @param pointerId the pointer id of the source.
93      * @param times the source {@link ResizableIntArray} to read the event times from.
94      * @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from.
95      * @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from.
96      * @param startPos the starting index of the data in {@code times} and etc.
97      * @param length the number of data to be appended.
98      */
append(final int pointerId, @Nonnull final ResizableIntArray times, @Nonnull final ResizableIntArray xCoordinates, @Nonnull final ResizableIntArray yCoordinates, final int startPos, final int length)99     public void append(final int pointerId, @Nonnull final ResizableIntArray times,
100             @Nonnull final ResizableIntArray xCoordinates,
101             @Nonnull final ResizableIntArray yCoordinates, final int startPos, final int length) {
102         if (length == 0) {
103             return;
104         }
105         mXCoordinates.append(xCoordinates, startPos, length);
106         mYCoordinates.append(yCoordinates, startPos, length);
107         mPointerIds.fill(pointerId, mPointerIds.getLength(), length);
108         mTimes.append(times, startPos, length);
109     }
110 
111     /**
112      * Shift to the left by elementCount, discarding elementCount pointers at the start.
113      * @param elementCount how many elements to shift.
114      */
115     @UsedForTesting
shift(final int elementCount)116     public void shift(final int elementCount) {
117         mXCoordinates.shift(elementCount);
118         mYCoordinates.shift(elementCount);
119         mPointerIds.shift(elementCount);
120         mTimes.shift(elementCount);
121     }
122 
reset()123     public void reset() {
124         final int defaultCapacity = mDefaultCapacity;
125         mXCoordinates.reset(defaultCapacity);
126         mYCoordinates.reset(defaultCapacity);
127         mPointerIds.reset(defaultCapacity);
128         mTimes.reset(defaultCapacity);
129     }
130 
getPointerSize()131     public int getPointerSize() {
132         return mXCoordinates.getLength();
133     }
134 
135     @Nonnull
getXCoordinates()136     public int[] getXCoordinates() {
137         return mXCoordinates.getPrimitiveArray();
138     }
139 
140     @Nonnull
getYCoordinates()141     public int[] getYCoordinates() {
142         return mYCoordinates.getPrimitiveArray();
143     }
144 
145     @Nonnull
getPointerIds()146     public int[] getPointerIds() {
147         return mPointerIds.getPrimitiveArray();
148     }
149 
150     /**
151      * Gets the time each point was registered, in milliseconds, relative to the first event in the
152      * sequence.
153      * @return The time each point was registered, in milliseconds, relative to the first event in
154      * the sequence.
155      */
156     @Nonnull
getTimes()157     public int[] getTimes() {
158         return mTimes.getPrimitiveArray();
159     }
160 
161     @Override
toString()162     public String toString() {
163         return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes
164                 + " x=" + mXCoordinates + " y=" + mYCoordinates;
165     }
166 }
167