aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk1
-rw-r--r--java/AndroidManifest.xml1
-rw-r--r--java/res/layout/vibration_settings_dialog.xml49
-rw-r--r--java/res/values/attrs.xml4
-rw-r--r--java/res/values/config.xml6
-rw-r--r--java/res/values/donottranslate.xml1
-rw-r--r--java/res/values/strings.xml2
-rw-r--r--java/res/values/themes-basic-highcontrast.xml1
-rw-r--r--java/res/values/themes-basic.xml1
-rw-r--r--java/res/values/themes-gingerbread.xml1
-rw-r--r--java/res/values/themes-ics.xml1
-rw-r--r--java/res/values/themes-stone-bold.xml1
-rw-r--r--java/res/values/themes-stone.xml1
-rw-r--r--java/res/values/touch-position-correction.xml74
-rw-r--r--java/res/xml/kbd_rows_number.xml2
-rw-r--r--java/res/xml/prefs.xml3
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java79
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java55
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java4
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Flag.java15
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java21
-rw-r--r--java/src/com/android/inputmethod/latin/MoreSuggestionsView.java18
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java69
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestionsView.java37
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java18
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java87
-rw-r--r--native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp16
-rw-r--r--native/jni/jni_common.h14
-rw-r--r--native/src/correction.cpp14
-rw-r--r--native/src/correction.h3
-rw-r--r--native/src/defines_touch_position_correction.h61
-rw-r--r--native/src/proximity_info.cpp33
-rw-r--r--native/src/proximity_info.h15
-rw-r--r--native/src/unigram_dictionary.cpp30
-rw-r--r--native/src/unigram_dictionary.h15
-rw-r--r--tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java14
38 files changed, 552 insertions, 220 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 505e41b49..c274a6c44 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,6 +50,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/LatinIME.apk)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 2baae54fb..b0525326c 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:label="@string/english_ime_name"
diff --git a/java/res/layout/vibration_settings_dialog.xml b/java/res/layout/vibration_settings_dialog.xml
new file mode 100644
index 000000000..981ba9be0
--- /dev/null
+++ b/java/res/layout/vibration_settings_dialog.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dip">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_margin="10dip">
+ <TextView android:id="@+id/vibration_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20dip"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/settings_ms"
+ android:textSize="20dip"/>
+ </LinearLayout>
+ <SeekBar
+ android:id="@+id/vibration_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:max="250"
+ android:layout_margin="10dip"/>
+</LinearLayout>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 2a7632124..34ce527f1 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -34,7 +34,9 @@
<attr name="moreSuggestionsViewStyle" format="reference" />
<attr name="suggestionBackgroundStyle" format="reference" />
<attr name="suggestionPreviewBackgroundStyle" format="reference" />
- </declare-styleable>
+ <!-- Touch position correction -->
+ <attr name="touchPositionCorrectionData" format="reference" />
+ </declare-styleable>
<declare-styleable name="KeyboardView">
<!-- Image for the key. This image needs to be a StateListDrawable, with the following
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 999247839..bcce58123 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -82,8 +82,10 @@
will be subject to auto-correction. -->
<item>0</item>
</string-array>
- <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare a word to be a typo -->
- <string name="spellchecker_typo_threshold_value" translatable="false">0.11</string>
+ <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare a word to be "likely" -->
+ <string name="spellchecker_likely_threshold_value" translatable="false">0.11</string>
+ <!-- Threshold of the normalized score of any dictionary lookup to be offered as a suggestion by the spell checker -->
+ <string name="spellchecker_suggestion_threshold_value" translatable="false">0.03</string>
<!-- Screen metrics for logging.
0 = "mdpi phone screen"
1 = "hdpi phone screen"
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 75e22ddd8..aefaec9ef 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -165,4 +165,5 @@
<!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
<string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
<string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string>
+ <string name="settings_ms">ms</string>
</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2f591fdf0..a1c1a9ffd 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -343,4 +343,6 @@
<!-- Title of an option for usability study mode -->
<string name="prefs_usability_study_mode">Usability study mode</string>
+ <!-- Title of the settings for vibration duration -->
+ <string name="prefs_vibration_duration_settings">Vibration duration settings</string>
</resources>
diff --git a/java/res/values/themes-basic-highcontrast.xml b/java/res/values/themes-basic-highcontrast.xml
index 91272356f..bc3c84706 100644
--- a/java/res/values/themes-basic-highcontrast.xml
+++ b/java/res/values/themes-basic-highcontrast.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item>
</style>
</resources>
diff --git a/java/res/values/themes-basic.xml b/java/res/values/themes-basic.xml
index 6c0e16e7b..29cb9cc7d 100644
--- a/java/res/values/themes-basic.xml
+++ b/java/res/values/themes-basic.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item>
</style>
</resources>
diff --git a/java/res/values/themes-gingerbread.xml b/java/res/values/themes-gingerbread.xml
index 43bff5082..c4a0f804a 100644
--- a/java/res/values/themes-gingerbread.xml
+++ b/java/res/values/themes-gingerbread.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_gingerbread</item>
</style>
</resources>
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 1235d4e88..dd2b6a334 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle.IceCreamSandwich</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle.IceCreamSandwich</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle.IceCreamSandwich</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_ice_cream_sandwich</item>
</style>
</resources>
diff --git a/java/res/values/themes-stone-bold.xml b/java/res/values/themes-stone-bold.xml
index 6e25f41d7..6e864bed0 100644
--- a/java/res/values/themes-stone-bold.xml
+++ b/java/res/values/themes-stone-bold.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item>
</style>
</resources>
diff --git a/java/res/values/themes-stone.xml b/java/res/values/themes-stone.xml
index 3cbda810e..64c557035 100644
--- a/java/res/values/themes-stone.xml
+++ b/java/res/values/themes-stone.xml
@@ -28,5 +28,6 @@
<item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item>
<item name="suggestionBackgroundStyle">@style/SuggestionBackgroundStyle</item>
<item name="suggestionPreviewBackgroundStyle">@style/SuggestionPreviewBackgroundStyle</item>
+ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item>
</style>
</resources>
diff --git a/java/res/values/touch-position-correction.xml b/java/res/values/touch-position-correction.xml
new file mode 100644
index 000000000..0a0e4e545
--- /dev/null
+++ b/java/res/values/touch-position-correction.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!--
+ An entry of the touch_position_correction word should be:
+ 1. (float) (touch_center_x - key_center_x) / key_width
+ 2. (float) (touch_center_y - key_center_y) / key_height
+ 3. (float) sweet_spot_radius / (key_width^2 + key_height^2)
+ -->
+
+ <string-array
+ name="touch_position_correction_data_empty"
+ translatable="false"
+ >
+ <!-- empty -->
+ </string-array>
+
+ <string-array
+ name="touch_position_correction_data_gingerbread"
+ translatable="false"
+ >
+ <!-- First row -->
+ <item>0.0091285</item>
+ <item>0.1193203</item>
+ <item>0.1622607</item>
+
+ <!-- Second row -->
+ <item>-0.0233128</item>
+ <item>0.1379798</item>
+ <item>0.1585229</item>
+
+ <!-- Third row -->
+ <item>-0.0080185</item>
+ <item>0.1911477</item>
+ <item>0.1570948</item>
+ </string-array>
+
+ <string-array
+ name="touch_position_correction_data_ice_cream_sandwich"
+ translatable="false"
+ >
+ <!-- First row -->
+ <item>0.0038756</item>
+ <item>-0.0005677</item>
+ <item>0.1577026</item>
+
+ <!-- Second row -->
+ <item>-0.0236678</item>
+ <item>0.0381731</item>
+ <item>0.1529972</item>
+
+ <!-- Third row -->
+ <item>-0.0086827</item>
+ <item>0.0880847</item>
+ <item>0.1522819</item>
+ </string-array>
+</resources> \ No newline at end of file
diff --git a/java/res/xml/kbd_rows_number.xml b/java/res/xml/kbd_rows_number.xml
index 21d0656d1..90ac5686b 100644
--- a/java/res/xml/kbd_rows_number.xml
+++ b/java/res/xml/kbd_rows_number.xml
@@ -36,6 +36,7 @@
latin:keyStyle="num2KeyStyle" />
<Key
latin:keyStyle="num3KeyStyle" />
+ <Spacer />
</Row>
<Row>
<Key
@@ -44,6 +45,7 @@
latin:keyStyle="num5KeyStyle" />
<Key
latin:keyStyle="num6KeyStyle" />
+ <Spacer />
</Row>
<Row>
<Key
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 24de95f10..312af2888 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -125,6 +125,9 @@
android:summary="@string/enable_span_insert_summary"
android:persistent="true"
android:defaultValue="true" />
+ <PreferenceScreen
+ android:key="pref_vibration_duration_settings"
+ android:title="@string/prefs_vibration_duration_settings"/>
<!-- TODO: evaluate results and revive this option. The code
already supports it. -->
<!-- <CheckBoxPreference -->
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 045f0d7b2..9e4c1ea79 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -138,7 +138,8 @@ public class Keyboard {
mProximityInfo = new ProximityInfo(
params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
- mMostCommonKeyWidth, mKeys);
+ mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrectionXs,
+ params.mTouchPositionCorrectionYs, params.mTouchPositionCorrectionRadii);
}
public ProximityInfo getProximityInfo() {
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 71b46d646..d35b1a939 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -16,6 +16,9 @@
package com.android.inputmethod.keyboard;
+import android.graphics.Rect;
+
+import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;
@@ -27,9 +30,9 @@ public class ProximityInfo {
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
/** Number of key widths from current touch point to search for nearest keys. */
private static float SEARCH_DISTANCE = 1.2f;
- private static final int UNKNOWN_THEME = -1;
private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private final int mKeyHeight;
private final int mGridWidth;
private final int mGridHeight;
private final int mGridSize;
@@ -40,8 +43,13 @@ public class ProximityInfo {
private final int mKeyboardHeight;
private final int[][] mGridNeighbors;
- ProximityInfo(
- int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, List<Key> keys) {
+ private final float[] mTouchPositionCorrectionXs;
+ private final float[] mTouchPositionCorrectionYs;
+ private final float[] mTouchPositionCorrectionRadii;
+
+ ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth,
+ int keyHeight, List<Key> keys, float[] touchPositionCorrectionXs,
+ float[] touchPositionCorrectionYs, float[] touchPositionCorrectionRadii) {
mGridWidth = gridWidth;
mGridHeight = gridHeight;
mGridSize = mGridWidth * mGridHeight;
@@ -49,6 +57,10 @@ public class ProximityInfo {
mCellHeight = (height + mGridHeight - 1) / mGridHeight;
mKeyboardMinWidth = minWidth;
mKeyboardHeight = height;
+ mKeyHeight = keyHeight;
+ mTouchPositionCorrectionXs = touchPositionCorrectionXs;
+ mTouchPositionCorrectionYs = touchPositionCorrectionYs;
+ mTouchPositionCorrectionRadii = touchPositionCorrectionRadii;
mGridNeighbors = new int[mGridSize][];
if (minWidth == 0 || height == 0) {
// No proximity required. Keyboard might be mini keyboard.
@@ -58,7 +70,7 @@ public class ProximityInfo {
}
public static ProximityInfo createDummyProximityInfo() {
- return new ProximityInfo(1, 1, 1, 1, 1, Collections.<Key>emptyList());
+ return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptyList(), null, null, null);
}
public static ProximityInfo createSpellCheckerProximityInfo() {
@@ -67,7 +79,7 @@ public class ProximityInfo {
spellCheckerProximityInfo.setProximityInfoNative(
SpellCheckerProximityInfo.ROW_SIZE,
480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY,
- 0, null, null, null, null, null, UNKNOWN_THEME);
+ 0, null, null, null, null, null, null, null, null);
return spellCheckerProximityInfo;
}
@@ -78,7 +90,8 @@ public class ProximityInfo {
private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray,
int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
- int[] keyWidths, int[] keyHeights, int[] keyCharCodes, int themeId);
+ int[] keyWidths, int[] keyHeights, int[] keyCharCodes,
+ float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii);
private native void releaseProximityInfoNative(int nativeProximityInfo);
private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
@@ -93,12 +106,11 @@ public class ProximityInfo {
}
}
final int keyCount = keys.size();
- int[] keyXCoordinates = new int[keyCount];
- int[] keyYCoordinates = new int[keyCount];
- int[] keyWidths = new int[keyCount];
- int[] keyHeights = new int[keyCount];
- int[] keyCharCodes = new int[keyCount];
- final int themeId = 5; // TODO: Use real theme id.
+ final int[] keyXCoordinates = new int[keyCount];
+ final int[] keyYCoordinates = new int[keyCount];
+ final int[] keyWidths = new int[keyCount];
+ final int[] keyHeights = new int[keyCount];
+ final int[] keyCharCodes = new int[keyCount];
for (int i = 0; i < keyCount; ++i) {
final Key key = keys.get(i);
keyXCoordinates[i] = key.mX;
@@ -107,10 +119,51 @@ public class ProximityInfo {
keyHeights[i] = key.mHeight;
keyCharCodes[i] = key.mCode;
}
+
+ final boolean hasTouchPositionCorrectionData =
+ mTouchPositionCorrectionXs != null
+ && mTouchPositionCorrectionYs != null
+ && mTouchPositionCorrectionRadii != null
+ && mTouchPositionCorrectionXs.length > 0
+ && mTouchPositionCorrectionYs.length > 0
+ && mTouchPositionCorrectionRadii.length > 0;
+ final float[] sweetSpotCenterXs =
+ hasTouchPositionCorrectionData ? new float[keyCount] : null;
+ final float[] sweetSpotCenterYs =
+ hasTouchPositionCorrectionData ? new float[keyCount] : null;
+ final float[] sweetSpotRadii =
+ hasTouchPositionCorrectionData ? new float[keyCount] : null;
+ if (hasTouchPositionCorrectionData) {
+ calculateSweetSpot(keys, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
+ }
+
mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray,
keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes,
- themeId);
+ sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
+ }
+
+ private void calculateSweetSpot(List<Key> keys, float[] sweetSpotCenterXs,
+ float[] sweetSpotCenterYs, float[] sweetSpotRadii) {
+ final int keyCount = keys.size();
+ for (int i = 0; i < keyCount; ++i) {
+ final Key key = keys.get(i);
+ final Rect hitBox = key.mHitBox;
+ final int row = hitBox.top / mKeyHeight;
+ if (row < mTouchPositionCorrectionRadii.length) {
+ final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f;
+ final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f;
+ final float hitBoxWidth = hitBox.right - hitBox.left;
+ final float hitBoxHeight = hitBox.bottom - hitBox.top;
+ final float x = mTouchPositionCorrectionXs[row];
+ final float y = mTouchPositionCorrectionYs[row];
+ final float radius = mTouchPositionCorrectionRadii[row];
+ sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth;
+ sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight;
+ sweetSpotRadii[i] = radius
+ * (float)Math.sqrt(hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight);
+ }
+ }
}
public int getNativeProximityInfo() {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 187a1adcb..46836da67 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -30,6 +30,7 @@ import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import org.xmlpull.v1.XmlPullParser;
@@ -126,6 +127,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
private static final int DEFAULT_KEYBOARD_ROWS = 4;
+ private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3;
+
protected final KP mParams;
protected final Context mContext;
protected final Resources mResources;
@@ -248,10 +251,62 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
mParams.mThemeId = a.getInt(R.styleable.KeyboardTheme_themeId, 0);
a.recycle();
+ if (!setTouchPositionCorrectionData(context)) {
+ // In the regression test, setTouchPositionCorrectionData() fails
+ mParams.mTouchPositionCorrectionXs = null;
+ mParams.mTouchPositionCorrectionYs = null;
+ mParams.mTouchPositionCorrectionRadii = null;
+ }
+
mParams.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
mParams.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
}
+ private boolean setTouchPositionCorrectionData(Context context) {
+ final TypedArray a = context.obtainStyledAttributes(R.styleable.KeyboardTheme);
+ final int resourceId = a.getResourceId(
+ R.styleable.KeyboardTheme_touchPositionCorrectionData, 0);
+ if (resourceId == 0) {
+ // In the regression test, we cannot use theme resources
+ // TODO: Fix this
+ return false;
+ }
+ final String[] data = context.getResources().getStringArray(resourceId);
+ a.recycle();
+ final int dataLength = data.length;
+ if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) {
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException("the size of touch position correction data is invalid");
+ }
+ return false;
+ }
+ final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ mParams.mTouchPositionCorrectionXs = new float[length];
+ mParams.mTouchPositionCorrectionYs = new float[length];
+ mParams.mTouchPositionCorrectionRadii = new float[length];
+ try {
+ for (int i = 0; i < dataLength; ++i) {
+ final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE;
+ final float value = Float.parseFloat(data[i]);
+ if (type == 0) {
+ mParams.mTouchPositionCorrectionXs[index] = value;
+ } else if (type == 1) {
+ mParams.mTouchPositionCorrectionYs[index] = value;
+ } else {
+ mParams.mTouchPositionCorrectionRadii[index] = value;
+ }
+ }
+ } catch (NumberFormatException e) {
+ if (LatinImeLogger.sDBG) {
+ throw new RuntimeException(
+ "the number format for touch position correction data is invalid");
+ }
+ return false;
+ }
+ return true;
+ }
+
public KeyboardBuilder<KP> load(KeyboardId id) {
mParams.mId = id;
try {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
index 97f58fad2..d1aea72a5 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
@@ -68,6 +68,10 @@ public class KeyboardParams {
public int mMostCommonKeyHeight = 0;
public int mMostCommonKeyWidth = 0;
+ public float[] mTouchPositionCorrectionXs;
+ public float[] mTouchPositionCorrectionYs;
+ public float[] mTouchPositionCorrectionRadii;
+
protected void clearKeys() {
mKeys.clear();
mShiftKeys.clear();
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 6a6a0a4ee..ab9edb110 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -61,6 +61,8 @@ public class BinaryDictionary extends Dictionary {
public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING =
new Flag(R.bool.config_require_umlaut_processing, 0x1);
+ public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2);
+
// Can create a new flag from extravalue :
// public static final Flag FLAG_MYFLAG =
// new Flag("my_flag", 0x02);
diff --git a/java/src/com/android/inputmethod/latin/Flag.java b/java/src/com/android/inputmethod/latin/Flag.java
index 3cb8f7e17..4ba6c80f5 100644
--- a/java/src/com/android/inputmethod/latin/Flag.java
+++ b/java/src/com/android/inputmethod/latin/Flag.java
@@ -25,8 +25,9 @@ public class Flag {
public final int mMask;
public final int mSource;
- static private final int SOURCE_CONFIG = 1;
- static private final int SOURCE_EXTRAVALUE = 2;
+ private static final int SOURCE_CONFIG = 1;
+ private static final int SOURCE_EXTRAVALUE = 2;
+ private static final int SOURCE_PARAM = 3;
public Flag(int resourceId, int mask) {
mName = null;
@@ -42,6 +43,13 @@ public class Flag {
mMask = mask;
}
+ public Flag(int mask) {
+ mName = null;
+ mResource = 0;
+ mSource = SOURCE_PARAM;
+ mMask = mask;
+ }
+
// If context/switcher are null, set all related flags in flagArray to on.
public static int initFlags(Flag[] flagArray, Context context, SubtypeSwitcher switcher) {
int flags = 0;
@@ -57,6 +65,9 @@ public class Flag {
switcher.currentSubtypeContainsExtraValueKey(entry.mName))
flags |= entry.mMask;
break;
+ case Flag.SOURCE_PARAM:
+ flags |= entry.mMask;
+ break;
}
}
return flags;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 32649d5a1..cf1cb8f25 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1661,9 +1661,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(
autoCorrectionAvailable);
} else {
- final SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
- if (previousSuggestions == mSettingsValues.mSuggestPuncList)
- return;
+ SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
+ if (previousSuggestions == mSettingsValues.mSuggestPuncList) {
+ if (builder.size() == 0) {
+ return;
+ }
+ previousSuggestions = SuggestedWords.EMPTY;
+ }
builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions);
}
}
@@ -2099,16 +2103,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
private void updateKeypressVibrationDuration() {
- final String[] durationPerHardwareList = mResources.getStringArray(
- R.array.keypress_vibration_durations);
- final String hardwarePrefix = Build.HARDWARE + ",";
- for (final String element : durationPerHardwareList) {
- if (element.startsWith(hardwarePrefix)) {
- mKeypressVibrationDuration =
- Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
- break;
- }
- }
+ mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources);
}
private void playKeyClick(int primaryCode) {
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
index 5a2eb1632..51f6c040d 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java
@@ -163,8 +163,6 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
- (container.getMeasuredHeight() - container.getPaddingBottom())
+ parentView.getPaddingTop() + mCoordinates[1];
- window.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- window.setOutsideTouchable(true);
window.setContentView(container);
window.setWidth(container.getMeasuredWidth());
window.setHeight(container.getMeasuredHeight());
@@ -221,22 +219,6 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
};
@Override
- public boolean dispatchTouchEvent(MotionEvent me) {
- final int index = me.getActionIndex();
- final int id = me.getPointerId(index);
- final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
- final int x = (int)me.getX(index);
- final int y = (int)me.getY(index);
- final boolean inside = (x >= 0 && x < getWidth() && y >= 0 && y < getHeight());
- if (inside || tracker.isInSlidingKeyInput()) {
- return super.dispatchTouchEvent(me);
- } else {
- dismissMoreKeysPanel();
- return true;
- }
- }
-
- @Override
public boolean onTouchEvent(MotionEvent me) {
final int action = me.getAction();
final long eventTime = me.getEventTime();
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index d706cd0a4..a2e896619 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -36,7 +36,10 @@ import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
+import android.view.View;
import android.view.inputmethod.EditorInfo;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.android.inputmethod.compat.CompatUtils;
@@ -89,6 +92,9 @@ public class Settings extends InputMethodSettingsActivity
public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+ public static final String PREF_VIBRATION_DURATION_SETTINGS =
+ "pref_vibration_duration_settings";
+
// Dialog ids
private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
@@ -335,6 +341,7 @@ public class Settings extends InputMethodSettingsActivity
private boolean mVoiceOn;
private AlertDialog mDialog;
+ private TextView mVibrationSettingsTextView;
private boolean mOkClicked = false;
private String mVoiceModeOff;
@@ -475,6 +482,19 @@ public class Settings extends InputMethodSettingsActivity
miscSettings.removePreference(pref);
}
}
+
+ final PreferenceScreen vibrationSettingsPref =
+ (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
+ if (vibrationSettingsPref != null) {
+ vibrationSettingsPref.setOnPreferenceClickListener(
+ new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference arg0) {
+ showVibrationSettingsDialog();
+ return true;
+ }
+ });
+ }
}
@SuppressWarnings("unused")
@@ -621,4 +641,51 @@ public class Settings extends InputMethodSettingsActivity
mVoicePreference.setValue(mVoiceModeOff);
}
}
-}
+
+ private void showVibrationSettingsDialog() {
+ final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+ final Activity context = getActivityInternal();
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.prefs_vibration_duration_settings);
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ final int ms = Integer.valueOf(mVibrationSettingsTextView.getText().toString());
+ sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
+ }
+ });
+ final View v = context.getLayoutInflater().inflate(
+ R.layout.vibration_settings_dialog, null);
+ final int currentMs = Utils.getCurrentVibrationDuration(
+ getPreferenceManager().getSharedPreferences(), getResources());
+ mVibrationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value);
+ final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings);
+ sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
+ final int tempMs = arg1;
+ mVibrationSettingsTextView.setText(String.valueOf(tempMs));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar arg0) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar arg0) {
+ final int tempMs = arg0.getProgress();
+ VibratorCompatWrapper.getInstance(context).vibrate(tempMs);
+ }
+ });
+ sb.setProgress(currentMs);
+ mVibrationSettingsTextView.setText(String.valueOf(currentMs));
+ builder.setView(v);
+ builder.create().show();
+ }
+} \ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/SuggestionsView.java
index 9d0e42a18..fe54f4ae1 100644
--- a/java/src/com/android/inputmethod/latin/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/SuggestionsView.java
@@ -27,6 +27,7 @@ import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Message;
import android.os.SystemClock;
@@ -506,10 +507,22 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
.findViewById(R.id.more_suggestions_view);
mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView);
- mMoreSuggestionsWindow = new PopupWindow(context);
- mMoreSuggestionsWindow.setWindowLayoutMode(
+
+ final PopupWindow moreWindow = new PopupWindow(context);
+ moreWindow.setWindowLayoutMode(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- mMoreSuggestionsWindow.setBackgroundDrawable(null);
+ moreWindow.setBackgroundDrawable(new ColorDrawable(android.R.color.transparent));
+ moreWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+ moreWindow.setFocusable(true);
+ moreWindow.setOutsideTouchable(true);
+ moreWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
+ @Override
+ public void onDismiss() {
+ mKeyboardView.dimEntireKeyboard(false);
+ }
+ });
+ mMoreSuggestionsWindow = moreWindow;
+
final Resources res = context.getResources();
mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
R.dimen.more_suggestions_modal_tolerance);
@@ -517,21 +530,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
context, mMoreSuggestionsSlidingListener);
}
- private final View.OnTouchListener mMoreSuggestionsCanceller = new View.OnTouchListener() {
- @Override
- public boolean onTouch(View view, MotionEvent me) {
- if (!mMoreSuggestionsWindow.isShowing()) return false;
-
- switch (me.getAction()) {
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- return mMoreSuggestionsView.dismissMoreKeysPanel();
- default:
- return true;
- }
- }
- };
-
/**
* A connection back to the input method.
* @param listener
@@ -726,8 +724,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
private boolean dismissMoreSuggestions() {
if (mMoreSuggestionsWindow.isShowing()) {
mMoreSuggestionsWindow.dismiss();
- mKeyboardView.dimEntireKeyboard(false);
- mKeyboardView.setOnTouchListener(null);
return true;
}
return false;
@@ -767,7 +763,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mOriginX = mLastX;
mOriginY = mLastY;
mKeyboardView.dimEntireKeyboard(true);
- mKeyboardView.setOnTouchListener(mMoreSuggestionsCanceller);
for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
mWords.get(i).setPressed(false);
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index c35273edd..771276567 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -17,9 +17,11 @@
package com.android.inputmethod.latin;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -772,4 +774,20 @@ public class Utils {
// - It also does not work with unicode surrogate code points.
return s.toUpperCase(locale).charAt(0) + s.substring(1);
}
+
+ public static int getCurrentVibrationDuration(SharedPreferences sp, Resources res) {
+ final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+ if (ms >= 0) {
+ return ms;
+ }
+ final String[] durationPerHardwareList = res.getStringArray(
+ R.array.keypress_vibration_durations);
+ final String hardwarePrefix = Build.HARDWARE + ",";
+ for (final String element : durationPerHardwareList) {
+ if (element.startsWith(hardwarePrefix)) {
+ return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
+ }
+ }
+ return -1;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 2546df0a2..1d5986ef9 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -70,11 +70,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private Map<String, Dictionary> mUserDictionaries =
Collections.synchronizedMap(new TreeMap<String, Dictionary>());
- private double mTypoThreshold;
+ // The threshold for a candidate to be offered as a suggestion.
+ private double mSuggestionThreshold;
+ // The threshold for a suggestion to be considered "likely".
+ private double mLikelyThreshold;
@Override public void onCreate() {
super.onCreate();
- mTypoThreshold = Double.parseDouble(getString(R.string.spellchecker_typo_threshold_value));
+ mSuggestionThreshold =
+ Double.parseDouble(getString(R.string.spellchecker_suggestion_threshold_value));
+ mLikelyThreshold =
+ Double.parseDouble(getString(R.string.spellchecker_likely_threshold_value));
}
@Override
@@ -95,6 +101,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private final int DEFAULT_SUGGESTION_LENGTH = 16;
private final ArrayList<CharSequence> mSuggestions;
private final int[] mScores;
+ private final String mOriginalText;
+ private final double mSuggestionThreshold;
+ private final double mLikelyThreshold;
private final int mMaxLength;
private int mLength = 0;
@@ -103,7 +112,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
private String mBestSuggestion = null;
private int mBestScore = Integer.MIN_VALUE; // As small as possible
- SuggestionsGatherer(final int maxLength) {
+ SuggestionsGatherer(final String originalText, final double suggestionThreshold,
+ final double likelyThreshold, final int maxLength) {
+ mOriginalText = originalText;
+ mSuggestionThreshold = suggestionThreshold;
+ mLikelyThreshold = likelyThreshold;
mMaxLength = maxLength;
mSuggestions = new ArrayList<CharSequence>(maxLength + 1);
mScores = new int[mMaxLength];
@@ -117,28 +130,42 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
// if it doesn't. See documentation for binarySearch.
final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
+ if (insertIndex == 0 && mLength >= mMaxLength) {
+ // In the future, we may want to keep track of the best suggestion score even if
+ // we are asked for 0 suggestions. In this case, we can use the following
+ // (tested) code to keep it:
+ // If the maxLength is 0 (should never be less, but if it is, it's treated as 0)
+ // then we need to keep track of the best suggestion in mBestScore and
+ // mBestSuggestion. This is so that we know whether the best suggestion makes
+ // the score cutoff, since we need to know that to return a meaningful
+ // looksLikeTypo.
+ // if (0 >= mMaxLength) {
+ // if (score > mBestScore) {
+ // mBestScore = score;
+ // mBestSuggestion = new String(word, wordOffset, wordLength);
+ // }
+ // }
+ return true;
+ }
+
+ // Compute the normalized score and skip this word if it's normalized score does not
+ // make the threshold.
+ final String wordString = new String(word, wordOffset, wordLength);
+ final double normalizedScore =
+ Utils.calcNormalizedScore(mOriginalText, wordString, score);
+ if (normalizedScore < mSuggestionThreshold) {
+ if (DBG) Log.i(TAG, wordString + " does not make the score threshold");
+ return true;
+ }
+
if (mLength < mMaxLength) {
final int copyLen = mLength - insertIndex;
++mLength;
System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen);
- mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
+ mSuggestions.add(insertIndex, wordString);
} else {
- if (insertIndex == 0) {
- // If the maxLength is 0 (should never be less, but if it is, it's treated as 0)
- // then we need to keep track of the best suggestion in mBestScore and
- // mBestSuggestion. This is so that we know whether the best suggestion makes
- // the score cutoff, since we need to know that to return a meaningful
- // looksLikeTypo.
- if (0 >= mMaxLength) {
- if (score > mBestScore) {
- mBestScore = score;
- mBestSuggestion = new String(word, wordOffset, wordLength);
- }
- }
- return true;
- }
System.arraycopy(mScores, 1, mScores, 0, insertIndex);
- mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
+ mSuggestions.add(insertIndex, wordString);
mSuggestions.remove(0);
}
mScores[insertIndex] = score;
@@ -146,8 +173,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
return true;
}
- public Result getResults(final CharSequence originalText, final double threshold,
- final int capitalizeType, final Locale locale) {
+ public Result getResults(final int capitalizeType, final Locale locale) {
final String[] gatheredSuggestions;
final boolean hasLikelySuggestions;
if (0 == mLength) {
@@ -160,8 +186,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
} else {
gatheredSuggestions = EMPTY_STRING_ARRAY;
final double normalizedScore =
- Utils.calcNormalizedScore(originalText, mBestSuggestion, mBestScore);
- hasLikelySuggestions = (normalizedScore > threshold);
+ Utils.calcNormalizedScore(mOriginalText, mBestSuggestion, mBestScore);
+ hasLikelySuggestions = (normalizedScore > mLikelyThreshold);
}
} else {
if (DBG) {
@@ -194,11 +220,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
final int bestScore = mScores[mLength - 1];
final CharSequence bestSuggestion = mSuggestions.get(0);
final double normalizedScore =
- Utils.calcNormalizedScore(originalText, bestSuggestion, bestScore);
- hasLikelySuggestions = (normalizedScore > threshold);
+ Utils.calcNormalizedScore(mOriginalText, bestSuggestion, bestScore);
+ hasLikelySuggestions = (normalizedScore > mLikelyThreshold);
if (DBG) {
Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
- Log.i(TAG, "Normalized score = " + normalizedScore + " (threshold " + threshold
+ Log.i(TAG, "Normalized score = " + normalizedScore
+ + " (threshold " + mLikelyThreshold
+ ") => hasLikelySuggestions = " + hasLikelySuggestions);
}
}
@@ -350,8 +377,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
}
// TODO: Don't gather suggestions if the limit is <= 0 unless necessary
- final SuggestionsGatherer suggestionsGatherer =
- new SuggestionsGatherer(suggestionsLimit);
+ final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(text,
+ mService.mSuggestionThreshold, mService.mLikelyThreshold, suggestionsLimit);
final WordComposer composer = new WordComposer();
final int length = text.length();
for (int i = 0; i < length; ++i) {
@@ -392,8 +419,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService {
}
}
- final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(text,
- mService.mTypoThreshold, capitalizeType, mLocale);
+ final SuggestionsGatherer.Result result = suggestionsGatherer.getResults(
+ capitalizeType, mLocale);
if (DBG) {
Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index 07cee4053..595ea2fdc 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -32,18 +32,27 @@ static jint latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object,
jint maxProximityCharsSize, jint displayWidth, jint displayHeight, jint gridWidth,
jint gridHeight, jintArray proximityCharsArray, jint keyCount,
jintArray keyXCoordinateArray, jintArray keyYCoordinateArray, jintArray keyWidthArray,
- jintArray keyHeightArray, jintArray keyCharCodeArray, jint themeId) {
+ jintArray keyHeightArray, jintArray keyCharCodeArray,
+ jfloatArray sweetSpotCenterXArray, jfloatArray sweetSpotCenterYArray,
+ jfloatArray sweetSpotRadiusArray) {
jint *proximityChars = env->GetIntArrayElements(proximityCharsArray, NULL);
jint *keyXCoordinates = safeGetIntArrayElements(env, keyXCoordinateArray);
jint *keyYCoordinates = safeGetIntArrayElements(env, keyYCoordinateArray);
jint *keyWidths = safeGetIntArrayElements(env, keyWidthArray);
jint *keyHeights = safeGetIntArrayElements(env, keyHeightArray);
jint *keyCharCodes = safeGetIntArrayElements(env, keyCharCodeArray);
+ jfloat *sweetSpotCenterXs = safeGetFloatArrayElements(env, sweetSpotCenterXArray);
+ jfloat *sweetSpotCenterYs = safeGetFloatArrayElements(env, sweetSpotCenterYArray);
+ jfloat *sweetSpotRadii = safeGetFloatArrayElements(env, sweetSpotRadiusArray);
ProximityInfo *proximityInfo = new ProximityInfo(maxProximityCharsSize, displayWidth,
displayHeight, gridWidth, gridHeight, (const uint32_t*)proximityChars,
keyCount, (const int32_t*)keyXCoordinates, (const int32_t*)keyYCoordinates,
(const int32_t*)keyWidths, (const int32_t*)keyHeights, (const int32_t*)keyCharCodes,
- themeId);
+ (const float*)sweetSpotCenterXs, (const float*)sweetSpotCenterYs,
+ (const float*)sweetSpotRadii);
+ safeReleaseFloatArrayElements(env, sweetSpotRadiusArray, sweetSpotRadii);
+ safeReleaseFloatArrayElements(env, sweetSpotCenterYArray, sweetSpotCenterYs);
+ safeReleaseFloatArrayElements(env, sweetSpotCenterXArray, sweetSpotCenterXs);
safeReleaseIntArrayElements(env, keyCharCodeArray, keyCharCodes);
safeReleaseIntArrayElements(env, keyHeightArray, keyHeights);
safeReleaseIntArrayElements(env, keyWidthArray, keyWidths);
@@ -60,7 +69,8 @@ static void latinime_Keyboard_release(JNIEnv *env, jobject object, jint proximit
}
static JNINativeMethod sKeyboardMethods[] = {
- {"setProximityInfoNative", "(IIIII[II[I[I[I[I[II)I", (void*)latinime_Keyboard_setProximityInfo},
+ {"setProximityInfoNative", "(IIIII[II[I[I[I[I[I[F[F[F)I",
+ (void*)latinime_Keyboard_setProximityInfo},
{"releaseProximityInfoNative", "(I)V", (void*)latinime_Keyboard_release}
};
diff --git a/native/jni/jni_common.h b/native/jni/jni_common.h
index dbf6d3e19..9548e1b3f 100644
--- a/native/jni/jni_common.h
+++ b/native/jni/jni_common.h
@@ -35,12 +35,26 @@ inline jint *safeGetIntArrayElements(JNIEnv *env, jintArray jArray) {
}
}
+inline jfloat *safeGetFloatArrayElements(JNIEnv *env, jfloatArray jArray) {
+ if (jArray) {
+ return env->GetFloatArrayElements(jArray, NULL);
+ } else {
+ return NULL;
+ }
+}
+
inline void safeReleaseIntArrayElements(JNIEnv *env, jintArray jArray, jint *cArray) {
if (jArray) {
env->ReleaseIntArrayElements(jArray, cArray, 0);
}
}
+inline void safeReleaseFloatArrayElements(JNIEnv *env, jfloatArray jArray, jfloat *cArray) {
+ if (jArray) {
+ env->ReleaseFloatArrayElements(jArray, cArray, 0);
+ }
+}
+
} // namespace latinime
#endif // LATINIME_JNI_COMMON_H
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index d5bfed017..9a7e5f35d 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -62,7 +62,8 @@ void Correction::initCorrectionState(
}
void Correction::setCorrectionParams(const int skipPos, const int excessivePos,
- const int transposedPos, const int spaceProximityPos, const int missingSpacePos) {
+ const int transposedPos, const int spaceProximityPos, const int missingSpacePos,
+ const bool useFullEditDistance) {
// TODO: remove
mTransposedPos = transposedPos;
mExcessivePos = excessivePos;
@@ -74,6 +75,7 @@ void Correction::setCorrectionParams(const int skipPos, const int excessivePos,
mSpaceProximityPos = spaceProximityPos;
mMissingSpacePos = missingSpacePos;
+ mUseFullEditDistance = useFullEditDistance;
}
void Correction::checkState() {
@@ -439,7 +441,7 @@ inline static void multiplyIntCapped(const int multiplier, int *base) {
}
inline static int powerIntCapped(const int base, const int n) {
- if (n == 0) return 1;
+ if (n <= 0) return 1;
if (base == 2) {
return n < 31 ? 1 << n : S_INT_MAX;
} else {
@@ -529,6 +531,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
const int proximityMatchedCount = correction->mProximityCount;
const bool lastCharExceeded = correction->mLastCharExceeded;
+ const bool useFullEditDistance = correction->mUseFullEditDistance;
+ const int outputLength = outputIndex + 1;
if (skippedCount >= inputLength || inputLength == 0) {
return -1;
}
@@ -682,6 +686,12 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
multiplyIntCapped(fullWordMultiplier, &finalFreq);
}
+ if (useFullEditDistance && outputLength > inputLength + 1) {
+ const int diff = outputLength - inputLength - 1;
+ const int divider = diff < 31 ? 1 << diff : S_INT_MAX;
+ finalFreq = divider > finalFreq ? 1 : finalFreq / divider;
+ }
+
if (DEBUG_DICT_FULL) {
LOGI("calc: %d, %d", outputIndex, sameLength);
}
diff --git a/native/src/correction.h b/native/src/correction.h
index 41130ad77..ddb98b9d8 100644
--- a/native/src/correction.h
+++ b/native/src/correction.h
@@ -44,7 +44,7 @@ public:
// TODO: remove
void setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos,
- const int spaceProximityPos, const int missingSpacePos);
+ const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance);
void checkState();
bool initProcessState(const int index);
@@ -111,6 +111,7 @@ private:
const int FULL_WORD_MULTIPLIER;
const ProximityInfo *mProximityInfo;
+ bool mUseFullEditDistance;
int mMaxEditDistance;
int mMaxDepth;
int mInputLength;
diff --git a/native/src/defines_touch_position_correction.h b/native/src/defines_touch_position_correction.h
deleted file mode 100644
index 122906804..000000000
--- a/native/src/defines_touch_position_correction.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-**
-** Copyright 2011, 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_DEFINES_TOUCH_POSITION_CORRECTION_H
-#define LATINIME_DEFINES_TOUCH_POSITION_CORRECTION_H
-
-#define OUTER_SWEET_SPOT_RADIUS_RATIO 1.3
-
-static const char* TOUCH_POSITION_CORRECTION_GROUPS[] = {
- "qwertyuiop",
- "a",
- "sdfghjk",
- "l",
- "zxcvbnm",
-};
-
-// (center X) / (key width)
-static const float RELATIVE_TOUCH_CENTER_X[] = {
- 0, // qwertyuiop
- -0.26871, // a
- 0, // sdfghjk
- 0.028050, // l
- 0, // zxcvbnm
-};
-
-// (center Y) / (key height)
-static const float RELATIVE_TOUCH_CENTER_Y[] = {
- 0.192088, // qwertyuiop
- 0.214100, // a
- 0.216640, // sdfghjk
- 0.233288, // l
- 0.286598, // zxcvbnm
-};
-
-// (sweet spot radius) / ((key width) + (key height))
-static const float SWEET_SPOT_RADIUS[] = {
- 0.148955, // qwertyuiop
- 0.185437, // a
- 0.145522, // sdfghjk
- 0.156882, // l
- 0.144211, // zxcvbnm
-};
-
-#define CORRECTION_GROUP_COUNT \
- ((int)(sizeof(TOUCH_POSITION_CORRECTION_GROUPS) / sizeof(TOUCH_POSITION_CORRECTION_GROUPS[0])))
-
-#endif // LATINIME_DEFINES_TOUCH_POSITION_CORRECTION_H
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index 58842b92f..4ff6e0ac0 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -20,7 +20,6 @@
#define LOG_TAG "LatinIME: proximity_info.cpp"
-#include "defines_touch_position_correction.h"
#include "dictionary.h"
#include "proximity_info.h"
@@ -38,12 +37,13 @@ ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboard
const int keyboardHeight, const int gridWidth, const int gridHeight,
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, int themeId)
+ const int32_t *keyCharCodes, const float *sweetSpotCenterXs, const float *sweetSpotCenterYs,
+ const float *sweetSpotRadii)
: MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth),
KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight),
CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
- KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), THEME_ID(themeId) {
+ KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)) {
const int len = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
mProximityCharsArray = new uint32_t[len];
if (DEBUG_PROXIMITY_INFO) {
@@ -56,33 +56,24 @@ ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboard
copyOrFillZero(mKeyWidths, keyWidths, KEY_COUNT * sizeof(mKeyWidths[0]));
copyOrFillZero(mKeyHeights, keyHeights, KEY_COUNT * sizeof(mKeyHeights[0]));
copyOrFillZero(mKeyCharCodes, keyCharCodes, KEY_COUNT * sizeof(mKeyCharCodes[0]));
+ copyOrFillZero(mSweetSpotCenterXs, sweetSpotCenterXs,
+ KEY_COUNT * sizeof(mSweetSpotCenterXs[0]));
+ copyOrFillZero(mSweetSpotCenterYs, sweetSpotCenterYs,
+ KEY_COUNT * sizeof(mSweetSpotCenterYs[0]));
+ copyOrFillZero(mSweetSpotRadii, sweetSpotRadii, KEY_COUNT * sizeof(mSweetSpotRadii[0]));
- initializeCodeToGroup();
initializeCodeToKeyIndex();
}
-// Build the reversed look up table from the char code to the index in its group.
-// see TOUCH_POSITION_CORRECTION_GROUPS
-void ProximityInfo::initializeCodeToGroup() {
- memset(mCodeToGroup, -1, (MAX_GROUPED_CHAR_CODE + 1) * sizeof(mCodeToGroup[0]));
- for (int i = 0; i < CORRECTION_GROUP_COUNT; ++i) {
- const char *group = TOUCH_POSITION_CORRECTION_GROUPS[i];
- for (int j = 0; group[j]; ++j) {
- const int code = group[j];
- if (0 <= code && code <= MAX_GROUPED_CHAR_CODE)
- mCodeToGroup[code] = i;
- }
- }
-}
-
// Build the reversed look up table from the char code to the index in mKeyXCoordinates,
// mKeyYCoordinates, mKeyWidths, mKeyHeights, mKeyCharCodes.
void ProximityInfo::initializeCodeToKeyIndex() {
- memset(mCodeToKeyIndex, -1, (MAX_GROUPED_CHAR_CODE + 1) * sizeof(mCodeToKeyIndex[0]));
+ memset(mCodeToKeyIndex, -1, (MAX_CHAR_CODE + 1) * sizeof(mCodeToKeyIndex[0]));
for (int i = 0; i < KEY_COUNT; ++i) {
const int code = mKeyCharCodes[i];
- if (0 <= code && code <= MAX_GROUPED_CHAR_CODE)
+ if (0 <= code && code <= MAX_CHAR_CODE) {
mCodeToKeyIndex[code] = i;
+ }
}
}
@@ -210,6 +201,6 @@ bool ProximityInfo::sameAsTyped(const unsigned short *word, int length) const {
}
const int ProximityInfo::MAX_KEY_COUNT_IN_A_KEYBOARD;
-const int ProximityInfo::MAX_GROUPED_CHAR_CODE;
+const int ProximityInfo::MAX_CHAR_CODE;
} // namespace latinime
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index 3190e73ef..b1e8236d3 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -37,7 +37,8 @@ public:
const int keybaordHeight, const int gridWidth, const int gridHeight,
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, int themeId);
+ const int32_t *keyCharCodes, const float *sweetSpotCenterXs,
+ const float *sweetSpotCenterYs, const float *sweetSpotRadii);
~ProximityInfo();
bool hasSpaceProximity(const int x, const int y) const;
void setInputParams(const int* inputCodes, const int inputLength);
@@ -55,11 +56,10 @@ public:
private:
// The max number of the keys in one keyboard layout
static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64;
- // The upper limit of the char code in TOUCH_POSITION_CORRECTION_GROUP
- static const int MAX_GROUPED_CHAR_CODE = 127;
+ // The upper limit of the char code in mCodeToKeyIndex
+ static const int MAX_CHAR_CODE = 127;
int getStartIndexFromCoordinates(const int x, const int y) const;
- void initializeCodeToGroup();
void initializeCodeToKeyIndex();
const int MAX_PROXIMITY_CHARS_SIZE;
const int KEYBOARD_WIDTH;
@@ -69,7 +69,6 @@ private:
const int CELL_WIDTH;
const int CELL_HEIGHT;
const int KEY_COUNT;
- const int THEME_ID;
const int *mInputCodes;
uint32_t *mProximityCharsArray;
int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
@@ -77,10 +76,12 @@ private:
int32_t mKeyWidths[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyHeights[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyCharCodes[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
int mInputLength;
unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
- int mCodeToGroup[MAX_GROUPED_CHAR_CODE + 1];
- int mCodeToKeyIndex[MAX_GROUPED_CHAR_CODE + 1];
+ int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
};
} // namespace latinime
diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp
index 517dc843e..1b798a8f1 100644
--- a/native/src/unigram_dictionary.cpp
+++ b/native/src/unigram_dictionary.cpp
@@ -132,7 +132,8 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit
memcpy(codesDest, codesSrc, remainingBytes);
getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
- (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies);
+ (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies,
+ flags);
}
int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
@@ -146,7 +147,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
codesSize, flags, codes, codesSize, 0, codesBuffer, outWords, frequencies);
} else { // Normal processing
getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize,
- outWords, frequencies);
+ outWords, frequencies, flags);
}
PROF_START(20);
@@ -175,7 +176,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize,
- unsigned short *outWords, int *frequencies) {
+ unsigned short *outWords, int *frequencies, const int flags) {
PROF_OPEN;
PROF_START(0);
@@ -187,9 +188,10 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
mCorrection->initCorrection(mProximityInfo, mInputLength, maxDepth);
PROF_END(0);
+ const bool useFullEditDistance = USE_FULL_EDIT_DISTANCE & flags;
// TODO: remove
PROF_START(1);
- getSuggestionCandidates();
+ getSuggestionCandidates(useFullEditDistance);
PROF_END(1);
PROF_START(2);
@@ -212,7 +214,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
if (DEBUG_DICT) {
LOGI("--- Suggest missing space characters %d", i);
}
- getMissingSpaceWords(mInputLength, i, mCorrection);
+ getMissingSpaceWords(mInputLength, i, mCorrection, useFullEditDistance);
}
}
PROF_END(5);
@@ -231,7 +233,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
i, x, y, proximityInfo->hasSpaceProximity(x, y));
}
if (proximityInfo->hasSpaceProximity(x, y)) {
- getMistypedSpaceWords(mInputLength, i, mCorrection);
+ getMistypedSpaceWords(mInputLength, i, mCorrection, useFullEditDistance);
}
}
}
@@ -315,10 +317,10 @@ bool UnigramDictionary::addWord(unsigned short *word, int length, int frequency)
static const char QUOTE = '\'';
static const char SPACE = ' ';
-void UnigramDictionary::getSuggestionCandidates() {
+void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance) {
// TODO: Remove setCorrectionParams
mCorrection->setCorrectionParams(0, 0, 0,
- -1 /* spaceProximityPos */, -1 /* missingSpacePos */);
+ -1 /* spaceProximityPos */, -1 /* missingSpacePos */, useFullEditDistance);
int rootPosition = ROOT_POS;
// Get the number of children of root, then increment the position
int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
@@ -349,16 +351,20 @@ void UnigramDictionary::getSuggestionCandidates() {
}
void UnigramDictionary::getMissingSpaceWords(
- const int inputLength, const int missingSpacePos, Correction *correction) {
+ const int inputLength, const int missingSpacePos, Correction *correction,
+ const bool useFullEditDistance) {
correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
- -1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos);
+ -1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos,
+ useFullEditDistance);
getSplitTwoWordsSuggestion(inputLength, correction);
}
void UnigramDictionary::getMistypedSpaceWords(
- const int inputLength, const int spaceProximityPos, Correction *correction) {
+ const int inputLength, const int spaceProximityPos, Correction *correction,
+ const bool useFullEditDistance) {
correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
- -1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */);
+ -1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */,
+ useFullEditDistance);
getSplitTwoWordsSuggestion(inputLength, correction);
}
diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h
index 65746db8d..ef9709a89 100644
--- a/native/src/unigram_dictionary.h
+++ b/native/src/unigram_dictionary.h
@@ -78,7 +78,7 @@ private:
void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
const int *ycoordinates, const int *codes, const int codesSize,
- unsigned short *outWords, int *frequencies);
+ unsigned short *outWords, int *frequencies, const int flags);
bool isDigraph(const int* codes, const int i, const int codesSize) const;
void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo,
const int *xcoordinates, const int* ycoordinates, const int *codesBuffer,
@@ -87,13 +87,13 @@ private:
void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
const int *ycoordinates, const int *codes, const int codesSize,
unsigned short *outWords, int *frequencies);
- void getSuggestionCandidates();
+ void getSuggestionCandidates(const bool useFullEditDistance);
bool addWord(unsigned short *word, int length, int frequency);
void getSplitTwoWordsSuggestion(const int inputLength, Correction *correction);
- void getMissingSpaceWords(
- const int inputLength, const int missingSpacePos, Correction *correction);
- void getMistypedSpaceWords(
- const int inputLength, const int spaceProximityPos, Correction *correction);
+ void getMissingSpaceWords(const int inputLength, const int missingSpacePos,
+ Correction *correction, const bool useFullEditDistance);
+ void getMistypedSpaceWords(const int inputLength, const int spaceProximityPos,
+ Correction *correction, const bool useFullEditDistance);
void onTerminal(const int freq, Correction *correction);
bool needsToSkipCurrentNode(const unsigned short c,
const int inputIndex, const int skipPos, const int depth);
@@ -122,7 +122,8 @@ private:
// or something very bad (like, the apocalypse) will happen.
// Please update both at the same time.
enum {
- REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1
+ REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1,
+ USE_FULL_EDIT_DISTANCE = 0x2
};
static const struct digraph_t { int first; int second; } GERMAN_UMLAUT_DIGRAPHS[];
diff --git a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
index 096bfd182..35a7b51d6 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java
@@ -60,6 +60,7 @@ public class XmlDictInputOutput {
final FusionDictionary mDictionary;
int mState; // the state of the parser
int mFreq; // the currently read freq
+ String mWord; // the current word
final HashMap<String, ArrayList<WeightedString>> mBigramsMap;
/**
@@ -72,6 +73,7 @@ public class XmlDictInputOutput {
HashMap<String, ArrayList<WeightedString>> bigrams) {
mDictionary = dict;
mBigramsMap = bigrams;
+ mWord = "";
mState = START;
mFreq = 0;
}
@@ -80,6 +82,7 @@ public class XmlDictInputOutput {
public void startElement(String uri, String localName, String qName, Attributes attrs) {
if (WORD_TAG.equals(localName)) {
mState = WORD;
+ mWord = "";
for (int attrIndex = 0; attrIndex < attrs.getLength(); ++attrIndex) {
final String attrName = attrs.getLocalName(attrIndex);
if (FREQUENCY_ATTR.equals(attrName)) {
@@ -94,14 +97,19 @@ public class XmlDictInputOutput {
@Override
public void characters(char[] ch, int start, int length) {
if (WORD == mState) {
- final String word = String.copyValueOf(ch, start, length);
- mDictionary.add(word, mFreq, mBigramsMap.get(word));
+ // The XML parser is free to return text in arbitrary chunks one after the
+ // other. In particular, this happens in some implementations when it finds
+ // an escape code like "&amp;".
+ mWord += String.copyValueOf(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) {
- if (WORD == mState) mState = START;
+ if (WORD == mState) {
+ mDictionary.add(mWord, mFreq, mBigramsMap.get(mWord));
+ mState = START;
+ }
}
}