Merge "Kill the StringBuilderPool."
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index d4a50b6..9abbc2f 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -139,7 +139,7 @@
             <enum name="alwaysDisplay" value="-1" />
         </attr>
         <attr name="delayBeforeFadeoutLangageOnSpacebar" format="integer" />
-        <attr name="finalFadeoutFactorOfLanguageOnSpacebar" format="float" />
+        <attr name="finalAlphaOfLanguageOnSpacebar" format="integer" />
         <!-- Key detection hysteresis distance. -->
         <attr name="keyHysteresisDistance" format="dimension" />
         <!-- Touch noise threshold time in millisecond -->
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index eb2f9bb..818b1c4 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -80,7 +80,7 @@
         <item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item>
         <item name="durationOfFadeoutLanguageOnSpacebar">200</item>
         <item name="delayBeforeFadeoutLangageOnSpacebar">1200</item>
-        <item name="finalFadeoutFactorOfLanguageOnSpacebar">0.5</item>
+        <item name="finalAlphaOfLanguageOnSpacebar">128</item>
     </style>
     <style
         name="LatinKeyboardView"
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 9168d07..f4e766c 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -21,7 +21,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.Align;
 import android.graphics.Typeface;
@@ -77,13 +76,14 @@
     private Drawable mSpaceIcon;
     // Stuff to draw language name on spacebar.
     private ValueAnimator mLanguageOnSpacebarAnimator;
-    private float mFinalFadeoutFactorOfLanguageOnSpacebar;
+    private int mFinalAlphaOfLanguageOnSpacebar;
     private int mDurationOfFadeoutLanguageOnSpacebar;
+    private static final int ALPHA_OPAQUE = 255;
     private static final int LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY = 0;
     private static final int LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY = -1;
     private boolean mNeedsToDisplayLanguage;
     private Locale mSpacebarLocale;
-    private float mSpacebarTextFadeFactor = 0.0f;
+    private int mSpacebarTextAlpha;
     private final float mSpacebarTextRatio;
     private float mSpacebarTextSize;
     private final int mSpacebarTextColor;
@@ -344,8 +344,8 @@
                 LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY);
         final int delayBeforeFadeoutLanguageOnSpacebar = a.getInt(
                 R.styleable.LatinKeyboardView_delayBeforeFadeoutLangageOnSpacebar, 0);
-        mFinalFadeoutFactorOfLanguageOnSpacebar = a.getFloat(
-                R.styleable.LatinKeyboardView_finalFadeoutFactorOfLanguageOnSpacebar, 0.0f);
+        mFinalAlphaOfLanguageOnSpacebar = a.getInt(
+                R.styleable.LatinKeyboardView_finalAlphaOfLanguageOnSpacebar, 0);
 
         final KeyTimerParams keyTimerParams = new KeyTimerParams(a);
         mPointerTrackerParams = new PointerTrackerParams(a);
@@ -361,8 +361,8 @@
 
         PointerTracker.setParameters(mPointerTrackerParams);
 
-        mLanguageOnSpacebarAnimator = ValueAnimator.ofFloat(
-                1.0f, mFinalFadeoutFactorOfLanguageOnSpacebar);
+        mLanguageOnSpacebarAnimator = ValueAnimator.ofInt(
+                ALPHA_OPAQUE, mFinalAlphaOfLanguageOnSpacebar);
         mLanguageOnSpacebarAnimator.setStartDelay(delayBeforeFadeoutLanguageOnSpacebar);
         if (mDurationOfFadeoutLanguageOnSpacebar > 0) {
             mLanguageOnSpacebarAnimator.setDuration(mDurationOfFadeoutLanguageOnSpacebar);
@@ -370,7 +370,7 @@
         mLanguageOnSpacebarAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                mSpacebarTextFadeFactor = (Float)animation.getAnimatedValue();
+                mSpacebarTextAlpha = (Integer)animation.getAnimatedValue();
                 invalidateKey(mSpaceKey);
             }
         });
@@ -794,15 +794,15 @@
         mLanguageOnSpacebarAnimator.cancel();
         mNeedsToDisplayLanguage = needsToDisplayLanguage;
         if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY) {
-            mSpacebarTextFadeFactor = 0.0f;
+            mNeedsToDisplayLanguage = false;
         } else if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY) {
-            mSpacebarTextFadeFactor = 1.0f;
+            mSpacebarTextAlpha = ALPHA_OPAQUE;
         } else {
             if (subtypeChanged && needsToDisplayLanguage) {
-                mSpacebarTextFadeFactor = 1.0f;
+                mSpacebarTextAlpha = ALPHA_OPAQUE;
                 mLanguageOnSpacebarAnimator.start();
             } else {
-                mSpacebarTextFadeFactor = mFinalFadeoutFactorOfLanguageOnSpacebar;
+                mSpacebarTextAlpha = mFinalAlphaOfLanguageOnSpacebar;
             }
         }
         invalidateKey(mSpaceKey);
@@ -835,12 +835,6 @@
         }
     }
 
-    private static int getSpacebarTextColor(int color, float fadeFactor) {
-        final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor),
-                Color.red(color), Color.green(color), Color.blue(color));
-        return newColor;
-    }
-
     // Compute width of text with specified text size using paint.
     private int getTextWidth(Paint paint, String text, float textSize) {
         paint.setTextSize(textSize);
@@ -888,7 +882,7 @@
         final int width = key.mWidth;
         final int height = key.mHeight;
 
-        // If application locales are explicitly selected.
+        // If input subtypes are explicitly selected.
         if (mNeedsToDisplayLanguage) {
             final String language = layoutLanguageOnSpacebar(paint, mSpacebarLocale, width,
                     mSpacebarTextSize);
@@ -898,9 +892,11 @@
             final float descent = paint.descent();
             final float textHeight = -paint.ascent() + descent;
             final float baseline = height / 2 + textHeight / 2;
-            paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor));
+            paint.setColor(mSpacebarTextShadowColor);
+            paint.setAlpha(mSpacebarTextAlpha);
             canvas.drawText(language, width / 2, baseline - descent - 1, paint);
-            paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor));
+            paint.setColor(mSpacebarTextColor);
+            paint.setAlpha(mSpacebarTextAlpha);
             canvas.drawText(language, width / 2, baseline - descent, paint);
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 1480bba..13d18e5 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -76,7 +76,7 @@
     public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) {
         final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo();
         spellCheckerProximityInfo.mNativeProximityInfo =
-                spellCheckerProximityInfo.setProximityInfoNative(
+                spellCheckerProximityInfo.setProximityInfoNative("",
                         SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, (480 / 10), proximity,
                         0, null, null, null, null, null, null, null, null);
         return spellCheckerProximityInfo;
@@ -87,7 +87,8 @@
         JniUtils.loadNativeLibrary();
     }
 
-    private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
+    private native long setProximityInfoNative(
+            String locale, int maxProximityCharsSize, int displayWidth,
             int displayHeight, int gridWidth, int gridHeight,
             int mostCommonKeyWidth, int[] proximityCharsArray,
             int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
@@ -154,7 +155,7 @@
             calculateSweetSpotParams = false;
         }
 
-        mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
+        mNativeProximityInfo = setProximityInfoNative("", MAX_PROXIMITY_CHARS_SIZE,
                 keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth,
                 proximityCharsArray,
                 keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes,
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 7e5953b..ffaede3 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -30,6 +30,7 @@
     jni_common.cpp
 
 LATIN_IME_CORE_SRC_FILES := \
+    additional_proximity_chars.cpp \
     basechars.cpp \
     bigram_dictionary.cpp \
     char_utils.cpp \
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index 844b230..a9b6cca 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -25,16 +25,19 @@
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
+#include <string>
 
 namespace latinime {
 
 static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object,
-        jint maxProximityCharsSize, jint displayWidth, jint displayHeight, jint gridWidth,
-        jint gridHeight, jint mostCommonkeyWidth, jintArray proximityCharsArray, jint keyCount,
-        jintArray keyXCoordinateArray, jintArray keyYCoordinateArray, jintArray keyWidthArray,
-        jintArray keyHeightArray, jintArray keyCharCodeArray,
+        jstring localejStr, jint maxProximityCharsSize, jint displayWidth, jint displayHeight,
+        jint gridWidth, jint gridHeight, jint mostCommonkeyWidth, jintArray proximityCharsArray,
+        jint keyCount, jintArray keyXCoordinateArray, jintArray keyYCoordinateArray,
+        jintArray keyWidthArray, jintArray keyHeightArray, jintArray keyCharCodeArray,
         jfloatArray sweetSpotCenterXArray, jfloatArray sweetSpotCenterYArray,
         jfloatArray sweetSpotRadiusArray) {
+    const char *localeStrPtr = env->GetStringUTFChars(localejStr, 0);
+    const std::string localeStr(localeStrPtr);
     jint *proximityChars = env->GetIntArrayElements(proximityCharsArray, 0);
     jint *keyXCoordinates = safeGetIntArrayElements(env, keyXCoordinateArray);
     jint *keyYCoordinates = safeGetIntArrayElements(env, keyYCoordinateArray);
@@ -44,7 +47,7 @@
     jfloat *sweetSpotCenterXs = safeGetFloatArrayElements(env, sweetSpotCenterXArray);
     jfloat *sweetSpotCenterYs = safeGetFloatArrayElements(env, sweetSpotCenterYArray);
     jfloat *sweetSpotRadii = safeGetFloatArrayElements(env, sweetSpotRadiusArray);
-    ProximityInfo *proximityInfo = new ProximityInfo(maxProximityCharsSize, displayWidth,
+    ProximityInfo *proximityInfo = new ProximityInfo(localeStr, maxProximityCharsSize, displayWidth,
             displayHeight, gridWidth, gridHeight, mostCommonkeyWidth,
             (const uint32_t*)proximityChars,
             keyCount, (const int32_t*)keyXCoordinates, (const int32_t*)keyYCoordinates,
@@ -60,6 +63,7 @@
     safeReleaseIntArrayElements(env, keyYCoordinateArray, keyYCoordinates);
     safeReleaseIntArrayElements(env, keyXCoordinateArray, keyXCoordinates);
     env->ReleaseIntArrayElements(proximityCharsArray, proximityChars, 0);
+    env->ReleaseStringUTFChars(localejStr, localeStrPtr);
     return (jlong)proximityInfo;
 }
 
@@ -70,7 +74,7 @@
 }
 
 static JNINativeMethod sKeyboardMethods[] = {
-    {"setProximityInfoNative", "(IIIIII[II[I[I[I[I[I[F[F[F)J",
+    {"setProximityInfoNative", "(Ljava/lang/String;IIIIII[II[I[I[I[I[I[F[F[F)J",
             (void*)latinime_Keyboard_setProximityInfo},
     {"releaseProximityInfoNative", "(J)V", (void*)latinime_Keyboard_release}
 };
diff --git a/native/src/additional_proximity_chars.cpp b/native/src/additional_proximity_chars.cpp
new file mode 100644
index 0000000..74c96ae
--- /dev/null
+++ b/native/src/additional_proximity_chars.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "additional_proximity_chars.h"
+
+namespace latinime {
+const std::string AdditionalProximityChars::LOCALE_EN_US("en");
+
+const uint16_t AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = {
+    'e', 'i', 'o', 'u'
+};
+
+const uint16_t AdditionalProximityChars::EN_US_ADDITIONAL_E[EN_US_ADDITIONAL_E_SIZE] = {
+    'a', 'i', 'o', 'u'
+};
+
+const uint16_t AdditionalProximityChars::EN_US_ADDITIONAL_I[EN_US_ADDITIONAL_I_SIZE] = {
+    'a', 'e', 'o', 'u'
+};
+
+const uint16_t AdditionalProximityChars::EN_US_ADDITIONAL_O[EN_US_ADDITIONAL_O_SIZE] = {
+    'a', 'e', 'i', 'u'
+};
+
+const uint16_t AdditionalProximityChars::EN_US_ADDITIONAL_U[EN_US_ADDITIONAL_U_SIZE] = {
+    'a', 'e', 'i', 'o'
+};
+}
diff --git a/native/src/additional_proximity_chars.h b/native/src/additional_proximity_chars.h
new file mode 100644
index 0000000..b76726c
--- /dev/null
+++ b/native/src/additional_proximity_chars.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
+#define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
+
+#include <stdint.h>
+#include <string>
+
+namespace latinime {
+
+class AdditionalProximityChars {
+ private:
+    static const std::string LOCALE_EN_US;
+    static const int EN_US_ADDITIONAL_A_SIZE = 4;
+    static const uint16_t EN_US_ADDITIONAL_A[];
+    static const int EN_US_ADDITIONAL_E_SIZE = 4;
+    static const uint16_t EN_US_ADDITIONAL_E[];
+    static const int EN_US_ADDITIONAL_I_SIZE = 4;
+    static const uint16_t EN_US_ADDITIONAL_I[];
+    static const int EN_US_ADDITIONAL_O_SIZE = 4;
+    static const uint16_t EN_US_ADDITIONAL_O[];
+    static const int EN_US_ADDITIONAL_U_SIZE = 4;
+    static const uint16_t EN_US_ADDITIONAL_U[];
+
+    static bool isEnLocale(std::string* locale_str) {
+        return locale_str && locale_str->size() >= LOCALE_EN_US.size()
+                && locale_str->compare(0, LOCALE_EN_US.size(), LOCALE_EN_US);
+    }
+
+ public:
+    static int getAdditionalCharsSize(std::string* locale_str, uint16_t c) {
+        if (!isEnLocale(locale_str)) {
+            return 0;
+        }
+        switch(c) {
+        case 'a':
+            return EN_US_ADDITIONAL_A_SIZE;
+        case 'e':
+            return EN_US_ADDITIONAL_E_SIZE;
+        case 'i':
+            return EN_US_ADDITIONAL_I_SIZE;
+        case 'o':
+            return EN_US_ADDITIONAL_O_SIZE;
+        case 'u':
+            return EN_US_ADDITIONAL_U_SIZE;
+        default:
+            return 0;
+        }
+    }
+
+    static const uint16_t* getAdditionalChars(std::string* locale_str, uint16_t c) {
+        if (!isEnLocale(locale_str)) {
+            return 0;
+        }
+        switch(c) {
+        case 'a':
+            return EN_US_ADDITIONAL_A;
+        case 'e':
+            return EN_US_ADDITIONAL_E;
+        case 'i':
+            return EN_US_ADDITIONAL_I;
+        case 'o':
+            return EN_US_ADDITIONAL_O;
+        case 'u':
+            return EN_US_ADDITIONAL_U;
+        default:
+            return 0;
+        }
+    }
+
+    static bool hasAdditionalChars(std::string* locale_str, uint16_t c) {
+        return getAdditionalCharsSize(locale_str, c) > 0;
+    }
+};
+
+}
+
+#endif // LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index ad19f58..561fffa 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -16,10 +16,11 @@
 
 #include <assert.h>
 #include <stdio.h>
-#include <string.h>
+#include <string>
 
 #define LOG_TAG "LatinIME: proximity_info.cpp"
 
+#include "additional_proximity_chars.h"
 #include "dictionary.h"
 #include "proximity_info.h"
 
@@ -33,9 +34,9 @@
     }
 }
 
-ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
-        const int keyboardHeight, const int gridWidth, const int gridHeight,
-        const int mostCommonKeyWidth,
+ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
+        const int keyboardWidth, const int keyboardHeight, const int gridWidth,
+        const int gridHeight, const int mostCommonKeyWidth,
         const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates,
         const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights,
         const int32_t *keyCharCodes, const float *sweetSpotCenterXs, const float *sweetSpotCenterYs,
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index caabadf..bfcef63 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -18,6 +18,7 @@
 #define LATINIME_PROXIMITY_INFO_H
 
 #include <stdint.h>
+#include <string>
 
 #include "defines.h"
 
@@ -43,9 +44,9 @@
         ADDITIONAL_PROXIMITY_CHAR
     } ProximityType;
 
-    ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
-            const int keybaordHeight, const int gridWidth, const int gridHeight,
-            const int mostCommonkeyWidth,
+    ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
+            const int keyboardWidth, const int keybaordHeight, const int gridWidth,
+            const int gridHeight, const int mostCommonkeyWidth,
             const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates,
             const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights,
             const int32_t *keyCharCodes, const float *sweetSpotCenterXs,