Skip to content

Commit d27f1cd

Browse files
adampAndroid (Google) Code Review
authored andcommitted
Merge "Further refine touchMajor processing in ScaleGestureDetector" into jb-mr1-dev
2 parents 75b694f + 5b5c414 commit d27f1cd

File tree

1 file changed

+49
-108
lines changed

1 file changed

+49
-108
lines changed

core/java/android/view/ScaleGestureDetector.java

Lines changed: 49 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
import android.content.Context;
2020
import android.os.SystemClock;
2121
import android.util.FloatMath;
22-
import android.util.Log;
23-
24-
import java.util.Arrays;
2522

2623
/**
2724
* Detects scaling transformation gestures using the supplied {@link MotionEvent}s.
@@ -143,11 +140,16 @@ public void onScaleEnd(ScaleGestureDetector detector) {
143140
private int mSpanSlop;
144141
private int mMinSpan;
145142

146-
private float[] mTouchHistoryLastAccepted;
147-
private int[] mTouchHistoryDirection;
148-
private long[] mTouchHistoryLastAcceptedTime;
143+
// Bounds for recently seen values
144+
private float mTouchUpper;
145+
private float mTouchLower;
146+
private float mTouchHistoryLastAccepted;
147+
private int mTouchHistoryDirection;
148+
private long mTouchHistoryLastAcceptedTime;
149+
private int mTouchMinMajor;
149150

150151
private static final long TOUCH_STABILIZE_TIME = 128; // ms
152+
private static final int TOUCH_MIN_MAJOR = 48; // dp
151153

152154
/**
153155
* Consistency verifier for debugging purposes.
@@ -160,6 +162,8 @@ public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
160162
mContext = context;
161163
mListener = listener;
162164
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
165+
mTouchMinMajor =
166+
(int) (context.getResources().getDisplayMetrics().density * TOUCH_MIN_MAJOR + 0.5f);
163167
mMinSpan = context.getResources().getDimensionPixelSize(
164168
com.android.internal.R.dimen.config_minScalingSpan);
165169
}
@@ -172,123 +176,67 @@ public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
172176
private void addTouchHistory(MotionEvent ev) {
173177
final long currentTime = SystemClock.uptimeMillis();
174178
final int count = ev.getPointerCount();
179+
boolean accept = currentTime - mTouchHistoryLastAcceptedTime >= TOUCH_STABILIZE_TIME;
180+
float total = 0;
181+
int sampleCount = 0;
175182
for (int i = 0; i < count; i++) {
176-
final int id = ev.getPointerId(i);
177-
ensureTouchHistorySize(id);
178-
179-
final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted[id]);
180-
boolean accept = true;
183+
final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted);
181184
final int historySize = ev.getHistorySize();
182-
for (int h = 0; h < historySize + 1; h++) {
183-
final float major;
184-
final float minor;
185+
final int pointerSampleCount = historySize + 1;
186+
for (int h = 0; h < pointerSampleCount; h++) {
187+
float major;
185188
if (h < historySize) {
186189
major = ev.getHistoricalTouchMajor(i, h);
187-
minor = ev.getHistoricalTouchMinor(i, h);
188190
} else {
189191
major = ev.getTouchMajor(i);
190-
minor = ev.getTouchMinor(i);
191192
}
192-
final float avg = (major + minor) / 2;
193+
if (major < mTouchMinMajor) major = mTouchMinMajor;
194+
total += major;
195+
196+
if (Float.isNaN(mTouchUpper) || major > mTouchUpper) {
197+
mTouchUpper = major;
198+
}
199+
if (Float.isNaN(mTouchLower) || major < mTouchLower) {
200+
mTouchLower = major;
201+
}
193202

194203
if (hasLastAccepted) {
195-
final int directionSig = (int) Math.signum(avg - mTouchHistoryLastAccepted[id]);
196-
if (directionSig != mTouchHistoryDirection[id] ||
197-
(directionSig == 0 && mTouchHistoryDirection[id] == 0)) {
198-
mTouchHistoryDirection[id] = directionSig;
204+
final int directionSig = (int) Math.signum(major - mTouchHistoryLastAccepted);
205+
if (directionSig != mTouchHistoryDirection ||
206+
(directionSig == 0 && mTouchHistoryDirection == 0)) {
207+
mTouchHistoryDirection = directionSig;
199208
final long time = h < historySize ? ev.getHistoricalEventTime(h)
200209
: ev.getEventTime();
201-
mTouchHistoryLastAcceptedTime[id] = time;
202-
accept = false;
203-
}
204-
if (currentTime - mTouchHistoryLastAcceptedTime[id] < TOUCH_STABILIZE_TIME) {
210+
mTouchHistoryLastAcceptedTime = time;
205211
accept = false;
206212
}
207213
}
208214
}
209-
210-
if (accept) {
211-
float newAccepted = (ev.getTouchMajor(i) + ev.getTouchMinor(i)) / 2;
212-
if (hasLastAccepted) {
213-
newAccepted = (mTouchHistoryLastAccepted[id] + newAccepted) / 2;
214-
}
215-
mTouchHistoryLastAccepted[id] = newAccepted;
216-
mTouchHistoryDirection[id] = 0;
217-
mTouchHistoryLastAcceptedTime[id] = ev.getEventTime();
218-
}
215+
sampleCount += pointerSampleCount;
219216
}
220-
}
221217

222-
/**
223-
* Clear out the touch history for a given pointer id.
224-
* @param id pointer id to clear
225-
* @see #addTouchHistory(MotionEvent)
226-
*/
227-
private boolean removeTouchHistoryForId(int id) {
228-
if (id >= mTouchHistoryLastAccepted.length) {
229-
return false;
230-
}
231-
mTouchHistoryLastAccepted[id] = Float.NaN;
232-
mTouchHistoryDirection[id] = 0;
233-
mTouchHistoryLastAcceptedTime[id] = 0;
234-
return true;
235-
}
218+
final float avg = total / sampleCount;
236219

237-
/**
238-
* Get the adjusted combined touchMajor/touchMinor value for a given pointer id
239-
* @param id the pointer id of the data to obtain
240-
* @return the adjusted major/minor value for the point at id
241-
* @see #addTouchHistory(MotionEvent)
242-
*/
243-
private float getAdjustedTouchHistory(int id) {
244-
if (id >= mTouchHistoryLastAccepted.length) {
245-
Log.e(TAG, "Error retrieving adjusted touch history for id=" + id +
246-
" - incomplete event stream?");
247-
return 0;
220+
if (accept) {
221+
float newAccepted = (mTouchUpper + mTouchLower + avg) / 3;
222+
mTouchUpper = (mTouchUpper + newAccepted) / 2;
223+
mTouchLower = (mTouchLower + newAccepted) / 2;
224+
mTouchHistoryLastAccepted = newAccepted;
225+
mTouchHistoryDirection = 0;
226+
mTouchHistoryLastAcceptedTime = ev.getEventTime();
248227
}
249-
return mTouchHistoryLastAccepted[id];
250228
}
251229

252230
/**
253231
* Clear all touch history tracking. Useful in ACTION_CANCEL or ACTION_UP.
254232
* @see #addTouchHistory(MotionEvent)
255233
*/
256234
private void clearTouchHistory() {
257-
if (mTouchHistoryLastAccepted == null) {
258-
// All three arrays will be null if this is the case; nothing to do.
259-
return;
260-
}
261-
Arrays.fill(mTouchHistoryLastAccepted, Float.NaN);
262-
Arrays.fill(mTouchHistoryDirection, 0);
263-
Arrays.fill(mTouchHistoryLastAcceptedTime, 0);
264-
}
265-
266-
private void ensureTouchHistorySize(int id) {
267-
final int requiredSize = id + 1;
268-
if (mTouchHistoryLastAccepted == null || mTouchHistoryLastAccepted.length < requiredSize) {
269-
final float[] newLastAccepted = new float[requiredSize];
270-
final int[] newDirection = new int[requiredSize];
271-
final long[] newLastAcceptedTime = new long[requiredSize];
272-
273-
int oldLength = 0;
274-
if (mTouchHistoryLastAccepted != null) {
275-
System.arraycopy(mTouchHistoryLastAccepted, 0, newLastAccepted, 0,
276-
mTouchHistoryLastAccepted.length);
277-
System.arraycopy(mTouchHistoryDirection, 0, newDirection, 0,
278-
mTouchHistoryDirection.length);
279-
System.arraycopy(mTouchHistoryLastAcceptedTime, 0, newLastAcceptedTime, 0,
280-
mTouchHistoryLastAcceptedTime.length);
281-
oldLength = mTouchHistoryLastAccepted.length;
282-
}
283-
284-
Arrays.fill(newLastAccepted, oldLength, newLastAccepted.length, Float.NaN);
285-
Arrays.fill(newDirection, oldLength, newDirection.length, 0);
286-
Arrays.fill(newLastAcceptedTime, oldLength, newLastAcceptedTime.length, 0);
287-
288-
mTouchHistoryLastAccepted = newLastAccepted;
289-
mTouchHistoryDirection = newDirection;
290-
mTouchHistoryLastAcceptedTime = newLastAcceptedTime;
291-
}
235+
mTouchUpper = Float.NaN;
236+
mTouchLower = Float.NaN;
237+
mTouchHistoryLastAccepted = Float.NaN;
238+
mTouchHistoryDirection = 0;
239+
mTouchHistoryLastAcceptedTime = 0;
292240
}
293241

294242
/**
@@ -346,23 +294,16 @@ public boolean onTouchEvent(MotionEvent event) {
346294
final float focusX = sumX / div;
347295
final float focusY = sumY / div;
348296

349-
if (pointerUp) {
350-
final int id = event.getPointerId(event.getActionIndex());
351-
if (!removeTouchHistoryForId(id)) {
352-
Log.e(TAG, "Got ACTION_POINTER_UP for previously unknown id=" + id +
353-
" - incomplete event stream?");
354-
}
355-
} else {
356-
addTouchHistory(event);
357-
}
297+
298+
addTouchHistory(event);
358299

359300
// Determine average deviation from focal point
360301
float devSumX = 0, devSumY = 0;
361302
for (int i = 0; i < count; i++) {
362303
if (skipIndex == i) continue;
363304

364-
// Average touch major and touch minor and convert the resulting diameter into a radius.
365-
final float touchSize = getAdjustedTouchHistory(event.getPointerId(i)) / 2;
305+
// Convert the resulting diameter into a radius.
306+
final float touchSize = mTouchHistoryLastAccepted / 2;
366307
devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
367308
devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
368309
}

0 commit comments

Comments
 (0)