diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 43d28be5d3c5691c8e2cc3892e3123ef4444b580..e4e75c34298c78b0874a1cad0f01f7d18ad008a7 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -26,10 +26,8 @@ import android.graphics.Paint.Align;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.SparseArray;
 import android.view.View;
 
 import com.android.inputmethod.keyboard.internal.KeyDrawParams;
@@ -73,15 +71,15 @@ import java.util.HashSet;
  */
 public class KeyboardView extends View {
     // XML attributes
-    protected final KeyVisualAttributes mKeyVisualAttributes;
+    private final KeyVisualAttributes mKeyVisualAttributes;
     private final int mKeyLabelHorizontalPadding;
     private final float mKeyHintLetterPadding;
     private final float mKeyPopupHintLetterPadding;
     private final float mKeyShiftedLetterHintPadding;
     private final float mKeyTextShadowRadius;
-    protected final float mVerticalCorrection;
-    protected final Drawable mKeyBackground;
-    protected final Rect mKeyBackgroundPadding = new Rect();
+    private final float mVerticalCorrection;
+    private final Drawable mKeyBackground;
+    private final Rect mKeyBackgroundPadding = new Rect();
 
     // HORIZONTAL ELLIPSIS "...", character for popup hint.
     private static final String POPUP_HINT_CHAR = "\u2026";
@@ -113,10 +111,6 @@ public class KeyboardView extends View {
     private final Canvas mOffscreenCanvas = new Canvas();
     private final Paint mPaint = new Paint();
     private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
-    // This sparse array caches key label text height in pixel indexed by key label text size.
-    private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray();
-    // This sparse array caches key label text width in pixel indexed by key label text size.
-    private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray();
     private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
     private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
 
@@ -134,15 +128,15 @@ public class KeyboardView extends View {
         mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset(
                 R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
         mKeyHintLetterPadding = keyboardViewAttr.getDimension(
-                R.styleable.KeyboardView_keyHintLetterPadding, 0);
+                R.styleable.KeyboardView_keyHintLetterPadding, 0.0f);
         mKeyPopupHintLetterPadding = keyboardViewAttr.getDimension(
-                R.styleable.KeyboardView_keyPopupHintLetterPadding, 0);
+                R.styleable.KeyboardView_keyPopupHintLetterPadding, 0.0f);
         mKeyShiftedLetterHintPadding = keyboardViewAttr.getDimension(
-                R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0);
+                R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0.0f);
         mKeyTextShadowRadius = keyboardViewAttr.getFloat(
                 R.styleable.KeyboardView_keyTextShadowRadius, 0.0f);
         mVerticalCorrection = keyboardViewAttr.getDimension(
-                R.styleable.KeyboardView_verticalCorrection, 0);
+                R.styleable.KeyboardView_verticalCorrection, 0.0f);
         keyboardViewAttr.recycle();
 
         final TypedArray keyAttr = context.obtainStyledAttributes(attrs,
@@ -185,6 +179,14 @@ public class KeyboardView extends View {
         return mKeyboard;
     }
 
+    protected float getVerticalCorrection() {
+        return mVerticalCorrection;
+    }
+
+    protected void updateKeyDrawParams(final int keyHeight) {
+        mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
+    }
+
     @Override
     protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
         if (mKeyboard != null) {
@@ -213,7 +215,7 @@ public class KeyboardView extends View {
             }
             onDrawKeyboard(mOffscreenCanvas);
         }
-        canvas.drawBitmap(mOffscreenBuffer, 0, 0, null);
+        canvas.drawBitmap(mOffscreenBuffer, 0.0f, 0.0f, null);
     }
 
     private boolean maybeAllocateOffscreenBuffer() {
@@ -333,7 +335,7 @@ public class KeyboardView extends View {
         canvas.translate(bgX, bgY);
         background.draw(canvas);
         if (LatinImeLogger.sVISUALDEBUG) {
-            drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint());
+            drawRectangle(canvas, 0.0f, 0.0f, bgWidth, bgHeight, 0x80c00000, new Paint());
         }
         canvas.translate(-bgX, -bgY);
     }
@@ -347,7 +349,7 @@ public class KeyboardView extends View {
         final float centerY = keyHeight * 0.5f;
 
         if (LatinImeLogger.sVISUALDEBUG) {
-            drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint());
+            drawRectangle(canvas, 0.0f, 0.0f, keyWidth, keyHeight, 0x800000c0, new Paint());
         }
 
         // Draw key label.
@@ -357,14 +359,16 @@ public class KeyboardView extends View {
             final String label = key.mLabel;
             paint.setTypeface(key.selectTypeface(params));
             paint.setTextSize(key.selectTextSize(params));
-            final float labelCharHeight = getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint);
-            final float labelCharWidth = getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint);
+            final float labelCharHeight = TypefaceUtils.getCharHeight(
+                    KEY_LABEL_REFERENCE_CHAR, paint);
+            final float labelCharWidth = TypefaceUtils.getCharWidth(
+                    KEY_LABEL_REFERENCE_CHAR, paint);
 
             // Vertical label text alignment.
-            final float baseline = centerY + labelCharHeight / 2;
+            final float baseline = centerY + labelCharHeight / 2.0f;
 
             // Horizontal label text alignment
-            float labelWidth = 0;
+            float labelWidth = 0.0f;
             if (key.isAlignLeft()) {
                 positionX = mKeyLabelHorizontalPadding;
                 paint.setTextAlign(Align.LEFT);
@@ -373,31 +377,31 @@ public class KeyboardView extends View {
                 paint.setTextAlign(Align.RIGHT);
             } else if (key.isAlignLeftOfCenter()) {
                 // TODO: Parameterise this?
-                positionX = centerX - labelCharWidth * 7 / 4;
+                positionX = centerX - labelCharWidth * 7.0f / 4.0f;
                 paint.setTextAlign(Align.LEFT);
             } else if (key.hasLabelWithIconLeft() && icon != null) {
-                labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
+                labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth()
                         + LABEL_ICON_MARGIN * keyWidth;
-                positionX = centerX + labelWidth / 2;
+                positionX = centerX + labelWidth / 2.0f;
                 paint.setTextAlign(Align.RIGHT);
             } else if (key.hasLabelWithIconRight() && icon != null) {
-                labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
+                labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth()
                         + LABEL_ICON_MARGIN * keyWidth;
-                positionX = centerX - labelWidth / 2;
+                positionX = centerX - labelWidth / 2.0f;
                 paint.setTextAlign(Align.LEFT);
             } else {
                 positionX = centerX;
                 paint.setTextAlign(Align.CENTER);
             }
             if (key.needsXScale()) {
-                paint.setTextScaleX(
-                        Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
+                paint.setTextScaleX(Math.min(1.0f,
+                        (keyWidth * MAX_LABEL_RATIO) / TypefaceUtils.getLabelWidth(label, paint)));
             }
 
             paint.setColor(key.selectTextColor(params));
             if (key.isEnabled()) {
                 // Set a drop shadow for the text
-                paint.setShadowLayer(mKeyTextShadowRadius, 0, 0, params.mTextShadowColor);
+                paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor);
             } else {
                 // Make label invisible
                 paint.setColor(Color.TRANSPARENT);
@@ -405,7 +409,7 @@ public class KeyboardView extends View {
             blendAlpha(paint, params.mAnimAlpha);
             canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
             // Turn off drop shadow and reset x-scale.
-            paint.setShadowLayer(0, 0, 0, 0);
+            paint.setShadowLayer(0.0f, 0.0f, 0.0f, Color.TRANSPARENT);
             paint.setTextScaleX(1.0f);
 
             if (icon != null) {
@@ -413,10 +417,10 @@ public class KeyboardView extends View {
                 final int iconHeight = icon.getIntrinsicHeight();
                 final int iconY = (keyHeight - iconHeight) / 2;
                 if (key.hasLabelWithIconLeft()) {
-                    final int iconX = (int)(centerX - labelWidth / 2);
+                    final int iconX = (int)(centerX - labelWidth / 2.0f);
                     drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
                 } else if (key.hasLabelWithIconRight()) {
-                    final int iconX = (int)(centerX + labelWidth / 2 - iconWidth);
+                    final int iconX = (int)(centerX + labelWidth / 2.0f - iconWidth);
                     drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
                 }
             }
@@ -439,20 +443,23 @@ public class KeyboardView extends View {
                 // The hint label is placed just right of the key label. Used mainly on
                 // "phone number" layout.
                 // TODO: Generalize the following calculations.
-                hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2;
-                hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+                hintX = positionX
+                        + TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2.0f;
+                hintY = centerY
+                        + TypefaceUtils.getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
                 paint.setTextAlign(Align.LEFT);
             } else if (key.hasShiftedLetterHint()) {
                 // The hint label is placed at top-right corner of the key. Used mainly on tablet.
                 hintX = keyWidth - mKeyShiftedLetterHintPadding
-                        - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+                        - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
                 paint.getFontMetrics(mFontMetrics);
                 hintY = -mFontMetrics.top;
                 paint.setTextAlign(Align.CENTER);
             } else { // key.hasHintLetter()
                 // The hint letter is placed at top-right corner of the key. Used mainly on phone.
                 hintX = keyWidth - mKeyHintLetterPadding
-                        - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2;
+                        - TypefaceUtils.getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint)
+                        / 2.0f;
                 hintY = -paint.ascent();
                 paint.setTextAlign(Align.CENTER);
             }
@@ -506,7 +513,7 @@ public class KeyboardView extends View {
         paint.setColor(params.mHintLabelColor);
         paint.setTextAlign(Align.CENTER);
         final float hintX = keyWidth - mKeyHintLetterPadding
-                - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
+                - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
         final float hintY = keyHeight - mKeyPopupHintLetterPadding;
         canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
 
@@ -517,54 +524,6 @@ public class KeyboardView extends View {
         }
     }
 
-    private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) {
-        final int labelSize = (int)paint.getTextSize();
-        final Typeface face = paint.getTypeface();
-        final int codePointOffset = referenceChar << 15;
-        if (face == Typeface.DEFAULT) {
-            return codePointOffset + labelSize;
-        } else if (face == Typeface.DEFAULT_BOLD) {
-            return codePointOffset + labelSize + 0x1000;
-        } else if (face == Typeface.MONOSPACE) {
-            return codePointOffset + labelSize + 0x2000;
-        } else {
-            return codePointOffset + labelSize;
-        }
-    }
-
-    // Working variable for the following methods.
-    private final Rect mTextBounds = new Rect();
-
-    private float getCharHeight(final char[] referenceChar, final Paint paint) {
-        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
-        final Float cachedValue = sTextHeightCache.get(key);
-        if (cachedValue != null)
-            return cachedValue;
-
-        paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
-        final float height = mTextBounds.height();
-        sTextHeightCache.put(key, height);
-        return height;
-    }
-
-    private float getCharWidth(final char[] referenceChar, final Paint paint) {
-        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
-        final Float cachedValue = sTextWidthCache.get(key);
-        if (cachedValue != null)
-            return cachedValue;
-
-        paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
-        final float width = mTextBounds.width();
-        sTextWidthCache.put(key, width);
-        return width;
-    }
-
-    // TODO: Remove this method.
-    public float getLabelWidth(final String label, final Paint paint) {
-        paint.getTextBounds(label, 0, label.length(), mTextBounds);
-        return mTextBounds.width();
-    }
-
     protected static void drawIcon(final Canvas canvas, final Drawable icon, final int x,
             final int y, final int width, final int height) {
         canvas.translate(x, y);
@@ -578,7 +537,7 @@ public class KeyboardView extends View {
         paint.setStyle(Paint.Style.STROKE);
         paint.setStrokeWidth(1.0f);
         paint.setColor(color);
-        canvas.drawLine(0, y, w, y, paint);
+        canvas.drawLine(0.0f, y, w, y, paint);
     }
 
     private static void drawVerticalLine(final Canvas canvas, final float x, final float h,
@@ -586,7 +545,7 @@ public class KeyboardView extends View {
         paint.setStyle(Paint.Style.STROKE);
         paint.setStrokeWidth(1.0f);
         paint.setColor(color);
-        canvas.drawLine(x, 0, x, h, paint);
+        canvas.drawLine(x, 0.0f, x, h, paint);
     }
 
     private static void drawRectangle(final Canvas canvas, final float x, final float y,
@@ -595,15 +554,20 @@ public class KeyboardView extends View {
         paint.setStrokeWidth(1.0f);
         paint.setColor(color);
         canvas.translate(x, y);
-        canvas.drawRect(0, 0, w, h, paint);
+        canvas.drawRect(0.0f, 0.0f, w, h, paint);
         canvas.translate(-x, -y);
     }
 
-    public Paint newDefaultLabelPaint() {
+    public Paint newLabelPaint(final Key key) {
         final Paint paint = new Paint();
         paint.setAntiAlias(true);
-        paint.setTypeface(mKeyDrawParams.mTypeface);
-        paint.setTextSize(mKeyDrawParams.mLabelSize);
+        if (key == null) {
+            paint.setTypeface(mKeyDrawParams.mTypeface);
+            paint.setTextSize(mKeyDrawParams.mLabelSize);
+        } else {
+            paint.setTypeface(key.selectTypeface(mKeyDrawParams));
+            paint.setTextSize(key.selectTextSize(mKeyDrawParams));
+        }
         return paint;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 7dfbea353807b4d932f4d6c96153ebc857d4d3f9..ba78d014abde67c797f3fb1b7131a0e3263d9990 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -530,9 +530,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
                 R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0);
 
         final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension(
-                R.styleable.MainKeyboardView_keyHysteresisDistance, 0);
+                R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f);
         final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension(
-                R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0);
+                R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f);
         mKeyDetector = new KeyDetector(
                 keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier);
         mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr);
@@ -655,7 +655,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         mKeyTimerHandler.cancelLongPressTimer();
         super.setKeyboard(keyboard);
         mKeyDetector.setKeyboard(
-                keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
+                keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection());
         PointerTracker.setKeyDetector(mKeyDetector);
         mTouchScreenRegulator.setKeyboardGeometry(keyboard.mOccupiedWidth);
         mMoreKeysKeyboardCache.clear();
@@ -1329,7 +1329,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
 
         // Overlay a dark rectangle to dim.
         if (mNeedsToDimEntireKeyboard) {
-            canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundDimAlphaPaint);
+            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mBackgroundDimAlphaPaint);
         }
     }
 
@@ -1353,9 +1353,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         }
     }
 
-    private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) {
+    private static boolean fitsTextIntoWidth(final int width, final String text,
+            final Paint paint) {
         paint.setTextScaleX(1.0f);
-        final float textWidth = getLabelWidth(text, paint);
+        final float textWidth = TypefaceUtils.getLabelWidth(text, paint);
         if (textWidth < width) {
             return true;
         }
@@ -1366,12 +1367,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         }
 
         paint.setTextScaleX(scaleX);
-        return getLabelWidth(text, paint) < width;
+        return TypefaceUtils.getLabelWidth(text, paint) < width;
     }
 
     // Layout language name on spacebar.
-    private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype,
-            final int width) {
+    private static String layoutLanguageOnSpacebar(final Paint paint,
+            final InputMethodSubtype subtype, final int width) {
         // Choose appropriate language name to fit into the width.
         final String fullText = getFullDisplayName(subtype);
         if (fitsTextIntoWidth(width, fullText, paint)) {
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index 66c30149c3ed01c095343a470fc2f0fd8e5923ed..c2a9bfe3cba5cdf056cc0f08868421f6b9078735 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.keyboard;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 
@@ -257,7 +258,6 @@ public final class MoreKeysKeyboard extends Keyboard {
         private static final float LABEL_PADDING_RATIO = 0.2f;
         private static final float DIVIDER_RATIO = 0.2f;
 
-
         /**
          * The builder of MoreKeysKeyboard.
          * @param context the context of {@link MoreKeysKeyboardView}.
@@ -289,10 +289,10 @@ public final class MoreKeysKeyboard extends Keyboard {
                 // be considered because the vertical positions of both backgrounds were already
                 // adjusted with their bottom paddings deducted.
                 width = keyPreviewDrawParams.mPreviewVisibleWidth;
-                height = keyPreviewDrawParams.mPreviewVisibleHeight
-                        + mParams.mVerticalGap;
+                height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap;
             } else {
-                width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth);
+                width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth,
+                        context.getResources());
                 height = parentKeyboard.mMostCommonKeyHeight;
             }
             final int dividerWidth;
@@ -310,22 +310,18 @@ public final class MoreKeysKeyboard extends Keyboard {
         }
 
         private static int getMaxKeyWidth(final KeyboardView view, final Key parentKey,
-                final int minKeyWidth) {
-            final int padding = (int)(view.getResources()
-                    .getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding)
-                    + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0));
-            final Paint paint = view.newDefaultLabelPaint();
-            paint.setTypeface(parentKey.selectTypeface(view.mKeyDrawParams));
-            paint.setTextSize(parentKey.selectMoreKeyTextSize(view.mKeyDrawParams));
+                final int minKeyWidth, final Resources res) {
+            final float padding =
+                    res.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding)
+                    + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0.0f);
+            final Paint paint = view.newLabelPaint(parentKey);
             int maxWidth = minKeyWidth;
             for (final MoreKeySpec spec : parentKey.mMoreKeys) {
                 final String label = spec.mLabel;
                 // If the label is single letter, minKeyWidth is enough to hold the label.
                 if (label != null && StringUtils.codePointCount(label) > 1) {
-                    final int width = (int)view.getLabelWidth(label, paint) + padding;
-                    if (maxWidth < width) {
-                        maxWidth = width;
-                    }
+                    maxWidth = Math.max(maxWidth,
+                            (int)(TypefaceUtils.getLabelWidth(label, paint) + padding));
                 }
             }
             return maxWidth;
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
index 0d42ab2fe4a36748add68251c5d6cc6499fcc85a..a356eb1191fde8967ebe20425b19ffc46c2fb840 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -71,7 +71,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
     public void setKeyboard(final Keyboard keyboard) {
         super.setKeyboard(keyboard);
         mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
-                -getPaddingTop() + mVerticalCorrection);
+                -getPaddingTop() + getVerticalCorrection());
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java b/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a54e119ceb12f3a43d6a46bffd258434a5c68ea
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 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;
+
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.util.SparseArray;
+
+import com.android.inputmethod.latin.CollectionUtils;
+
+public final class TypefaceUtils {
+    private TypefaceUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    // This sparse array caches key label text height in pixel indexed by key label text size.
+    private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray();
+    // Working variable for the following method.
+    private static final Rect sTextHeightBounds = new Rect();
+
+    public static float getCharHeight(final char[] referenceChar, final Paint paint) {
+        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
+        synchronized (sTextHeightCache) {
+            final Float cachedValue = sTextHeightCache.get(key);
+            if (cachedValue != null) {
+                return cachedValue;
+            }
+
+            paint.getTextBounds(referenceChar, 0, 1, sTextHeightBounds);
+            final float height = sTextHeightBounds.height();
+            sTextHeightCache.put(key, height);
+            return height;
+        }
+    }
+
+    // This sparse array caches key label text width in pixel indexed by key label text size.
+    private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray();
+    // Working variable for the following method.
+    private static final Rect sTextWidthBounds = new Rect();
+
+    public static float getCharWidth(final char[] referenceChar, final Paint paint) {
+        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
+        synchronized (sTextWidthCache) {
+            final Float cachedValue = sTextWidthCache.get(key);
+            if (cachedValue != null) {
+                return cachedValue;
+            }
+
+            paint.getTextBounds(referenceChar, 0, 1, sTextWidthBounds);
+            final float width = sTextWidthBounds.width();
+            sTextWidthCache.put(key, width);
+            return width;
+        }
+    }
+
+    private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) {
+        final int labelSize = (int)paint.getTextSize();
+        final Typeface face = paint.getTypeface();
+        final int codePointOffset = referenceChar << 15;
+        if (face == Typeface.DEFAULT) {
+            return codePointOffset + labelSize;
+        } else if (face == Typeface.DEFAULT_BOLD) {
+            return codePointOffset + labelSize + 0x1000;
+        } else if (face == Typeface.MONOSPACE) {
+            return codePointOffset + labelSize + 0x2000;
+        } else {
+            return codePointOffset + labelSize;
+        }
+    }
+
+    public static float getLabelWidth(final String label, final Paint paint) {
+        final Rect textBounds = new Rect();
+        paint.getTextBounds(label, 0, label.length(), textBounds);
+        return textBounds.width();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index ed408bb3c66eb48e28bc8a23589ef285677b14a8..3037669c031ec6ed7e0d9616e2231f69fa7abc05 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -16,12 +16,14 @@
 
 package com.android.inputmethod.latin.suggestions;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.TypefaceUtils;
 import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
@@ -50,16 +52,12 @@ public final class MoreSuggestions extends Keyboard {
             super();
         }
 
-        // TODO: Remove {@link MoreSuggestionsView} argument.
         public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth,
-                final int minWidth, final int maxRow, final MoreSuggestionsView view) {
+                final int minWidth, final int maxRow, final Paint paint, final Resources res) {
             clearKeys();
-            final Resources res = view.getResources();
             mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
             mDividerWidth = mDivider.getIntrinsicWidth();
-            final int padding = (int) res.getDimension(
-                    R.dimen.more_suggestions_key_horizontal_padding);
-            final Paint paint = view.newDefaultLabelPaint();
+            final float padding = res.getDimension(R.dimen.more_suggestions_key_horizontal_padding);
 
             int row = 0;
             int pos = fromPos, rowStartPos = fromPos;
@@ -67,7 +65,7 @@ public final class MoreSuggestions extends Keyboard {
             while (pos < size) {
                 final String word = suggestions.getWord(pos);
                 // TODO: Should take care of text x-scaling.
-                mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding;
+                mWidths[pos] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding);
                 final int numColumn = pos - rowStartPos + 1;
                 final int columnWidth =
                         (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
@@ -169,8 +167,8 @@ public final class MoreSuggestions extends Keyboard {
         private int mFromPos;
         private int mToPos;
 
-        public Builder(final MoreSuggestionsView paneView) {
-            super(paneView.getContext(), new MoreSuggestionsParam());
+        public Builder(final Context context, final MoreSuggestionsView paneView) {
+            super(context, new MoreSuggestionsParam());
             mPaneView = paneView;
         }
 
@@ -183,7 +181,7 @@ public final class MoreSuggestions extends Keyboard {
 
             mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
             final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
-                    mPaneView);
+                    mPaneView.newLabelPaint(null /* key */), mResources);
             mFromPos = fromPos;
             mToPos = fromPos + count;
             mSuggestions = suggestions;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 438820d172bb14117a37c0466bb1077292de20e4..94715cd84d58708bde6f14e45300ee490da89d07 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -43,7 +43,7 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView {
     }
 
     public void updateKeyboardGeometry(final int keyHeight) {
-        mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
+        updateKeyDrawParams(keyHeight);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index eeaf828a7b9edcdb41fadb010f337ae9c7b2522e..4ef36fa466b53e038aa4af54212fa46bf05a5efc 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -596,7 +596,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
         mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
         mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
                 .findViewById(R.id.more_suggestions_view);
-        mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView);
+        mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView);
 
         final Resources res = context.getResources();
         mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(