merge in jb-mr1-release history after reset to jb-mr1-dev
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 5a79d50..4887ac5 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -573,6 +573,7 @@
     private void endBatchInput() {
         synchronized (sAggregratedPointers) {
             mGestureStrokeWithPreviewTrail.appendAllBatchPoints(sAggregratedPointers);
+            mGestureStrokeWithPreviewTrail.reset();
             if (getActivePointerTrackerCount() == 1) {
                 if (DEBUG_LISTENER) {
                     Log.d(TAG, "onEndBatchInput: batchPoints="
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index 7442b7f..95c9572 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -33,15 +33,10 @@
     private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
     private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY);
     private int mCurrentStrokeId = -1;
-    private long mCurrentDownTime;
+    // The wall time of the zero value in {@link #mEventTimes}
+    private long mCurrentTimeBase;
     private int mTrailStartIndex;
 
-    private final static Xfermode PORTER_DUFF_MODE_SRC =
-            new PorterDuffXfermode(PorterDuff.Mode.SRC);
-
-    // Use this value as imaginary zero because x-coordinates may be zero.
-    private static final int DOWN_EVENT_MARKER = -128;
-
     static final class Params {
         public final int mTrailColor;
         public final float mTrailStartWidth;
@@ -69,6 +64,9 @@
         }
     }
 
+    // Use this value as imaginary zero because x-coordinates may be zero.
+    private static final int DOWN_EVENT_MARKER = -128;
+
     private static int markAsDownEvent(final int xCoord) {
         return DOWN_EVENT_MARKER - xCoord;
     }
@@ -83,26 +81,23 @@
     }
 
     public void addStroke(final GestureStrokeWithPreviewTrail stroke, final long downTime) {
-        final int strokeId = stroke.getGestureStrokeId();
-        final boolean isNewStroke = strokeId != mCurrentStrokeId;
         final int trailSize = mEventTimes.getLength();
         stroke.appendPreviewStroke(mEventTimes, mXCoordinates, mYCoordinates);
-        final int newTrailSize = mEventTimes.getLength();
-        if (stroke.getGestureStrokePreviewSize() == 0) {
+        if (mEventTimes.getLength() == trailSize) {
             return;
         }
-        if (isNewStroke) {
-            final int elapsedTime = (int)(downTime - mCurrentDownTime);
-            final int[] eventTimes = mEventTimes.getPrimitiveArray();
+        final int[] eventTimes = mEventTimes.getPrimitiveArray();
+        final int strokeId = stroke.getGestureStrokeId();
+        if (strokeId != mCurrentStrokeId) {
+            final int elapsedTime = (int)(downTime - mCurrentTimeBase);
             for (int i = mTrailStartIndex; i < trailSize; i++) {
+                // Decay the previous strokes' event times.
                 eventTimes[i] -= elapsedTime;
             }
-
-            if (newTrailSize > trailSize) {
-                final int[] xCoords = mXCoordinates.getPrimitiveArray();
-                xCoords[trailSize] = markAsDownEvent(xCoords[trailSize]);
-            }
-            mCurrentDownTime = downTime;
+            final int[] xCoords = mXCoordinates.getPrimitiveArray();
+            final int downIndex = trailSize;
+            xCoords[downIndex] = markAsDownEvent(xCoords[downIndex]);
+            mCurrentTimeBase = downTime - eventTimes[downIndex];
             mCurrentStrokeId = strokeId;
         }
     }
@@ -123,6 +118,9 @@
                 / params.mTrailLingerDuration, 0.0f);
     }
 
+    private final static Xfermode PORTER_DUFF_MODE_SRC =
+            new PorterDuffXfermode(PorterDuff.Mode.SRC);
+
     /**
      * Draw gesture preview trail
      * @param canvas The canvas to draw the gesture preview trail
@@ -139,7 +137,7 @@
         final int[] eventTimes = mEventTimes.getPrimitiveArray();
         final int[] xCoords = mXCoordinates.getPrimitiveArray();
         final int[] yCoords = mYCoordinates.getPrimitiveArray();
-        final int sinceDown = (int)(SystemClock.uptimeMillis() - mCurrentDownTime);
+        final int sinceDown = (int)(SystemClock.uptimeMillis() - mCurrentTimeBase);
         int startIndex;
         for (startIndex = mTrailStartIndex; startIndex < trailSize; startIndex++) {
             final int elapsedTime = sinceDown - eventTimes[startIndex];
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
index 8dde4d6..dbde4ef 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
@@ -158,7 +158,6 @@
 
         final Paint textPaint = new Paint();
         textPaint.setAntiAlias(true);
-        textPaint.setStyle(Paint.Style.FILL);
         textPaint.setTextAlign(Align.CENTER);
         textPaint.setTextSize(gestureFloatingPreviewTextSize);
         mTextPaint = textPaint;
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 92cfd1a..15a7131 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -55,7 +55,7 @@
             }
             AKLOGI("[ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d ]",
                     c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10]);
-            (void)c;
+            (void)c; // To suppress compiler warning
         }
     }
 }
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index c62b9b3..8c3174c 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -224,7 +224,7 @@
 bool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
         const NearKeysDistanceMap *const prevNearKeysDistances,
         const NearKeysDistanceMap *const prevPrevNearKeysDistances) const {
-    static const float MARGIN = 0.05f;
+    static const float MARGIN = 0.01f;
 
     for (NearKeysDistanceMap::const_iterator it = prevNearKeysDistances->begin();
         it != prevNearKeysDistances->end(); ++it) {
@@ -245,16 +245,19 @@
         const NearKeysDistanceMap *const prevNearKeysDistances,
         const NearKeysDistanceMap *const prevPrevNearKeysDistances) const {
     static const float BASE_SAMPLE_RATE_SCALE = 0.1f;
-    static const float SAVE_DISTANCE_SCALE = 14.0f;
+    static const float SAVE_DISTANCE_SCALE = 20.0f;
     static const float SAVE_DISTANCE_SCORE = 2.0f;
-    static const float SKIP_DISTANCE_SCALE = 1.5f;
+    static const float SKIP_DISTANCE_SCALE = 2.5f;
     static const float SKIP_DISTANCE_SCORE = -1.0f;
-    static const float CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 3.5f;
+    static const float CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 4.0f;
     static const float CHECK_LOCALMIN_DISTANCE_SCORE = -1.0f;
-    static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 32.0f;
+    static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 36.0f;
     static const float STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 5.0f;
     static const float STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD = 0.5f;
     static const float STRAIGHT_SKIP_SCORE = -1.0f;
+    static const float CORNER_ANGLE_THRESHOLD = M_PI_F / 2.0f;
+    static const float CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 2.7f;
+    static const float CORNER_SCORE = 1.0f;
 
     const std::size_t size = mInputXs.size();
     if (size <= 1) {
@@ -276,20 +279,26 @@
     }
     // Location
     if (distPrev < baseSampleRate * CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE) {
-        if (!isPrevLocalMin(currentNearKeysDistances, currentNearKeysDistances,
+        if (!isPrevLocalMin(currentNearKeysDistances, prevNearKeysDistances,
             prevPrevNearKeysDistances)) {
             score += CHECK_LOCALMIN_DISTANCE_SCORE;
         }
     }
     // Angle
+    const float angle1 = getAngle(x, y, mInputXs.back(), mInputYs.back());
+    const float angle2 = getAngle(mInputXs.back(), mInputYs.back(),
+            mInputXs[size - 2], mInputYs[size - 2]);
+    const float angleDiff = getAngleDiff(angle1, angle2);
+    // Skip straight
     if (nearest > STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD
-            && distPrev < baseSampleRate * STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE) {
-        const float angle1 = getAngle(x, y, mInputXs.back(), mInputYs.back());
-        const float angle2 = getAngle(mInputXs.back(), mInputYs.back(),
-                mInputXs[size - 2], mInputYs[size - 2]);
-        if (getAngleDiff(angle1, angle2) < STRAIGHT_ANGLE_THRESHOLD) {
-            score += STRAIGHT_SKIP_SCORE;
-        }
+            && distPrev < baseSampleRate * STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE
+            && angleDiff < STRAIGHT_ANGLE_THRESHOLD) {
+        score += STRAIGHT_SKIP_SCORE;
+    }
+    // Save corner
+    if (distPrev > baseSampleRate * CORNER_CHECK_DISTANCE_THRESHOLD_SCALE
+            && angleDiff > CORNER_ANGLE_THRESHOLD) {
+        score += CORNER_SCORE;
     }
     return score;
 }
@@ -447,9 +456,9 @@
 
 float ProximityInfoState::getAveragePointDuration() const {
     if (mInputSize == 0) {
-        return 0;
+        return 0.0f;
     }
-    return (mTimes[mInputSize - 1] - mTimes[0]) / static_cast<float>(mInputSize);
+    return static_cast<float>(mTimes[mInputSize - 1] - mTimes[0]) / static_cast<float>(mInputSize);
 }
 
 } // namespace latinime
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index cf806c1..6eaff48 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -225,7 +225,7 @@
             short unsigned int *w = outWords + j * MAX_WORD_LENGTH;
             char s[MAX_WORD_LENGTH];
             for (int i = 0; i <= MAX_WORD_LENGTH; i++) s[i] = w[i];
-            (void)s;
+            (void)s; // To suppress compiler warning
             AKLOGI("%s %i", s, frequencies[j]);
         }
     }