From c7dc673cf0fb56015826079423ced659b9180feb Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 14 Sep 2012 18:10:39 +0900 Subject: Use Path to draw gesture preview trail This change also reduces the number of points to use as preview trail. Bug: 7167303 Change-Id: I0cf4908efa44b17b42d4fddd6725238236ac2654 --- .../inputmethod/keyboard/PointerTracker.java | 47 +++---- .../keyboard/internal/GesturePreviewTrail.java | 135 ++++++++++++++++++--- .../keyboard/internal/GestureStroke.java | 2 +- .../internal/GestureStrokeWithPreviewPoints.java | 97 +++++++++++++++ .../internal/GestureStrokeWithPreviewTrail.java | 70 ----------- .../keyboard/internal/PreviewPlacerView.java | 2 +- 6 files changed, 243 insertions(+), 110 deletions(-) create mode 100644 java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java delete mode 100644 java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index a6439c46a..2bde8d2c5 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,7 +23,7 @@ import android.view.MotionEvent; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.keyboard.internal.GestureStroke; -import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewTrail; +import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.InputPointers; @@ -208,7 +208,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener.Adapter(); - private final GestureStrokeWithPreviewTrail mGestureStrokeWithPreviewTrail; + private final GestureStrokeWithPreviewPoints mGestureStrokeWithPreviewPoints; public static void init(boolean hasDistinctMultitouch, boolean needsPhantomSuddenMoveEventHack) { @@ -293,7 +293,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { throw new NullPointerException(); } mPointerId = id; - mGestureStrokeWithPreviewTrail = new GestureStrokeWithPreviewTrail(id); + mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(id); setKeyDetectorInner(handler.getKeyDetector()); mListener = handler.getKeyboardActionListener(); mDrawingProxy = handler.getDrawingProxy(); @@ -392,7 +392,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { private void setKeyDetectorInner(final KeyDetector keyDetector) { mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); - mGestureStrokeWithPreviewTrail.setGestureSampleLength(mKeyboard.mMostCommonKeyWidth); + mGestureStrokeWithPreviewPoints.setKeyboardGeometry(mKeyboard.mMostCommonKeyWidth); final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY); if (newKey != mCurrentKey) { if (mDrawingProxy != null) { @@ -502,8 +502,8 @@ public class PointerTracker implements PointerTrackerQueue.Element { mDrawingProxy.invalidateKey(key); } - public GestureStrokeWithPreviewTrail getGestureStrokeWithPreviewTrail() { - return mGestureStrokeWithPreviewTrail; + public GestureStrokeWithPreviewPoints getGestureStrokeWithPreviewPoints() { + return mGestureStrokeWithPreviewPoints; } public int getLastX() { @@ -544,8 +544,8 @@ public class PointerTracker implements PointerTrackerQueue.Element { return (sPointerTrackerQueue == null) ? 1 : sPointerTrackerQueue.size(); } - private void startBatchInput() { - if (sInGesture || !mGestureStrokeWithPreviewTrail.isStartOfAGesture()) { + private void mayStartBatchInput() { + if (sInGesture || !mGestureStrokeWithPreviewPoints.isStartOfAGesture()) { return; } if (DEBUG_LISTENER) { @@ -559,7 +559,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { private void updateBatchInput(final long eventTime) { synchronized (sAggregratedPointers) { - mGestureStrokeWithPreviewTrail.appendIncrementalBatchPoints(sAggregratedPointers); + mGestureStrokeWithPreviewPoints.appendIncrementalBatchPoints(sAggregratedPointers); final int size = sAggregratedPointers.getPointerSize(); if (size > sLastRecognitionPointSize && eventTime > sLastRecognitionTime + MIN_GESTURE_RECOGNITION_TIME) { @@ -575,10 +575,10 @@ public class PointerTracker implements PointerTrackerQueue.Element { mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } - private void endBatchInput() { + private void mayEndBatchInput() { synchronized (sAggregratedPointers) { - mGestureStrokeWithPreviewTrail.appendAllBatchPoints(sAggregratedPointers); - mGestureStrokeWithPreviewTrail.reset(); + mGestureStrokeWithPreviewPoints.appendAllBatchPoints(sAggregratedPointers); + mGestureStrokeWithPreviewPoints.reset(); if (getActivePointerTrackerCount() == 1) { if (DEBUG_LISTENER) { Log.d(TAG, "onEndBatchInput: batchPoints=" @@ -601,7 +601,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { final int trackersSize = sTrackers.size(); for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); - tracker.mGestureStrokeWithPreviewTrail.reset(); + tracker.mGestureStrokeWithPreviewPoints.reset(); } sAggregratedPointers.reset(); sLastRecognitionPointSize = 0; @@ -678,18 +678,21 @@ public class PointerTracker implements PointerTrackerQueue.Element { && mKeyboard.mId.isAlphabetKeyboard(); if (isAlphabetKeyboard && !mIsShowingMoreKeysPanel && key != null && Keyboard.isLetterCode(key.mCode)) { - mIsDetectingGesture = true; sGestureFirstDownTime = eventTime; - mGestureStrokeWithPreviewTrail.addPoint(x, y, 0, false /* isHistorical */); + onGestureDownEvent(x, y, eventTime); } } else if (sInGesture && activePointerTrackerCount > 1) { - mIsDetectingGesture = true; - final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime); - mGestureStrokeWithPreviewTrail.addPoint(x, y, elapsedTimeFromFirstDown, - false /* isHistorical */); + onGestureDownEvent(x, y, eventTime); } } + private void onGestureDownEvent(final int x, final int y, final long eventTime) { + mIsDetectingGesture = true; + final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime); + mGestureStrokeWithPreviewPoints.addPoint(x, y, elapsedTimeFromFirstDown, + false /* isHistorical */); + } + private void onDownEventInternal(final int x, final int y, final long eventTime) { Key key = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding @@ -726,8 +729,8 @@ public class PointerTracker implements PointerTrackerQueue.Element { final boolean isHistorical, final Key key) { final int gestureTime = (int)(eventTime - sGestureFirstDownTime); if (mIsDetectingGesture) { - mGestureStrokeWithPreviewTrail.addPoint(x, y, gestureTime, isHistorical); - startBatchInput(); + mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isHistorical); + mayStartBatchInput(); if (sInGesture && key != null) { updateBatchInput(eventTime); } @@ -919,7 +922,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { if (currentKey != null) { callListenerOnRelease(currentKey, currentKey.mCode, true); } - endBatchInput(); + mayEndBatchInput(); return; } // This event will be recognized as a regular code input. Clear unused possible batch points diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java index 4311fa775..699aaeaef 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java @@ -17,7 +17,9 @@ package com.android.inputmethod.keyboard.internal; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.Rect; +import android.graphics.RectF; import android.os.SystemClock; import com.android.inputmethod.latin.Constants; @@ -25,7 +27,7 @@ import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.ResizableIntArray; final class GesturePreviewTrail { - private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewTrail.PREVIEW_CAPACITY; + private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewPoints.PREVIEW_CAPACITY; private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); @@ -78,7 +80,7 @@ final class GesturePreviewTrail { ? DOWN_EVENT_MARKER - xCoordOrMark : xCoordOrMark; } - public void addStroke(final GestureStrokeWithPreviewTrail stroke, final long downTime) { + public void addStroke(final GestureStrokeWithPreviewPoints stroke, final long downTime) { final int trailSize = mEventTimes.getLength(); stroke.appendPreviewStroke(mEventTimes, mXCoordinates, mYCoordinates); if (mEventTimes.getLength() == trailSize) { @@ -116,6 +118,99 @@ final class GesturePreviewTrail { / params.mTrailLingerDuration, 0.0f); } + static final class WorkingSet { + // Input + // Previous point (P1) coordinates and trail radius. + public float p1x, p1y; + public float r1; + // Current point (P2) coordinates and trail radius. + public float p2x, p2y; + public float r2; + + // Output + // Closing point of arc at P1. + public float p1ax, p1ay; + // Opening point of arc at P1. + public float p1bx, p1by; + // Opening point of arc at P2. + public float p2ax, p2ay; + // Closing point of arc at P2. + public float p2bx, p2by; + // Start angle of the trail arcs. + public float aa; + // Sweep angle of the trail arc at P1. + public float a1; + public RectF arc1 = new RectF(); + // Sweep angle of the trail arc at P2. + public float a2; + public RectF arc2 = new RectF(); + } + + private static final float RIGHT_ANGLE = (float)(Math.PI / 2.0d); + private static final float RADIAN_TO_DEGREE = (float)(180.0d / Math.PI); + + private static boolean calculatePathPoints(final WorkingSet w) { + final float dx = w.p2x - w.p1x; + final float dy = w.p2y - w.p1y; + // Distance of the points. + final double l = Math.hypot(dx, dy); + if (Double.compare(0.0d, l) == 0) { + return false; + } + // Angle of the line p1-p2 + final float a = (float)Math.atan2(dy, dx); + // Difference of trail cap radius. + final float dr = w.r2 - w.r1; + // Variation of angle at trail cap. + final float ar = (float)Math.asin(dr / l); + // The start angle of trail cap arc at P1. + final float aa = a - (RIGHT_ANGLE + ar); + // The end angle of trail cap arc at P2. + final float ab = a + (RIGHT_ANGLE + ar); + final float cosa = (float)Math.cos(aa); + final float sina = (float)Math.sin(aa); + final float cosb = (float)Math.cos(ab); + final float sinb = (float)Math.sin(ab); + w.p1ax = w.p1x + w.r1 * cosa; + w.p1ay = w.p1y + w.r1 * sina; + w.p1bx = w.p1x + w.r1 * cosb; + w.p1by = w.p1y + w.r1 * sinb; + w.p2ax = w.p2x + w.r2 * cosa; + w.p2ay = w.p2y + w.r2 * sina; + w.p2bx = w.p2x + w.r2 * cosb; + w.p2by = w.p2y + w.r2 * sinb; + w.aa = aa * RADIAN_TO_DEGREE; + final float ar2degree = ar * 2.0f * RADIAN_TO_DEGREE; + w.a1 = -180.0f + ar2degree; + w.a2 = 180.0f + ar2degree; + w.arc1.set(w.p1x, w.p1y, w.p1x, w.p1y); + w.arc1.inset(-w.r1, -w.r1); + w.arc2.set(w.p2x, w.p2y, w.p2x, w.p2y); + w.arc2.inset(-w.r2, -w.r2); + return true; + } + + private static void createPath(final Path path, final WorkingSet w) { + path.rewind(); + // Trail cap at P1. + path.moveTo(w.p1x, w.p1y); + path.arcTo(w.arc1, w.aa, w.a1); + // Trail cap at P2. + path.moveTo(w.p2x, w.p2y); + path.arcTo(w.arc2, w.aa, w.a2); + // Two trapezoids connecting P1 and P2. + path.moveTo(w.p1ax, w.p1ay); + path.lineTo(w.p1x, w.p1y); + path.lineTo(w.p1bx, w.p1by); + path.lineTo(w.p2bx, w.p2by); + path.lineTo(w.p2x, w.p2y); + path.lineTo(w.p2ax, w.p2ay); + path.close(); + } + + private final WorkingSet mWorkingSet = new WorkingSet(); + private final Path mPath = new Path(); + /** * Draw gesture preview trail * @param canvas The canvas to draw the gesture preview trail @@ -147,30 +242,38 @@ final class GesturePreviewTrail { if (startIndex < trailSize) { paint.setColor(params.mTrailColor); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeCap(Paint.Cap.ROUND); - int lastX = getXCoordValue(xCoords[startIndex]); - int lastY = yCoords[startIndex]; - float maxWidth = getWidth(sinceDown - eventTimes[startIndex], params); + paint.setStyle(Paint.Style.FILL); + final Path path = mPath; + final WorkingSet w = mWorkingSet; + w.p1x = getXCoordValue(xCoords[startIndex]); + w.p1y = yCoords[startIndex]; + int lastTime = sinceDown - eventTimes[startIndex]; + float maxWidth = getWidth(lastTime, params); + w.r1 = maxWidth / 2.0f; // Initialize bounds rectangle. - outBoundsRect.set(lastX, lastY, lastX, lastY); + outBoundsRect.set((int)w.p1x, (int)w.p1y, (int)w.p1x, (int)w.p1y); for (int i = startIndex + 1; i < trailSize - 1; i++) { - final int x = xCoords[i]; - final int y = yCoords[i]; final int elapsedTime = sinceDown - eventTimes[i]; + w.p2x = getXCoordValue(xCoords[i]); + w.p2y = yCoords[i]; // Draw trail line only when the current point isn't a down point. - if (!isDownEventXCoord(x)) { + if (!isDownEventXCoord(xCoords[i])) { final int alpha = getAlpha(elapsedTime, params); paint.setAlpha(alpha); final float width = getWidth(elapsedTime, params); - paint.setStrokeWidth(width); - canvas.drawLine(lastX, lastY, x, y, paint); + w.r2 = width / 2.0f; + if (calculatePathPoints(w)) { + createPath(path, w); + canvas.drawPath(path, paint); + outBoundsRect.union((int)w.p2x, (int)w.p2y); + } // Take union for the bounds. - outBoundsRect.union(x, y); maxWidth = Math.max(maxWidth, width); } - lastX = getXCoordValue(x); - lastY = y; + w.p1x = w.p2x; + w.p1y = w.p2y; + w.r1 = w.r2; + lastTime = elapsedTime; } // Take care of trail line width. final int inset = -((int)maxWidth + 1); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java index 7a8c2409c..093a530d5 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java @@ -44,7 +44,7 @@ public class GestureStroke { mPointerId = pointerId; } - public void setGestureSampleLength(final int keyWidth) { + public void setKeyboardGeometry(final int keyWidth) { // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key? mMinGestureLength = (int)(keyWidth * MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH); mMinGestureSampleLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java new file mode 100644 index 000000000..ce3914076 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import com.android.inputmethod.latin.ResizableIntArray; + +public class GestureStrokeWithPreviewPoints extends GestureStroke { + public static final int PREVIEW_CAPACITY = 256; + + private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY); + private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY); + private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY); + + private int mStrokeId; + private int mLastPreviewSize; + + private int mMinPreviewSampleLengthSquare; + private int mLastX; + private int mLastY; + + // TODO: Move this to resource. + private static final float MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH = 0.1f; + + public GestureStrokeWithPreviewPoints(final int pointerId) { + super(pointerId); + } + + @Override + public void reset() { + super.reset(); + mStrokeId++; + mLastPreviewSize = 0; + mPreviewEventTimes.setLength(0); + mPreviewXCoordinates.setLength(0); + mPreviewYCoordinates.setLength(0); + } + + public int getGestureStrokeId() { + return mStrokeId; + } + + public int getGestureStrokePreviewSize() { + return mPreviewEventTimes.getLength(); + } + + @Override + public void setKeyboardGeometry(final int keyWidth) { + super.setKeyboardGeometry(keyWidth); + final float sampleLength = keyWidth * MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH; + mMinPreviewSampleLengthSquare = (int)(sampleLength * sampleLength); + } + + private boolean needsSampling(final int x, final int y) { + final int dx = x - mLastX; + final int dy = y - mLastY; + final boolean needsSampling = (dx * dx + dy * dy >= mMinPreviewSampleLengthSquare); + if (needsSampling) { + mLastX = x; + mLastY = y; + } + return needsSampling; + } + + @Override + public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { + super.addPoint(x, y, time, isHistorical); + if (mPreviewEventTimes.getLength() == 0 || isHistorical || needsSampling(x, y)) { + mPreviewEventTimes.add(time); + mPreviewXCoordinates.add(x); + mPreviewYCoordinates.add(y); + } + } + + public void appendPreviewStroke(final ResizableIntArray eventTimes, + final ResizableIntArray xCoords, final ResizableIntArray yCoords) { + final int length = mPreviewEventTimes.getLength() - mLastPreviewSize; + if (length <= 0) { + return; + } + eventTimes.append(mPreviewEventTimes, mLastPreviewSize, length); + xCoords.append(mPreviewXCoordinates, mLastPreviewSize, length); + yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length); + mLastPreviewSize = mPreviewEventTimes.getLength(); + } +} diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java deleted file mode 100644 index 6c1a9bc01..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewTrail.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import com.android.inputmethod.latin.ResizableIntArray; - -public class GestureStrokeWithPreviewTrail extends GestureStroke { - public static final int PREVIEW_CAPACITY = 256; - - private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY); - private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY); - private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY); - - private int mStrokeId; - private int mLastPreviewSize; - - public GestureStrokeWithPreviewTrail(final int pointerId) { - super(pointerId); - } - - @Override - public void reset() { - super.reset(); - mStrokeId++; - mLastPreviewSize = 0; - mPreviewEventTimes.setLength(0); - mPreviewXCoordinates.setLength(0); - mPreviewYCoordinates.setLength(0); - } - - public int getGestureStrokeId() { - return mStrokeId; - } - - public int getGestureStrokePreviewSize() { - return mPreviewEventTimes.getLength(); - } - - @Override - public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { - super.addPoint(x, y, time, isHistorical); - mPreviewEventTimes.add(time); - mPreviewXCoordinates.add(x); - mPreviewYCoordinates.add(y); - } - - public void appendPreviewStroke(final ResizableIntArray eventTimes, - final ResizableIntArray xCoords, final ResizableIntArray yCoords) { - final int length = mPreviewEventTimes.getLength() - mLastPreviewSize; - if (length <= 0) { - return; - } - eventTimes.append(mPreviewEventTimes, mLastPreviewSize, length); - xCoords.append(mPreviewXCoordinates, mLastPreviewSize, length); - yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length); - mLastPreviewSize = mPreviewEventTimes.getLength(); - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java index 915ce1f36..075a9bb0c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java @@ -205,7 +205,7 @@ public class PreviewPlacerView extends RelativeLayout { mGesturePreviewTrails.put(tracker.mPointerId, trail); } } - trail.addStroke(tracker.getGestureStrokeWithPreviewTrail(), tracker.getDownTime()); + trail.addStroke(tracker.getGestureStrokeWithPreviewPoints(), tracker.getDownTime()); } // TODO: Should narrow the invalidate region. -- cgit v1.2.3-83-g751a