diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index a8407254f53221e4cca689047b03f5cfb15106d4..4a8407cb57d2444e937b74e4c69ff3d715d38572 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -138,6 +138,7 @@ final class GesturePreviewTrail {
     }
 
     private final RoundedLine mRoundedLine = new RoundedLine();
+    private final Rect mRoundedLineBounds = new Rect();
 
     /**
      * Draw gesture preview trail
@@ -149,6 +150,8 @@ final class GesturePreviewTrail {
      */
     public boolean drawGestureTrail(final Canvas canvas, final Paint paint,
             final Rect outBoundsRect, final Params params) {
+        // Initialize bounds rectangle.
+        outBoundsRect.setEmpty();
         final int trailSize = mEventTimes.getLength();
         if (trailSize == 0) {
             return false;
@@ -171,39 +174,32 @@ final class GesturePreviewTrail {
         if (startIndex < trailSize) {
             paint.setColor(params.mTrailColor);
             paint.setStyle(Paint.Style.FILL);
-            final RoundedLine line = mRoundedLine;
+            final RoundedLine roundedLine = mRoundedLine;
             int p1x = getXCoordValue(xCoords[startIndex]);
             int p1y = yCoords[startIndex];
             final int lastTime = sinceDown - eventTimes[startIndex];
-            float maxWidth = getWidth(lastTime, params);
-            float r1 = maxWidth / 2.0f;
-            // Initialize bounds rectangle.
-            outBoundsRect.set(p1x, p1y, p1x, p1y);
+            float r1 = getWidth(lastTime, params) / 2.0f;
             for (int i = startIndex + 1; i < trailSize; i++) {
                 final int elapsedTime = sinceDown - eventTimes[i];
                 final int p2x = getXCoordValue(xCoords[i]);
                 final int p2y = yCoords[i];
-                final float width = getWidth(elapsedTime, params);
-                final float r2 = width / 2.0f;
+                final float r2 = getWidth(elapsedTime, params) / 2.0f;
                 // Draw trail line only when the current point isn't a down point.
                 if (!isDownEventXCoord(xCoords[i])) {
-                    final Path path = line.makePath(p1x, p1y, r1, p2x, p2y, r2);
+                    final Path path = roundedLine.makePath(p1x, p1y, r1, p2x, p2y, r2);
                     if (path != null) {
                         final int alpha = getAlpha(elapsedTime, params);
                         paint.setAlpha(alpha);
                         canvas.drawPath(path, paint);
                         // Take union for the bounds.
-                        outBoundsRect.union(p2x, p2y);
-                        maxWidth = Math.max(maxWidth, width);
+                        roundedLine.getBounds(mRoundedLineBounds);
+                        outBoundsRect.union(mRoundedLineBounds);
                     }
                 }
                 p1x = p2x;
                 p1y = p2y;
                 r1 = r2;
             }
-            // Take care of trail line width.
-            final int inset = -((int)maxWidth + 1);
-            outBoundsRect.inset(inset, inset);
         }
 
         final int newSize = trailSize - startIndex;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
index bfb7b1fe0ffce35cf72125a7b0fd18507a42f0c9..7c87467bb3e41a1e160afafbb1e67df37c0bef6f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java
@@ -52,7 +52,8 @@ public final class PreviewPlacerView extends RelativeLayout {
     private int mOffscreenOffsetY;
     private Bitmap mOffscreenBuffer;
     private final Canvas mOffscreenCanvas = new Canvas();
-    private final Rect mOffscreenDirtyRect = new Rect();
+    private final Rect mOffscreenSrcRect = new Rect();
+    private final Rect mDirtyRect = new Rect();
     private final Rect mGesturePreviewTrailBoundsRect = new Rect(); // per trail
     private final GestureFloatingPreviewText mGestureFloatingPreviewText;
     private boolean mShowSlidingKeyInputPreview;
@@ -193,6 +194,7 @@ public final class PreviewPlacerView extends RelativeLayout {
         mOffscreenBuffer = Bitmap.createBitmap(
                 mOffscreenWidth, mOffscreenHeight, Bitmap.Config.ARGB_8888);
         mOffscreenCanvas.setBitmap(mOffscreenBuffer);
+        mOffscreenCanvas.translate(0, mOffscreenOffsetY);
     }
 
     @Override
@@ -205,19 +207,18 @@ public final class PreviewPlacerView extends RelativeLayout {
             mayAllocateOffscreenBuffer();
             // Draw gesture trails to offscreen buffer.
             final boolean needsUpdatingGesturePreviewTrail = drawGestureTrails(
-                    mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect);
+                    mOffscreenCanvas, mGesturePaint, mDirtyRect);
+            if (needsUpdatingGesturePreviewTrail) {
+                mDrawingHandler.postUpdateGestureTrailPreview();
+            }
             // Transfer offscreen buffer to screen.
-            if (!mOffscreenDirtyRect.isEmpty()) {
-                canvas.translate(0, - mOffscreenOffsetY);
-                canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
-                        mGesturePaint);
-                canvas.translate(0, mOffscreenOffsetY);
+            if (!mDirtyRect.isEmpty()) {
+                mOffscreenSrcRect.set(mDirtyRect);
+                mOffscreenSrcRect.offset(0, mOffscreenOffsetY);
+                canvas.drawBitmap(mOffscreenBuffer, mOffscreenSrcRect, mDirtyRect, null);
                 // Note: Defer clearing the dirty rectangle here because we will get cleared
                 // rectangle on the canvas.
             }
-            if (needsUpdatingGesturePreviewTrail) {
-                mDrawingHandler.postUpdateGestureTrailPreview();
-            }
         }
         mGestureFloatingPreviewText.onDraw(canvas);
         if (mShowSlidingKeyInputPreview) {
@@ -235,10 +236,8 @@ public final class PreviewPlacerView extends RelativeLayout {
             offscreenCanvas.drawRect(dirtyRect, paint);
         }
         dirtyRect.setEmpty();
-
-        // Draw gesture trails to offscreen buffer.
-        offscreenCanvas.translate(0, mOffscreenOffsetY);
         boolean needsUpdatingGesturePreviewTrail = false;
+        // Draw gesture trails to offscreen buffer.
         synchronized (mGesturePreviewTrails) {
             // Trails count == fingers count that have ever been active.
             final int trailsCount = mGesturePreviewTrails.size();
@@ -251,20 +250,9 @@ public final class PreviewPlacerView extends RelativeLayout {
                 dirtyRect.union(mGesturePreviewTrailBoundsRect);
             }
         }
-        offscreenCanvas.translate(0, -mOffscreenOffsetY);
-
-        // Clip dirty rectangle with offscreen buffer width/height.
-        dirtyRect.offset(0, mOffscreenOffsetY);
-        clipRect(dirtyRect, 0, 0, mOffscreenWidth, mOffscreenHeight);
         return needsUpdatingGesturePreviewTrail;
     }
 
-    private static void clipRect(final Rect out, final int left, final int top, final int right,
-            final int bottom) {
-        out.set(Math.max(out.left, left), Math.max(out.top, top), Math.min(out.right, right),
-                Math.min(out.bottom, bottom));
-    }
-
     public void setGestureFloatingPreviewText(final SuggestedWords suggestedWords) {
         if (!mGestureFloatingPreviewText.isPreviewEnabled()) return;
         mGestureFloatingPreviewText.setSuggetedWords(suggestedWords);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/RoundedLine.java b/java/src/com/android/inputmethod/keyboard/internal/RoundedLine.java
index 1f5252077b7c53ba6fc9471c48a55ed1d9e14faa..cd6efc4b72db5c3650a8b49042cf1c35cf6fd3c4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/RoundedLine.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/RoundedLine.java
@@ -15,6 +15,7 @@
 package com.android.inputmethod.keyboard.internal;
 
 import android.graphics.Path;
+import android.graphics.Rect;
 import android.graphics.RectF;
 
 public final class RoundedLine {
@@ -100,4 +101,10 @@ public final class RoundedLine {
         mPath.close();
         return mPath;
     }
+
+    public void getBounds(final Rect outBounds) {
+        // Reuse mArc1 as working variable
+        mPath.computeBounds(mArc1, true /* unused */);
+        mArc1.roundOut(outBounds);
+    }
 }