aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values-af/strings.xml12
-rw-r--r--java/res/values-am/strings.xml12
-rw-r--r--java/res/values-ar/strings.xml12
-rw-r--r--java/res/values-be/strings.xml12
-rw-r--r--java/res/values-bg/strings.xml12
-rw-r--r--java/res/values-ca/strings.xml12
-rw-r--r--java/res/values-cs/strings.xml12
-rw-r--r--java/res/values-da/strings.xml12
-rw-r--r--java/res/values-de/strings.xml12
-rw-r--r--java/res/values-el/strings.xml12
-rw-r--r--java/res/values-es-rUS/strings.xml12
-rw-r--r--java/res/values-es/strings.xml12
-rw-r--r--java/res/values-et/strings.xml12
-rw-r--r--java/res/values-fa/strings.xml12
-rw-r--r--java/res/values-fi/strings.xml12
-rw-r--r--java/res/values-fr/strings.xml12
-rw-r--r--java/res/values-hi/strings.xml12
-rw-r--r--java/res/values-hr/strings.xml12
-rw-r--r--java/res/values-hu/strings.xml12
-rw-r--r--java/res/values-in/strings.xml12
-rw-r--r--java/res/values-it/strings.xml12
-rw-r--r--java/res/values-iw/strings.xml12
-rw-r--r--java/res/values-ja/strings.xml12
-rw-r--r--java/res/values-ko/strings.xml12
-rw-r--r--java/res/values-lt/strings.xml12
-rw-r--r--java/res/values-lv/strings.xml12
-rw-r--r--java/res/values-ms/strings.xml12
-rw-r--r--java/res/values-nb/strings.xml12
-rw-r--r--java/res/values-nl/strings.xml12
-rw-r--r--java/res/values-pl/strings.xml12
-rw-r--r--java/res/values-pt-rPT/strings.xml12
-rw-r--r--java/res/values-pt/strings.xml12
-rw-r--r--java/res/values-ro/strings.xml12
-rw-r--r--java/res/values-ru/strings.xml12
-rw-r--r--java/res/values-sk/strings.xml12
-rw-r--r--java/res/values-sl/strings.xml12
-rw-r--r--java/res/values-sr/strings.xml12
-rw-r--r--java/res/values-sv/strings.xml12
-rw-r--r--java/res/values-sw/strings.xml12
-rw-r--r--java/res/values-th/strings.xml12
-rw-r--r--java/res/values-tl/strings.xml12
-rw-r--r--java/res/values-tr/strings.xml12
-rw-r--r--java/res/values-uk/strings.xml12
-rw-r--r--java/res/values-vi/strings.xml12
-rw-r--r--java/res/values-zh-rCN/strings.xml12
-rw-r--r--java/res/values-zh-rTW/strings.xml12
-rw-r--r--java/res/values-zu/strings.xml12
-rw-r--r--java/res/values/strings.xml18
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java16
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java138
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java166
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java5
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java31
-rw-r--r--java/src/com/android/inputmethod/latin/define/ProductionFlag.java2
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java35
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java8
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java3
-rw-r--r--native/jni/Android.mk30
-rw-r--r--native/jni/jni_common.cpp4
-rw-r--r--native/jni/src/bigram_dictionary.cpp6
-rw-r--r--native/jni/src/correction.cpp20
-rw-r--r--native/jni/src/correction.h2
-rw-r--r--native/jni/src/defines.h1
-rw-r--r--native/jni/src/dictionary.cpp40
-rw-r--r--native/jni/src/dictionary.h1
-rw-r--r--native/jni/src/digraph_utils.cpp93
-rw-r--r--native/jni/src/digraph_utils.h47
-rw-r--r--native/jni/src/suggest/core/dictionary/shortcut_utils.h65
-rw-r--r--native/jni/src/suggest/core/policy/traversal.h3
-rw-r--r--native/jni/src/suggest/core/policy/weighting.cpp11
-rw-r--r--native/jni/src/suggest/core/policy/weighting.h1
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.cpp5
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.h2
-rw-r--r--native/jni/src/suggest/core/suggest.cpp520
-rw-r--r--native/jni/src/suggest/core/suggest.h95
-rw-r--r--native/jni/src/suggest/core/suggest_interface.h (renamed from native/jni/src/suggest/suggest_interface.h)0
-rw-r--r--native/jni/src/suggest/gesture_suggest.h61
-rw-r--r--native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp (renamed from native/jni/src/suggest/typing_suggest.cpp)8
-rw-r--r--native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h44
-rw-r--r--native/jni/src/suggest/policyimpl/typing/scoring_params.cpp52
-rw-r--r--native/jni/src/suggest/policyimpl/typing/scoring_params.h66
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp21
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_scoring.h82
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp21
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h55
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h37
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp24
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.h184
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp (renamed from native/jni/src/suggest/gesture_suggest.cpp)13
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.h195
-rw-r--r--native/jni/src/suggest/typing_suggest.h61
-rw-r--r--native/jni/src/unigram_dictionary.cpp31
-rw-r--r--native/jni/src/unigram_dictionary.h10
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java203
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java26
95 files changed, 2462 insertions, 664 deletions
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index f0b47be0e..90f321b01 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-sleutelbord (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-sleutelbord-instellings (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-speltoetser (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android-speltoetserinstellings (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Navorsing-loglêerbevele"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index f6ccec71a..7a6dd1d16 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"የAndroid ቁልፍ ሰሌዳ (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"የAndroid ቁልፍ ሰሌዳ ቅንብሮች (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android ፊደል አራሚ (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"የAndroid ፊደል አራሚ ቅንብሮች (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"የጥናት የምዝግብ ማስታወሻ ትዕዛዞች"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"የእውቅያ ስሞችን ተመልከት"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index f9b01d377..e9f92373c 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"لوحة مفاتيح Android ‏(AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"إعدادات لوحة مفاتيح Android‏ (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"المدقق الإملائي في Android‏ (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"إعدادات المدقق الإملائي في Android‏ (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"أوامر سجلات البحث"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"بحث في أسماء جهات الاتصال"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index 6c95cceba..c32a56d1d 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавіятура Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Налады клавіятуры Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Iнструмент праверкi правапiсу для Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Налады інструмента праверкі правапісу для Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Каманды гiсторыя даследаванняў"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукаць імёны кантактаў"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 58a6a7083..5feac034b 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавиатура на Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Настройки на клавиатурата на Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Програма за правописна проверка за Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Настройки на програмата за правописна проверка за Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Команди за рег. файл за проучвания"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Търсене на имена"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 5539fee7e..3ebf6397c 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclat d\'Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configuració del teclat d\'Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector ortogràfic d\'Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configuració del corrector ortogràfic d\'Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Recerca d\'ordres de reg."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index c7261ba7f..050ae6481 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klávesnice Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavení klávesnice Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kontrola pravopisu Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavení kontroly pravopisu Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Příkazy vývoj. protokolu"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 1ed998359..034c98f62 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-tastatur (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Indstillinger for Android-tastatur (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-stavekontrol (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Indstillinger for Android-stavekontrol (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Forskningslogkommandoer"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå kontaktnavne op"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 9816621c6..39444ea2f 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-Tastatur (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-Tastatureinstellungen (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-Rechtschreibprüfung (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Einstellungen für die Android-Rechtschreibprüfung (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Forschungsprotokollbefehle"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index f3b84c60b..93de977a7 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Πληκτρολόγιο Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ρυθμίσεις πληκτρολογίου Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Ορθογραφικός έλεγχος Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ρυθμίσεις ορθογραφικού ελέγχου Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Έρευνα εντολών καταγραφής"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Αναζήτηση ονομάτων επαφών"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index c7f20aae3..a544f7798 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado de Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configuración del teclado de Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector ortográfico de Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configuración del corrector ortográfico de Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro invest."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 81682589a..afc04f5b7 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ajustes del teclado de Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corrector de Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ajustes del corrector de Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro investigación"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Nombres de contactos"</string>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 8968bf4f8..acfa957f9 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidi klaviatuur (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Androidi klaviatuuri seaded (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidi õigekirjakontroll (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidi õigekirjakontrolli seaded (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Uuringulogi käsud"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakti nimede kontroll."</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 723ecd631..52d5b835e 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"صفحه کلید Android ‏(AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"تنظیمات صفحه کلید Android ‏(AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"غلط‌گیر Android ‏(AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"تنظیمات غلط‌گیر Android ‏(AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"گزینه‌های ورودی"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"فرمان‌های گزارش‌گیری پژوهش"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"جستجوی نام مخاطبین"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 2e6e4d1ce..8f36524df 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-näppäimistö (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-näppäimistön asetukset (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-oikoluku (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android-oikoluvun asetukset (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Tutkimuslokin komennot"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae kontaktien nimiä"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 2b8e3cbae..4daa0f6d9 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Clavier Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Paramètres du clavier Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Correcteur orthographique Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Paramètres du correcteur orthographique Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 28c48791e..c4238e88f 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android कीबोर्ड (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android कीबोर्ड सेटिंग (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android वर्तनी परीक्षक (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android वर्तनी परीक्षक सेटिंग (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्‍प"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"लॉग आदेशों का शोध करें"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"संपर्क नामों को खोजें"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 473287698..a5515cf06 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidova tipkovnica (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Postavke Androidove tipkovnice (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidova provjera pravopisa (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Postavke Androidove provjere pravopisa (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Istraživanje naredbi dnevnika"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 68ca03e63..d6075f778 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-billentyűzet (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android-billentyűzet beállításai (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidos helyesírás-ellenőrző (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidos helyesírás-ellenőrző beállításai (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Naplózási parancsok"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index e361e6951..953e0919d 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Keyboard Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Setelan Keyboard Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Pemeriksa Ejaan Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Setelan Pemeriksa Ejaan Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Riset Perintah Log"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kontak"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 52c2bfa88..7ce349a5e 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tastiera Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Impostazioni tastiera Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Controllo ortografico Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Impostazioni controllo ortografico Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Ricerca comandi di log"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index a2359378d..e3d3064b2 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"מקלדת Android‏ (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"הגדרות מקלדת Android‏ (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"בודק האיות של Android‏ (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"הגדרות בודק האיות של Android‏ (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"פקודות יומן מחקר"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"חפש שמות של אנשי קשר"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index a3da75200..6d6259d13 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androidキーボード(AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Androidキーボードの設定(AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Androidスペルチェッカー(AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Androidスペルチェッカーの設定(AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"ログコマンドの検索"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"連絡先名の検索"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 1f4596bbc..c58613dd7 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 키보드(AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 키보드 설정(AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 맞춤법 검사기(AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 맞춤법 검사기 설정(AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"로그 명령 탐색"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"연락처 이름 조회"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 307b5f234..57cf7bdfd 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"„Android“ klaviatūra (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"„Android“ klaviatūros nustatymai (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"„Android“ rašybos tikrinimo programa (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"„Android“ rašybos tikrinimo programos nustatymai (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Tyrinėti žurnalo komandas"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 0241583f6..499a451d1 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android tastatūra (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android tastatūras iestatījumi (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android pareizrakstības pārbaudītājs (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android pareizrakstības pārbaudītāja iestatījumi (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Izpētes žurnāla komandas"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index afb036a89..faf91646a 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Papan kekunci Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Tetapan Papan Kekunci Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Penyemak Ejaan Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Tetapan Penyemak Ejaan Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Arahan Log Penyelidikan"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 5db141c06..cd2606d75 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-tastatur (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Instillinger for Android-tastatur (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android-stavekontroll (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Innstillinger for Android-stavekontroll (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Kommandoer for undersøkelseslogging"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 176f828cc..fb2a82e40 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android-toetsenbord (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Instellingen voor het Android-toetsenbord (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Spellingcontrole van Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Instellingen voor spellingcontrole van Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Opdrachten in onderzoekslogbestand"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 34a03f6d3..f703a74e2 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klawiatura Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Ustawienia klawiatury Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Ustawienia sprawdzania pisowni na Androidzie (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Polecenia dziennika badań"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj kontakty"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 81e1485e1..9c52fd76c 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Definições do Teclado Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Verificador Ortográfico Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Definições do Verificador Ortográfico Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Comandos de Reg. Invest."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 880aca65d..dd1fcfd03 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Teclado Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Configurações de teclado Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Corretor ortográfico do Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Configurações de corretor ortográfico do Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Pesq. comandos de reg."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index a62bfd274..b0732c802 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tastatură Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Setări tastatură Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Verificator ortografic Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Setări verificator ortografic Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Comenzi jurnal cercetare"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index dab73870e..b3d770679 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавиатура Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Настройки клавиатуры Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Проверка правописания Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Настройки проверки правописания Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Настройки"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Все команды"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Поиск контактов"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index d6d8068b7..77d9409ae 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Klávesnica Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavenia klávesnice Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kontrola pravopisu (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavenia kontroly pravopisu Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Príkazy denníka výskumu"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 37540c3f7..87961ef2f 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Tipkovnica za Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Nastavitve tipkovnice za Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Črkovalnik za Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Nastavitve črkovalnika za Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Ukazi za dnevnik raziskav"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 8b8720f59..d8b3dbfbe 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android тастатура (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Подешавања Android тастатуре (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android провера правописа (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Подешавања Android провере правописа (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Команде евиденције истраживања"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Потражи имена контаката"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 6ceed109b..d17893380 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Androids tangentbord (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Inställningar för Androids tangentbord (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Stavningskontroll i Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Inställningar för Androids stavningskontroll (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Loggkommandon"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 5b566016d..290952645 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Kibodi ya Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Mipangilio ya Kibodi ya Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Kikagua-tahajia cha Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Mipangilio ya Kikagua-tahajia cha Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya unaowasiliana nao"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 28580762f..142903ca2 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"แป้นพิมพ์แอนดรอยด์ (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"การตั้งค่าแป้นพิมพ์แอนดรอยด์ (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"เครื่องตรวจตัวสะกดแอนดรอยด์ (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"การตั้งค่าเครื่องตรวจตัวสะกดแอนดรอยด์ (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"คำสั่งบันทึกการวิจัย"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ค้นหารายชื่อติดต่อ"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 04127ab61..fea07b446 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android Keyboard (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Mga Setting ng Android Keyboard (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Spell Checker ng Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Mga Setting ng Spell Checker ng Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Cmmnd sa Log ng Pnnliksik"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index f238f20d2..b976932de 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android klavye (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android Klavye Ayarları (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android Yazım Denetleyici (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android Yazım Denetleyici Ayarları (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Araştırma Günlüğü Komutları"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 42a0b9f26..f81ace632 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Клавіатура Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Налаштування клавіатури Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Перевірка орфографії Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Налаштування перевірки орфографії Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Команди журналу дослідж."</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукати імена контактів"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 245e68541..fac412a57 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Bàn phím Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Cài đặt bàn phím Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Trình kiểm tra chính tả Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Cài đặt trình kiểm tra chính tả Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Lệnh ghi nhật ký cho nghiên cứu"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index cba33224b..693a6746d 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 键盘 (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 键盘设置 (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 拼写检查工具 (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 拼写检查工具设置 (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"研究记录命令"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找联系人姓名"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 9a4896974..1fb204f2e 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Android 鍵盤 (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Android 鍵盤設定 (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Android 拼字檢查 (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Android 拼字檢查設定 (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"研究紀錄指令"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查詢聯絡人姓名"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index e360750dc..bcec13d4b 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -20,14 +20,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (8250992613616792321) -->
- <skip />
- <!-- no translation found for aosp_android_keyboard_ime_settings (423615877174850267) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (511950477199948048) -->
- <skip />
- <!-- no translation found for aosp_android_spell_checker_service_settings (2970535894327288421) -->
- <skip />
+ <string name="aosp_android_keyboard_ime_name" msgid="8250992613616792321">"Ikhibhodi ye-Android (AOSP)"</string>
+ <string name="aosp_android_keyboard_ime_settings" msgid="423615877174850267">"Izilungiselelo zekhibhodi ye-Android (AOSP)"</string>
+ <string name="aosp_spell_checker_service_name" msgid="511950477199948048">"Isihloli sokupela se-Android (AOSP)"</string>
+ <string name="aosp_android_spell_checker_service_settings" msgid="2970535894327288421">"Izilungiselelo zesihloli sokupela se-Android (AOSP)"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
<string name="english_ime_research_log" msgid="8492602295696577851">"Imiyalo yefayela lokungena lokucwaninga"</string>
<string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index ebcd3d956..201fc7030 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -350,10 +350,10 @@
<!-- Inform the user that a particular language has an available dictionary -->
<string name="has_dictionary">Dictionary available</string>
- <!-- Preferences item for enabling to send user statistics to Google -->
+ <!-- Preferences item for enabling to send user statistics for development only diagnostics -->
<string name="prefs_enable_log">Enable user feedback</string>
- <!-- Description for enabling to send user statistics to Google -->
- <string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports to Google.</string>
+ <!-- Description for enabling to send user statistics for development only diagnostics -->
+ <string name="prefs_description_log">Help improve this input method editor by automatically sending usage statistics and crash reports</string>
<!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
<string name="keyboard_layout">Keyboard theme</string>
@@ -422,12 +422,12 @@
<!-- Title of an option for usability study mode -->
<string name="prefs_usability_study_mode">Usability study mode</string>
- <!-- Title of the settings for key long press delay -->
- <string name="prefs_key_longpress_timeout_settings">Key long press delay settings</string>
- <!-- Title of the settings for keypress vibration duration -->
- <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration settings</string>
- <!-- Title of the settings for keypress sound volume -->
- <string name="prefs_keypress_sound_volume_settings">Keypress sound volume settings</string>
+ <!-- Title of the settings for key long press delay [CHAR LIMIT=30] -->
+ <string name="prefs_key_longpress_timeout_settings">Key long press delay</string>
+ <!-- Title of the settings for keypress vibration duration [CHAR LIMIT=30] -->
+ <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration</string>
+ <!-- Title of the settings for keypress sound volume [CHAR LIMIT=30] -->
+ <string name="prefs_keypress_sound_volume_settings">Keypress sound volume</string>
<!-- Title of the settings for reading an external dictionary file -->
<string name="prefs_read_external_dictionary">Read external dictionary file</string>
<!-- Message to show when there are no files to install as an external dictionary [CHAR LIMIT=100] -->
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
index b047fe038..e3e6d39e4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java
@@ -44,6 +44,7 @@ final class GesturePreviewTrail {
// The wall time of the zero value in {@link #mEventTimes}
private long mCurrentTimeBase;
private int mTrailStartIndex;
+ private int mLastInterpolatedDrawIndex;
static final class Params {
public final int mTrailColor;
@@ -96,6 +97,17 @@ final class GesturePreviewTrail {
}
final int[] eventTimes = mEventTimes.getPrimitiveArray();
final int strokeId = stroke.getGestureStrokeId();
+ // Because interpolation algorithm in {@link GestureStrokeWithPreviewPoints} can't determine
+ // the interpolated points in the last segment of gesture stroke, it may need recalculation
+ // of interpolation when new segments are added to the stroke.
+ // {@link #mLastInterpolatedDrawIndex} holds the start index of the last segment. It may
+ // be updated by the interpolation
+ // {@link GestureStrokeWithPreviewPoints#interpolatePreviewStroke}
+ // or by animation {@link #drawGestureTrail(Canvas,Paint,Rect,Params)} below.
+ final int lastInterpolatedIndex = (strokeId == mCurrentStrokeId)
+ ? mLastInterpolatedDrawIndex : trailSize;
+ mLastInterpolatedDrawIndex = stroke.interpolateStrokeAndReturnStartIndexOfLastSegment(
+ lastInterpolatedIndex, mEventTimes, mXCoordinates, mYCoordinates);
if (strokeId != mCurrentStrokeId) {
final int elapsedTime = (int)(downTime - mCurrentTimeBase);
for (int i = mTrailStartIndex; i < trailSize; i++) {
@@ -216,6 +228,10 @@ final class GesturePreviewTrail {
System.arraycopy(eventTimes, startIndex, eventTimes, 0, newSize);
System.arraycopy(xCoords, startIndex, xCoords, 0, newSize);
System.arraycopy(yCoords, startIndex, yCoords, 0, newSize);
+ // The start index of the last segment of the stroke
+ // {@link mLastInterpolatedDrawIndex} should also be updated because all array
+ // elements have just been shifted for compaction.
+ mLastInterpolatedDrawIndex = Math.max(mLastInterpolatedDrawIndex - startIndex, 0);
}
mEventTimes.setLength(newSize);
mXCoordinates.setLength(newSize);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
index fc81410ff..3315954c1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java
@@ -21,19 +21,32 @@ import com.android.inputmethod.latin.ResizableIntArray;
public final class GestureStrokeWithPreviewPoints extends GestureStroke {
public static final int PREVIEW_CAPACITY = 256;
+ private static final boolean ENABLE_INTERPOLATION = true;
+
private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY);
private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
private int mStrokeId;
private int mLastPreviewSize;
+ private final HermiteInterpolator mInterpolator = new HermiteInterpolator();
+ private int mLastInterpolatedPreviewIndex;
- private int mMinPreviewSampleLengthSquare;
+ private int mMinPreviewSamplingDistanceSquared;
private int mLastX;
private int mLastY;
+ private double mMinPreviewSamplingDistance;
+ private double mDistanceFromLastSample;
- // TODO: Move this to resource.
- private static final float MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH = 0.1f;
+ // TODO: Move these constants to resource.
+ // The minimum linear distance between sample points for preview in keyWidth unit.
+ private static final float MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH = 0.1f;
+ // The minimum trail distance between sample points for preview in keyWidth unit when using
+ // interpolation.
+ private static final float MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH_WITH_INTERPOLATION = 0.2f;
+ // The angular threshold to use interpolation in radian. PI/12 is 15 degree.
+ private static final double INTERPOLATION_ANGULAR_THRESHOLD = Math.PI / 12.0d;
+ private static final int MAX_INTERPOLATION_PARTITION = 4;
public GestureStrokeWithPreviewPoints(final int pointerId, final GestureStrokeParams params) {
super(pointerId, params);
@@ -44,6 +57,7 @@ public final class GestureStrokeWithPreviewPoints extends GestureStroke {
super.reset();
mStrokeId++;
mLastPreviewSize = 0;
+ mLastInterpolatedPreviewIndex = 0;
mPreviewEventTimes.setLength(0);
mPreviewXCoordinates.setLength(0);
mPreviewYCoordinates.setLength(0);
@@ -53,35 +67,49 @@ public final class GestureStrokeWithPreviewPoints extends GestureStroke {
return mStrokeId;
}
- public int getGestureStrokePreviewSize() {
- return mPreviewEventTimes.getLength();
- }
-
@Override
public void setKeyboardGeometry(final int keyWidth, final int keyboardHeight) {
super.setKeyboardGeometry(keyWidth, keyboardHeight);
- final float sampleLength = keyWidth * MIN_PREVIEW_SAMPLE_LENGTH_RATIO_TO_KEY_WIDTH;
- mMinPreviewSampleLengthSquare = (int)(sampleLength * sampleLength);
+ final float samplingRatioToKeyWidth = ENABLE_INTERPOLATION
+ ? MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH_WITH_INTERPOLATION
+ : MIN_PREVIEW_SAMPLING_RATIO_TO_KEY_WIDTH;
+ mMinPreviewSamplingDistance = keyWidth * samplingRatioToKeyWidth;
+ mMinPreviewSamplingDistanceSquared = (int)(
+ mMinPreviewSamplingDistance * mMinPreviewSamplingDistance);
}
- private boolean needsSampling(final int x, final int y) {
+ private boolean needsSampling(final int x, final int y, final boolean isMajorEvent) {
+ if (ENABLE_INTERPOLATION) {
+ mDistanceFromLastSample += Math.hypot(x - mLastX, y - mLastY);
+ mLastX = x;
+ mLastY = y;
+ if (mDistanceFromLastSample >= mMinPreviewSamplingDistance) {
+ mDistanceFromLastSample = 0.0d;
+ return true;
+ }
+ return false;
+ }
+
final int dx = x - mLastX;
final int dy = y - mLastY;
- return dx * dx + dy * dy >= mMinPreviewSampleLengthSquare;
+ if (isMajorEvent || dx * dx + dy * dy >= mMinPreviewSamplingDistanceSquared) {
+ mLastX = x;
+ mLastY = y;
+ return true;
+ }
+ return false;
}
@Override
public boolean addPointOnKeyboard(final int x, final int y, final int time,
final boolean isMajorEvent) {
- final boolean onValidArea = super.addPointOnKeyboard(x, y, time, isMajorEvent);
- if (isMajorEvent || needsSampling(x, y)) {
+ if (needsSampling(x, y, isMajorEvent)) {
mPreviewEventTimes.add(time);
mPreviewXCoordinates.add(x);
mPreviewYCoordinates.add(y);
- mLastX = x;
- mLastY = y;
}
- return onValidArea;
+ return super.addPointOnKeyboard(x, y, time, isMajorEvent);
+
}
public void appendPreviewStroke(final ResizableIntArray eventTimes,
@@ -95,4 +123,82 @@ public final class GestureStrokeWithPreviewPoints extends GestureStroke {
yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length);
mLastPreviewSize = mPreviewEventTimes.getLength();
}
+
+ /**
+ * Calculate interpolated points between the last interpolated point and the end of the trail.
+ * And return the start index of the last interpolated segment of input arrays because it
+ * may need to recalculate the interpolated points in the segment if further segments are
+ * added to this stroke.
+ *
+ * @param lastInterpolatedIndex the start index of the last interpolated segment of
+ * <code>eventTimes</code>, <code>xCoords</code>, and <code>yCoords</code>.
+ * @param eventTimes the event time array of gesture preview trail to be drawn.
+ * @param xCoords the x-coordinates array of gesture preview trail to be drawn.
+ * @param yCoords the y-coordinates array of gesture preview trail to be drawn.
+ * @return the start index of the last interpolated segment of input arrays.
+ */
+ public int interpolateStrokeAndReturnStartIndexOfLastSegment(final int lastInterpolatedIndex,
+ final ResizableIntArray eventTimes, final ResizableIntArray xCoords,
+ final ResizableIntArray yCoords) {
+ if (!ENABLE_INTERPOLATION) {
+ return lastInterpolatedIndex;
+ }
+ final int size = mPreviewEventTimes.getLength();
+ final int[] pt = mPreviewEventTimes.getPrimitiveArray();
+ final int[] px = mPreviewXCoordinates.getPrimitiveArray();
+ final int[] py = mPreviewYCoordinates.getPrimitiveArray();
+ mInterpolator.reset(px, py, 0, size);
+ // The last segment of gesture stroke needs to be interpolated again because the slope of
+ // the tangent at the last point isn't determined.
+ int lastInterpolatedDrawIndex = lastInterpolatedIndex;
+ int d1 = lastInterpolatedIndex;
+ for (int p2 = mLastInterpolatedPreviewIndex + 1; p2 < size; p2++) {
+ final int p1 = p2 - 1;
+ final int p0 = p1 - 1;
+ final int p3 = p2 + 1;
+ mLastInterpolatedPreviewIndex = p1;
+ lastInterpolatedDrawIndex = d1;
+ mInterpolator.setInterval(p0, p1, p2, p3);
+ final double m1 = Math.atan2(mInterpolator.mSlope1Y, mInterpolator.mSlope1X);
+ final double m2 = Math.atan2(mInterpolator.mSlope2Y, mInterpolator.mSlope2X);
+ final double dm = Math.abs(angularDiff(m2, m1));
+ final int partition = Math.min((int)Math.ceil(dm / INTERPOLATION_ANGULAR_THRESHOLD),
+ MAX_INTERPOLATION_PARTITION);
+ final int t1 = eventTimes.get(d1);
+ final int dt = pt[p2] - pt[p1];
+ d1++;
+ for (int i = 1; i < partition; i++) {
+ final float t = i / (float)partition;
+ mInterpolator.interpolate(t);
+ eventTimes.add(d1, (int)(dt * t) + t1);
+ xCoords.add(d1, (int)mInterpolator.mInterpolatedX);
+ yCoords.add(d1, (int)mInterpolator.mInterpolatedY);
+ d1++;
+ }
+ eventTimes.add(d1, pt[p2]);
+ xCoords.add(d1, px[p2]);
+ yCoords.add(d1, py[p2]);
+ }
+ return lastInterpolatedDrawIndex;
+ }
+
+ private static final double TWO_PI = Math.PI * 2.0d;
+
+ /**
+ * Calculate the angular of rotation from <code>a0</code> to <code>a1</code>.
+ *
+ * @param a1 the angular to which the rotation ends.
+ * @param a0 the angular from which the rotation starts.
+ * @return the angular rotation value from a0 to a1, normalized to [-PI, +PI].
+ */
+ private static double angularDiff(final double a1, final double a0) {
+ double deltaAngle = a1 - a0;
+ while (deltaAngle > Math.PI) {
+ deltaAngle -= TWO_PI;
+ }
+ while (deltaAngle < -Math.PI) {
+ deltaAngle += TWO_PI;
+ }
+ return deltaAngle;
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
new file mode 100644
index 000000000..0ec8153f5
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
@@ -0,0 +1,166 @@
+/*
+ * 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.internal;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+/**
+ * Interpolates XY-coordinates using Cubic Hermite Curve.
+ */
+public final class HermiteInterpolator {
+ private int[] mXCoords;
+ private int[] mYCoords;
+ private int mMinPos;
+ private int mMaxPos;
+
+ // Working variable to calculate interpolated value.
+ /** The coordinates of the start point of the interval. */
+ public int mP1X, mP1Y;
+ /** The coordinates of the end point of the interval. */
+ public int mP2X, mP2Y;
+ /** The slope of the tangent at the start point. */
+ public float mSlope1X, mSlope1Y;
+ /** The slope of the tangent at the end point. */
+ public float mSlope2X, mSlope2Y;
+ /** The interpolated coordinates.
+ * The return variables of {@link #interpolate(float)} to avoid instantiations.
+ */
+ public float mInterpolatedX, mInterpolatedY;
+
+ public HermiteInterpolator() {
+ // Nothing to do with here.
+ }
+
+ /**
+ * Reset this interpolator to point XY-coordinates data.
+ * @param xCoords the array of x-coordinates. Valid data are in left-open interval
+ * <code>[minPos, maxPos)</code>.
+ * @param yCoords the array of y-coordinates. Valid data are in left-open interval
+ * <code>[minPos, maxPos)</code>.
+ * @param minPos the minimum index of left-open interval of valid data.
+ * @param maxPos the maximum index of left-open interval of valid data.
+ */
+ @UsedForTesting
+ public void reset(final int[] xCoords, final int[] yCoords, final int minPos,
+ final int maxPos) {
+ mXCoords = xCoords;
+ mYCoords = yCoords;
+ mMinPos = minPos;
+ mMaxPos = maxPos;
+ }
+
+ /**
+ * Set interpolation interval.
+ * <p>
+ * The start and end coordinates of the interval will be set in {@link #mP1X}, {@link #mP1Y},
+ * {@link #mP2X}, and {@link #mP2Y}. The slope of the tangents at start and end points will be
+ * set in {@link #mSlope1X}, {@link #mSlope1Y}, {@link #mSlope2X}, and {@link #mSlope2Y}.
+ *
+ * @param p0 the index just before interpolation interval. If <code>p1</code> points the start
+ * of valid points, <code>p0</code> must be less than <code>minPos</code> of
+ * {@link #reset(int[],int[],int,int)}.
+ * @param p1 the start index of interpolation interval.
+ * @param p2 the end index of interpolation interval.
+ * @param p3 the index just after interpolation interval. If <code>p2</code> points the end of
+ * valid points, <code>p3</code> must be equal or greater than <code>maxPos</code> of
+ * {@link #reset(int[],int[],int,int)}.
+ */
+ @UsedForTesting
+ public void setInterval(final int p0, final int p1, final int p2, final int p3) {
+ mP1X = mXCoords[p1];
+ mP1Y = mYCoords[p1];
+ mP2X = mXCoords[p2];
+ mP2Y = mYCoords[p2];
+ // A(ax,ay) is the vector p1->p2.
+ final int ax = mP2X - mP1X;
+ final int ay = mP2Y - mP1Y;
+
+ // Calculate the slope of the tangent at p1.
+ if (p0 >= mMinPos) {
+ // p1 has previous valid point p0.
+ // The slope of the tangent is half of the vector p0->p2.
+ mSlope1X = (mP2X - mXCoords[p0]) / 2.0f;
+ mSlope1Y = (mP2Y - mYCoords[p0]) / 2.0f;
+ } else if (p3 < mMaxPos) {
+ // p1 has no previous valid point, but p2 has next valid point p3.
+ // B(bx,by) is the slope vector of the tangent at p2.
+ final float bx = (mXCoords[p3] - mP1X) / 2.0f;
+ final float by = (mYCoords[p3] - mP1Y) / 2.0f;
+ final float crossProdAB = ax * by - ay * bx;
+ final float dotProdAB = ax * bx + ay * by;
+ final float normASquare = ax * ax + ay * ay;
+ final float invHalfNormASquare = 1.0f / normASquare / 2.0f;
+ // The slope of the tangent is the mirror image of vector B to vector A.
+ mSlope1X = invHalfNormASquare * (dotProdAB * ax + crossProdAB * ay);
+ mSlope1Y = invHalfNormASquare * (dotProdAB * ay - crossProdAB * ax);
+ } else {
+ // p1 and p2 have no previous valid point. (Interval has only point p1 and p2)
+ mSlope1X = ax;
+ mSlope1Y = ay;
+ }
+
+ // Calculate the slope of the tangent at p2.
+ if (p3 < mMaxPos) {
+ // p2 has next valid point p3.
+ // The slope of the tangent is half of the vector p1->p3.
+ mSlope2X = (mXCoords[p3] - mP1X) / 2.0f;
+ mSlope2Y = (mYCoords[p3] - mP1Y) / 2.0f;
+ } else if (p0 >= mMinPos) {
+ // p2 has no next valid point, but p1 has previous valid point p0.
+ // B(bx,by) is the slope vector of the tangent at p1.
+ final float bx = (mP2X - mXCoords[p0]) / 2.0f;
+ final float by = (mP2Y - mYCoords[p0]) / 2.0f;
+ final float crossProdAB = ax * by - ay * bx;
+ final float dotProdAB = ax * bx + ay * by;
+ final float normASquare = ax * ax + ay * ay;
+ final float invHalfNormASquare = 1.0f / normASquare / 2.0f;
+ // The slope of the tangent is the mirror image of vector B to vector A.
+ mSlope2X = invHalfNormASquare * (dotProdAB * ax + crossProdAB * ay);
+ mSlope2Y = invHalfNormASquare * (dotProdAB * ay - crossProdAB * ax);
+ } else {
+ // p1 and p2 has no previous valid point. (Interval has only point p1 and p2)
+ mSlope2X = ax;
+ mSlope2Y = ay;
+ }
+ }
+
+ /**
+ * Calculate interpolation value at <code>t</code> in unit interval <code>[0,1]</code>.
+ * <p>
+ * On the unit interval [0,1], given a starting point p1 at t=0 and an ending point p2 at t=1
+ * with the slope of the tangent m1 at p1 and m2 at p2, the polynomial of cubic Hermite curve
+ * can be defined by
+ * p(t) = (1+2t)(1-t)(1-t)*p1 + t(1-t)(1-t)*m1 + (3-2t)t^2*p2 + (t-1)t^2*m2
+ * where t is an element of [0,1].
+ * <p>
+ * The interpolated XY-coordinates will be set in {@link #mInterpolatedX} and
+ * {@link #mInterpolatedY}.
+ *
+ * @param t the interpolation parameter. The value must be in close interval <code>[0,1]</code>.
+ */
+ @UsedForTesting
+ public void interpolate(final float t) {
+ final float omt = 1.0f - t;
+ final float tm2 = 2.0f * t;
+ final float k1 = 1.0f + tm2;
+ final float k2 = 3.0f - tm2;
+ final float omt2 = omt * omt;
+ final float t2 = t * t;
+ mInterpolatedX = (k1 * mP1X + t * mSlope1X) * omt2 + (k2 * mP2X - omt * mSlope2X) * t2;
+ mInterpolatedY = (k1 * mP1Y + t * mSlope1Y) * omt2 + (k2 * mP2Y - omt * mSlope2Y) * t2;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 92b68dcd7..3262a9a10 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1143,11 +1143,11 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (!mWordComposer.isComposingWord()) return;
final String typedWord = mWordComposer.getTypedWord();
if (typedWord.length() > 0) {
- commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
- separatorString);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.getInstance().onWordFinished(typedWord, mWordComposer.isBatchMode());
}
+ commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
+ separatorString);
}
}
@@ -1905,7 +1905,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private boolean handleSeparator(final int primaryCode, final int x, final int y,
final int spaceState) {
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.recordTimeForLogUnitSplit();
ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
}
boolean didAutoCorrect = false;
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 90c3fcdd2..dcb514a5e 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -22,6 +22,10 @@ import java.util.ArrayList;
import java.util.Locale;
public final class StringUtils {
+ public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
+ public static final int CAPITALIZE_FIRST = 1; // First only
+ public static final int CAPITALIZE_ALL = 2; // All caps
+
private StringUtils() {
// This utility class is not publicly instantiable.
}
@@ -171,4 +175,31 @@ public final class StringUtils {
}
return list.toArray(new String[list.size()]);
}
+
+ // This method assumes the text is not empty or null.
+ public static int getCapitalizationType(final String text) {
+ // If the first char is not uppercase, then the word is either all lower case or
+ // camel case, and in either case we return CAPITALIZE_NONE.
+ if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
+ final int len = text.length();
+ int capsCount = 1;
+ int letterCount = 1;
+ for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
+ if (1 != capsCount && letterCount != capsCount) break;
+ final int codePoint = text.codePointAt(i);
+ if (Character.isUpperCase(codePoint)) {
+ ++capsCount;
+ ++letterCount;
+ } else if (Character.isLetter(codePoint)) {
+ // We need to discount non-letters since they may not be upper-case, but may
+ // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
+ ++letterCount;
+ }
+ }
+ // We know the first char is upper case. So we want to test if either every letter other
+ // than the first is lower case, or if they are all upper case. If the string is exactly
+ // one char long, then we will arrive here with letterCount 1, and this is correct, too.
+ if (1 == capsCount) return CAPITALIZE_FIRST;
+ return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
index 699e47b6a..dc937fb25 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -28,5 +28,5 @@ public final class ProductionFlag {
// USES_DEVELOPMENT_ONLY_DIAGNOSTICS must be false for any production build.
public static final boolean USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG = false;
- public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = true;
+ public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 38a26486d..8d3b062ff 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -58,10 +58,6 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
- public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
- public static final int CAPITALIZE_FIRST = 1; // First only
- public static final int CAPITALIZE_ALL = 2; // All caps
-
private final static String[] EMPTY_STRING_ARRAY = new String[0];
private Map<String, DictionaryPool> mDictionaryPools = CollectionUtils.newSynchronizedTreeMap();
private Map<String, UserBinaryDictionary> mUserDictionaries =
@@ -325,13 +321,13 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
}
Collections.reverse(mSuggestions);
StringUtils.removeDupes(mSuggestions);
- if (CAPITALIZE_ALL == capitalizeType) {
+ if (StringUtils.CAPITALIZE_ALL == capitalizeType) {
for (int i = 0; i < mSuggestions.size(); ++i) {
// get(i) returns a CharSequence which is actually a String so .toString()
// should return the same object.
mSuggestions.set(i, mSuggestions.get(i).toString().toUpperCase(locale));
}
- } else if (CAPITALIZE_FIRST == capitalizeType) {
+ } else if (StringUtils.CAPITALIZE_FIRST == capitalizeType) {
for (int i = 0; i < mSuggestions.size(); ++i) {
// Likewise
mSuggestions.set(i, StringUtils.toTitleCase(
@@ -438,31 +434,4 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
}
return new DictAndProximity(dictionaryCollection, proximityInfo);
}
-
- // This method assumes the text is not empty or null.
- public static int getCapitalizationType(String text) {
- // If the first char is not uppercase, then the word is either all lower case,
- // and in either case we return CAPITALIZE_NONE.
- if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
- final int len = text.length();
- int capsCount = 1;
- int letterCount = 1;
- for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
- if (1 != capsCount && letterCount != capsCount) break;
- final int codePoint = text.codePointAt(i);
- if (Character.isUpperCase(codePoint)) {
- ++capsCount;
- ++letterCount;
- } else if (Character.isLetter(codePoint)) {
- // We need to discount non-letters since they may not be upper-case, but may
- // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
- ++letterCount;
- }
- }
- // We know the first char is upper case. So we want to test if either every letter other
- // than the first is lower case, or if they are all upper case. If the string is exactly
- // one char long, then we will arrive here with letterCount 1, and this is correct, too.
- if (1 == capsCount) return CAPITALIZE_FIRST;
- return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
- }
}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 4f86a3175..b15063235 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -150,7 +150,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
// Greek letters are either in the 370~3FF range (Greek & Coptic), or in the
// 1F00~1FFF range (Greek extended). Our dictionary contains both sort of characters.
// Our dictionary also contains a few words with 0xF2; it would be best to check
- // if that's correct, but a Google search does return results for these words so
+ // if that's correct, but a web search does return results for these words so
// they are probably okay.
return (codePoint >= 0x370 && codePoint <= 0x3FF)
|| (codePoint >= 0x1F00 && codePoint <= 0x1FFF)
@@ -214,14 +214,14 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
// If the word is in there as is, then it's in the dictionary. If not, we'll test lower
// case versions, but only if the word is not already all-lower case or mixed case.
if (dict.isValidWord(text)) return true;
- if (AndroidSpellCheckerService.CAPITALIZE_NONE == capitalizeType) return false;
+ if (StringUtils.CAPITALIZE_NONE == capitalizeType) return false;
// If we come here, we have a capitalized word (either First- or All-).
// Downcase the word and look it up again. If the word is only capitalized, we
// tested all possibilities, so if it's still negative we can return false.
final String lowerCaseText = text.toLowerCase(mLocale);
if (dict.isValidWord(lowerCaseText)) return true;
- if (AndroidSpellCheckerService.CAPITALIZE_FIRST == capitalizeType) return false;
+ if (StringUtils.CAPITALIZE_FIRST == capitalizeType) return false;
// If the lower case version is not in the dictionary, it's still possible
// that we have an all-caps version of a word that needs to be capitalized
@@ -296,7 +296,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
}
}
- final int capitalizeType = AndroidSpellCheckerService.getCapitalizationType(text);
+ final int capitalizeType = StringUtils.getCapitalizationType(text);
boolean isInDict = true;
DictAndProximity dictInfo = null;
try {
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 6e486ce70..fa124f3ba 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -1635,8 +1635,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final String scrubbedAutoCorrection = scrubDigitsFromString(autoCorrection);
final ResearchLogger researchLogger = getInstance();
researchLogger.mCurrentLogUnit.initializeSuggestions(suggestedWords);
- researchLogger.commitCurrentLogUnitAsWord(scrubbedAutoCorrection, Long.MAX_VALUE,
- isBatchMode);
+ researchLogger.onWordFinished(scrubbedAutoCorrection, isBatchMode);
// Add the autocorrection logStatement at the end of the logUnit for the committed word.
// We have to do this after calling commitCurrentLogUnitAsWord, because it may split the
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 423c24e88..cbe9515fe 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -24,20 +24,14 @@ FLAG_DO_PROFILE ?= false
include $(CLEAR_VARS)
LATIN_IME_SRC_DIR := src
-LATIN_IME_SRC_FULLPATH_DIR := $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
-LOCAL_C_INCLUDES += \
- $(LATIN_IME_SRC_FULLPATH_DIR) \
- $(LATIN_IME_SRC_FULLPATH_DIR)/suggest \
- $(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/dicnode \
- $(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/policy \
- $(LATIN_IME_SRC_FULLPATH_DIR)/suggest/core/session
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \
-Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls -Wno-system-headers
ifeq ($(TARGET_ARCH), arm)
-ifneq ($(TARGET_GCC_VERSION), 4.7)
+ifeq ($(TARGET_GCC_VERSION), 4.6)
LOCAL_CFLAGS += -Winline
endif # TARGET_GCC_VERSION
endif # TARGET_ARCH
@@ -58,19 +52,27 @@ LATIN_IME_CORE_SRC_FILES := \
correction.cpp \
dictionary.cpp \
dic_traverse_wrapper.cpp \
+ digraph_utils.cpp \
proximity_info.cpp \
proximity_info_params.cpp \
proximity_info_state.cpp \
proximity_info_state_utils.cpp \
unigram_dictionary.cpp \
words_priority_queue.cpp \
- suggest/core/dicnode/dic_node.cpp \
- suggest/core/dicnode/dic_nodes_cache.cpp \
- suggest/core/dicnode/dic_node_utils.cpp \
+ suggest/core/suggest.cpp \
+ $(addprefix suggest/core/dicnode/, \
+ dic_node.cpp \
+ dic_node_utils.cpp \
+ dic_nodes_cache.cpp) \
suggest/core/policy/weighting.cpp \
suggest/core/session/dic_traverse_session.cpp \
- suggest/gesture_suggest.cpp \
- suggest/typing_suggest.cpp
+ suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
+ $(addprefix suggest/policyimpl/typing/, \
+ scoring_params.cpp \
+ typing_scoring.cpp \
+ typing_suggest_policy.cpp \
+ typing_traversal.cpp \
+ typing_weighting.cpp)
LOCAL_SRC_FILES := \
$(LATIN_IME_JNI_SRC_FILES) \
@@ -125,6 +127,4 @@ include $(BUILD_SHARED_LIBRARY)
#################### Clean up the tmp vars
LATIN_IME_CORE_SRC_FILES :=
LATIN_IME_JNI_SRC_FILES :=
-LATIN_IME_GESTURE_IMPL_SRC_FILES :=
LATIN_IME_SRC_DIR :=
-LATIN_IME_SRC_FULLPATH_DIR :=
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index 1ea204102..8e5c50880 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -16,12 +16,12 @@
#define LOG_TAG "LatinIME: jni"
+#include "jni_common.h"
+
#include "com_android_inputmethod_keyboard_ProximityInfo.h"
#include "com_android_inputmethod_latin_BinaryDictionary.h"
#include "com_android_inputmethod_latin_DicTraverseSession.h"
#include "defines.h"
-#include "jni.h"
-#include "jni_common.h"
/*
* Returns the JNI version on success, -1 on failure.
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 43e59a262..92890383a 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -39,7 +39,7 @@ BigramDictionary::~BigramDictionary() {
void BigramDictionary::addWordBigram(int *word, int length, int probability, int *bigramProbability,
int *bigramCodePoints, int *outputTypes) const {
word[length] = 0;
- if (DEBUG_DICT) {
+ if (DEBUG_DICT_FULL) {
#ifdef FLAG_DBG
char s[length + 1];
for (int i = 0; i <= length; i++) s[i] = static_cast<char>(word[i]);
@@ -57,7 +57,7 @@ void BigramDictionary::addWordBigram(int *word, int length, int probability, int
}
insertAt++;
}
- if (DEBUG_DICT) {
+ if (DEBUG_DICT_FULL) {
AKLOGI("Bigram: InsertAt -> %d MAX_RESULTS: %d", insertAt, MAX_RESULTS);
}
if (insertAt >= MAX_RESULTS) {
@@ -76,7 +76,7 @@ void BigramDictionary::addWordBigram(int *word, int length, int probability, int
*dest++ = *word++;
}
*dest = 0; // NULL terminate
- if (DEBUG_DICT) {
+ if (DEBUG_DICT_FULL) {
AKLOGI("Bigram: Added word at %d", insertAt);
}
}
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 671507ee0..76234f840 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -954,7 +954,13 @@ inline static int editDistanceInternal(int *editDistanceTable, const int *before
// In dictionary.cpp, getSuggestion() method,
-// suggestion scores are computed using the below formula.
+// When USE_SUGGEST_INTERFACE_FOR_TYPING is true:
+// SUGGEST_INTERFACE_OUTPUT_SCALE was multiplied to the original suggestion scores to convert
+// them to integers.
+// score = (int)((original score) * SUGGEST_INTERFACE_OUTPUT_SCALE)
+// Undo the scaling here to recover the original score.
+// normalizedScore = ((float)score) / SUGGEST_INTERFACE_OUTPUT_SCALE
+// Otherwise: suggestion scores are computed using the below formula.
// original score
// := powf(mTypedLetterMultiplier (this is defined 2),
// (the number of matched characters between typed word and suggested word))
@@ -991,16 +997,20 @@ inline static int editDistanceInternal(int *editDistanceTable, const int *before
return 0.0f;
}
+ // add a weight based on edit distance.
+ // distance <= max(afterLength, beforeLength) == afterLength,
+ // so, 0 <= distance / afterLength <= 1
+ const float weight = 1.0f - static_cast<float>(distance) / static_cast<float>(afterLength);
+
+ if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
+ return (static_cast<float>(score) / SUGGEST_INTERFACE_OUTPUT_SCALE) * weight;
+ }
const float maxScore = score >= S_INT_MAX ? static_cast<float>(S_INT_MAX)
: static_cast<float>(MAX_INITIAL_SCORE)
* powf(static_cast<float>(TYPED_LETTER_MULTIPLIER),
static_cast<float>(min(beforeLength, afterLength - spaceCount)))
* static_cast<float>(FULL_WORD_MULTIPLIER);
- // add a weight based on edit distance.
- // distance <= max(afterLength, beforeLength) == afterLength,
- // so, 0 <= distance / afterLength <= 1
- const float weight = 1.0f - static_cast<float>(distance) / static_cast<float>(afterLength);
return (static_cast<float>(score) / maxScore) * weight;
}
} // namespace latinime
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index f0d62102f..a9e9b48a6 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -307,7 +307,7 @@ inline void Correction::startToTraverseAllNodes() {
mNeedsToTraverseAllNodes = true;
}
-inline bool Correction::isSingleQuote(const int c) {
+AK_FORCE_INLINE bool Correction::isSingleQuote(const int c) {
const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex);
return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE);
}
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 6e098157d..a45691261 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -287,6 +287,7 @@ static inline void prof_out(void) {
#define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true
#define SUGGEST_MULTIPLE_WORDS true
+#define USE_SUGGEST_INTERFACE_FOR_TYPING true
#define SUGGEST_INTERFACE_OUTPUT_SCALE 1000000.0f
// The following "rate"s are used as a multiplier before dividing by 100, so they are in percent.
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 6deab36b6..ed6ddb517 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -16,14 +16,18 @@
#define LOG_TAG "LatinIME: dictionary.cpp"
+#include "dictionary.h"
+
+#include <map> // TODO: remove
#include <stdint.h>
#include "bigram_dictionary.h"
#include "binary_format.h"
#include "defines.h"
-#include "dictionary.h"
#include "dic_traverse_wrapper.h"
-#include "gesture_suggest.h"
+#include "suggest/core/suggest.h"
+#include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
+#include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
#include "unigram_dictionary.h"
namespace latinime {
@@ -34,13 +38,15 @@ Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust)
mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust),
mUnigramDictionary(new UnigramDictionary(mOffsetDict, BinaryFormat::getFlags(mDict))),
mBigramDictionary(new BigramDictionary(mOffsetDict)),
- mGestureSuggest(new GestureSuggest()) {
+ mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
+ mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
}
Dictionary::~Dictionary() {
delete mUnigramDictionary;
delete mBigramDictionary;
delete mGestureSuggest;
+ delete mTypingSuggest;
}
int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession,
@@ -60,14 +66,26 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi
}
return result;
} else {
- std::map<int, int> bigramMap;
- uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
- mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
- prevWordLength, &bigramMap, bigramFilter);
- result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
- inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance, outWords,
- frequencies, outputTypes);
- return result;
+ if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
+ DicTraverseWrapper::initDicTraverseSession(
+ traverseSession, this, prevWordCodePoints, prevWordLength);
+ result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
+ ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
+ outWords, frequencies, spaceIndices, outputTypes);
+ if (DEBUG_DICT) {
+ DUMP_RESULT(outWords, frequencies);
+ }
+ return result;
+ } else {
+ std::map<int, int> bigramMap;
+ uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
+ mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
+ prevWordLength, &bigramMap, bigramFilter);
+ result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
+ inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance,
+ outWords, frequencies, outputTypes);
+ return result;
+ }
}
}
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index 449b95ab6..8c6a7de52 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -79,6 +79,7 @@ class Dictionary {
const UnigramDictionary *mUnigramDictionary;
const BigramDictionary *mBigramDictionary;
SuggestInterface *mGestureSuggest;
+ SuggestInterface *mTypingSuggest;
};
} // namespace latinime
#endif // LATINIME_DICTIONARY_H
diff --git a/native/jni/src/digraph_utils.cpp b/native/jni/src/digraph_utils.cpp
new file mode 100644
index 000000000..8781c5077
--- /dev/null
+++ b/native/jni/src/digraph_utils.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include "binary_format.h"
+#include "defines.h"
+#include "digraph_utils.h"
+
+namespace latinime {
+
+const DigraphUtils::digraph_t DigraphUtils::GERMAN_UMLAUT_DIGRAPHS[] =
+ { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS
+ { 'o', 'e', 0x00F6 }, // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS
+ { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS
+const DigraphUtils::digraph_t DigraphUtils::FRENCH_LIGATURES_DIGRAPHS[] =
+ { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE
+ { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE
+
+/* static */ bool DigraphUtils::hasDigraphForCodePoint(
+ const int dictFlags, const int compositeGlyphCodePoint) {
+ if (DigraphUtils::getDigraphForCodePoint(dictFlags, compositeGlyphCodePoint)) {
+ return true;
+ }
+ return false;
+}
+
+// Retrieves the set of all digraphs associated with the given dictionary.
+// Returns the size of the digraph array, or 0 if none exist.
+/* static */ int DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(
+ const int dictFlags, const DigraphUtils::digraph_t **digraphs) {
+ if (BinaryFormat::REQUIRES_GERMAN_UMLAUT_PROCESSING & dictFlags) {
+ *digraphs = DigraphUtils::GERMAN_UMLAUT_DIGRAPHS;
+ return NELEMS(DigraphUtils::GERMAN_UMLAUT_DIGRAPHS);
+ }
+ if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & dictFlags) {
+ *digraphs = DigraphUtils::FRENCH_LIGATURES_DIGRAPHS;
+ return NELEMS(DigraphUtils::FRENCH_LIGATURES_DIGRAPHS);
+ }
+ return 0;
+}
+
+// Returns the digraph codepoint for the given composite glyph codepoint and digraph codepoint index
+// (which specifies the first or second codepoint in the digraph).
+/* static */ int DigraphUtils::getDigraphCodePointForIndex(const int dictFlags,
+ const int compositeGlyphCodePoint, const DigraphCodePointIndex digraphCodePointIndex) {
+ if (digraphCodePointIndex == NOT_A_DIGRAPH_INDEX) {
+ return NOT_A_CODE_POINT;
+ }
+ const DigraphUtils::digraph_t *digraph =
+ DigraphUtils::getDigraphForCodePoint(dictFlags, compositeGlyphCodePoint);
+ if (!digraph) {
+ return NOT_A_CODE_POINT;
+ }
+ if (digraphCodePointIndex == FIRST_DIGRAPH_CODEPOINT) {
+ return digraph->first;
+ } else if (digraphCodePointIndex == SECOND_DIGRAPH_CODEPOINT) {
+ return digraph->second;
+ }
+ ASSERT(false);
+ return NOT_A_CODE_POINT;
+}
+
+/**
+ * Returns the digraph for the input composite glyph codepoint, or 0 if none exists.
+ * dictFlags: the dictionary flags needed to determine which digraphs are supported.
+ * compositeGlyphCodePoint: the method returns the digraph corresponding to this codepoint.
+ */
+/* static */ const DigraphUtils::digraph_t *DigraphUtils::getDigraphForCodePoint(
+ const int dictFlags, const int compositeGlyphCodePoint) {
+ const DigraphUtils::digraph_t *digraphs = 0;
+ const int digraphsSize =
+ DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(dictFlags, &digraphs);
+ for (int i = 0; i < digraphsSize; i++) {
+ if (digraphs[i].compositeGlyph == compositeGlyphCodePoint) {
+ return &digraphs[i];
+ }
+ }
+ return 0;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/digraph_utils.h b/native/jni/src/digraph_utils.h
new file mode 100644
index 000000000..6e364b67a
--- /dev/null
+++ b/native/jni/src/digraph_utils.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef DIGRAPH_UTILS_H
+#define DIGRAPH_UTILS_H
+
+namespace latinime {
+
+class DigraphUtils {
+ public:
+ typedef enum {
+ NOT_A_DIGRAPH_INDEX,
+ FIRST_DIGRAPH_CODEPOINT,
+ SECOND_DIGRAPH_CODEPOINT
+ } DigraphCodePointIndex;
+
+ typedef struct { int first; int second; int compositeGlyph; } digraph_t;
+
+ static bool hasDigraphForCodePoint(const int dictFlags, const int compositeGlyphCodePoint);
+ static int getAllDigraphsForDictionaryAndReturnSize(
+ const int dictFlags, const digraph_t **digraphs);
+ static int getDigraphCodePointForIndex(const int dictFlags, const int compositeGlyphCodePoint,
+ const DigraphCodePointIndex digraphCodePointIndex);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DigraphUtils);
+ static const digraph_t *getDigraphForCodePoint(
+ const int dictFlags, const int compositeGlyphCodePoint);
+
+ static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
+ static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
+};
+} // namespace latinime
+#endif // DIGRAPH_UTILS_H
diff --git a/native/jni/src/suggest/core/dictionary/shortcut_utils.h b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
new file mode 100644
index 000000000..c411408ec
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
@@ -0,0 +1,65 @@
+/*
+ * 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_SHORTCUT_UTILS
+#define LATINIME_SHORTCUT_UTILS
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "terminal_attributes.h"
+
+namespace latinime {
+
+class ShortcutUtils {
+ public:
+ static int outputShortcuts(const TerminalAttributes *const terminalAttributes,
+ int outputWordIndex, const int finalScore, int *const outputCodePoints,
+ int *const frequencies, int *const outputTypes, const bool sameAsTyped) {
+ TerminalAttributes::ShortcutIterator iterator = terminalAttributes->getShortcutIterator();
+ while (iterator.hasNextShortcutTarget() && outputWordIndex < MAX_RESULTS) {
+ int shortcutTarget[MAX_WORD_LENGTH];
+ int shortcutProbability;
+ const int shortcutTargetStringLength = iterator.getNextShortcutTarget(
+ MAX_WORD_LENGTH, shortcutTarget, &shortcutProbability);
+ int shortcutScore;
+ int kind;
+ if (shortcutProbability == BinaryFormat::WHITELIST_SHORTCUT_PROBABILITY
+ && sameAsTyped) {
+ shortcutScore = S_INT_MAX;
+ kind = Dictionary::KIND_WHITELIST;
+ } else {
+ // shortcut entry's score == its base entry's score - 1
+ shortcutScore = finalScore;
+ // Protection against int underflow
+ shortcutScore = max(S_INT_MIN + 1, shortcutScore) - 1;
+ kind = Dictionary::KIND_CORRECTION;
+ }
+ outputTypes[outputWordIndex] = kind;
+ frequencies[outputWordIndex] = shortcutScore;
+ frequencies[outputWordIndex] = max(S_INT_MIN + 1, shortcutScore) - 1;
+ const int startIndex2 = outputWordIndex * MAX_WORD_LENGTH;
+ DicNodeUtils::appendTwoWords(0, 0, shortcutTarget, shortcutTargetStringLength,
+ &outputCodePoints[startIndex2]);
+ ++outputWordIndex;
+ }
+ return outputWordIndex;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutUtils);
+};
+} // namespace latinime
+#endif // LATINIME_SHORTCUT_UTILS
diff --git a/native/jni/src/suggest/core/policy/traversal.h b/native/jni/src/suggest/core/policy/traversal.h
index 1d5082ff8..02c358aec 100644
--- a/native/jni/src/suggest/core/policy/traversal.h
+++ b/native/jni/src/suggest/core/policy/traversal.h
@@ -20,6 +20,9 @@
#include "defines.h"
namespace latinime {
+
+class DicTraverseSession;
+
class Traversal {
public:
virtual int getMaxPointerCount() const = 0;
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index 4d08fa0fa..e62b70423 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -14,14 +14,15 @@
* limitations under the License.
*/
+#include "suggest/core/policy/weighting.h"
+
#include "char_utils.h"
#include "defines.h"
-#include "dic_node.h"
-#include "dic_node_profiler.h"
-#include "dic_node_utils.h"
-#include "dic_traverse_session.h"
#include "hash_map_compat.h"
-#include "weighting.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_profiler.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/session/dic_traverse_session.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/policy/weighting.h b/native/jni/src/suggest/core/policy/weighting.h
index 83a0f4b45..b92dbe278 100644
--- a/native/jni/src/suggest/core/policy/weighting.h
+++ b/native/jni/src/suggest/core/policy/weighting.h
@@ -18,6 +18,7 @@
#define LATINIME_WEIGHTING_H
#include "defines.h"
+#include "hash_map_compat.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index 1f781dd43..ef6616e40 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -14,12 +14,13 @@
* limitations under the License.
*/
+#include "suggest/core/session/dic_traverse_session.h"
+
#include "defines.h"
#include "dictionary.h"
-#include "dic_node_utils.h"
-#include "dic_traverse_session.h"
#include "dic_traverse_wrapper.h"
#include "jni.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index af036f82b..62e1d1ab9 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -21,10 +21,10 @@
#include <vector>
#include "defines.h"
-#include "dic_nodes_cache.h"
#include "hash_map_compat.h"
#include "jni.h"
#include "proximity_info_state.h"
+#include "suggest/core/dicnode/dic_nodes_cache.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
new file mode 100644
index 000000000..1e97a9176
--- /dev/null
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -0,0 +1,520 @@
+/*
+ * 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 "suggest/core/suggest.h"
+
+#include "char_utils.h"
+#include "dictionary.h"
+#include "proximity_info.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_priority_queue.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/dictionary/shortcut_utils.h"
+#include "suggest/core/policy/scoring.h"
+#include "suggest/core/policy/traversal.h"
+#include "suggest/core/policy/weighting.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "terminal_attributes.h"
+
+namespace latinime {
+
+// Initialization of class constants.
+const int Suggest::LOOKAHEAD_DIC_NODES_CACHE_SIZE = 25;
+const int Suggest::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16;
+const int Suggest::MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE = 2;
+const float Suggest::AUTOCORRECT_CLASSIFICATION_THRESHOLD = 0.33f;
+const float Suggest::AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD = 0.6f;
+
+const bool Suggest::CORRECT_SPACE_OMISSION = true;
+const bool Suggest::CORRECT_TRANSPOSITION = true;
+const bool Suggest::CORRECT_INSERTION = true;
+const bool Suggest::CORRECT_OMISSION_G = true;
+
+/**
+ * Returns a set of suggestions for the given input touch points. The commitPoint argument indicates
+ * whether to prematurely commit the suggested words up to the given point for sentence-level
+ * suggestion.
+ *
+ * Note: Currently does not support concurrent calls across threads. Continuous suggestion is
+ * automatically activated for sequential calls that share the same starting input.
+ * TODO: Stop detecting continuous suggestion. Start using traverseSession instead.
+ */
+int Suggest::getSuggestions(ProximityInfo *pInfo, void *traverseSession,
+ int *inputXs, int *inputYs, int *times, int *pointerIds, int *inputCodePoints,
+ int inputSize, int commitPoint, int *outWords, int *frequencies, int *outputIndices,
+ int *outputTypes) const {
+ PROF_OPEN;
+ PROF_START(0);
+ const float maxSpatialDistance = TRAVERSAL->getMaxSpatialDistance();
+ DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
+ tSession->setupForGetSuggestions(pInfo, inputCodePoints, inputSize, inputXs, inputYs, times,
+ pointerIds, maxSpatialDistance, TRAVERSAL->getMaxPointerCount());
+ // TODO: Add the way to evaluate cache
+
+ initializeSearch(tSession, commitPoint);
+ PROF_END(0);
+ PROF_START(1);
+
+ // keep expanding search dicNodes until all have terminated.
+ while (tSession->getDicTraverseCache()->activeSize() > 0) {
+ expandCurrentDicNodes(tSession);
+ tSession->getDicTraverseCache()->advanceActiveDicNodes();
+ tSession->getDicTraverseCache()->advanceInputIndex(inputSize);
+ }
+ PROF_END(1);
+ PROF_START(2);
+ const int size = outputSuggestions(tSession, frequencies, outWords, outputIndices, outputTypes);
+ PROF_END(2);
+ PROF_CLOSE;
+ return size;
+}
+
+/**
+ * Initializes the search at the root of the lexicon trie. Note that when possible the search will
+ * continue suggestion from where it left off during the last call.
+ */
+void Suggest::initializeSearch(DicTraverseSession *traverseSession, int commitPoint) const {
+ if (!traverseSession->getProximityInfoState(0)->isUsed()) {
+ return;
+ }
+ if (TRAVERSAL->allowPartialCommit()) {
+ commitPoint = 0;
+ }
+
+ if (traverseSession->getInputSize() > MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE
+ && traverseSession->isContinuousSuggestionPossible()) {
+ if (commitPoint == 0) {
+ // Continue suggestion
+ traverseSession->getDicTraverseCache()->continueSearch();
+ } else {
+ // Continue suggestion after partial commit.
+ DicNode *topDicNode =
+ traverseSession->getDicTraverseCache()->setCommitPoint(commitPoint);
+ traverseSession->setPrevWordPos(topDicNode->getPrevWordNodePos());
+ traverseSession->getDicTraverseCache()->continueSearch();
+ traverseSession->setPartiallyCommited();
+ }
+ } else {
+ // Restart recognition at the root.
+ traverseSession->resetCache(TRAVERSAL->getMaxCacheSize(), MAX_RESULTS);
+ // Create a new dic node here
+ DicNode rootNode;
+ DicNodeUtils::initAsRoot(traverseSession->getDicRootPos(),
+ traverseSession->getOffsetDict(), traverseSession->getPrevWordPos(), &rootNode);
+ traverseSession->getDicTraverseCache()->copyPushActive(&rootNode);
+ }
+}
+
+/**
+ * Outputs the final list of suggestions (i.e., terminal nodes).
+ */
+int Suggest::outputSuggestions(DicTraverseSession *traverseSession, int *frequencies,
+ int *outputCodePoints, int *spaceIndices, int *outputTypes) const {
+ const int terminalSize = min(MAX_RESULTS,
+ static_cast<int>(traverseSession->getDicTraverseCache()->terminalSize()));
+ DicNode terminals[MAX_RESULTS]; // Avoiding non-POD variable length array
+
+ for (int index = terminalSize - 1; index >= 0; --index) {
+ traverseSession->getDicTraverseCache()->popTerminal(&terminals[index]);
+ }
+
+ const float languageWeight = SCORING->getAdjustedLanguageWeight(
+ traverseSession, terminals, terminalSize);
+
+ int outputWordIndex = 0;
+ // Insert most probable word at index == 0 as long as there is one terminal at least
+ const bool hasMostProbableString =
+ SCORING->getMostProbableString(traverseSession, terminalSize, languageWeight,
+ &outputCodePoints[0], &outputTypes[0], &frequencies[0]);
+ if (hasMostProbableString) {
+ ++outputWordIndex;
+ }
+
+ // Initial value of the loop index for terminal nodes (words)
+ int doubleLetterTerminalIndex = -1;
+ DoubleLetterLevel doubleLetterLevel = NOT_A_DOUBLE_LETTER;
+ SCORING->searchWordWithDoubleLetter(terminals, terminalSize,
+ &doubleLetterTerminalIndex, &doubleLetterLevel);
+
+ int maxScore = S_INT_MIN;
+ // Output suggestion results here
+ for (int terminalIndex = 0; terminalIndex < terminalSize && outputWordIndex < MAX_RESULTS;
+ ++terminalIndex) {
+ DicNode *terminalDicNode = &terminals[terminalIndex];
+ if (DEBUG_GEO_FULL) {
+ terminalDicNode->dump("OUT:");
+ }
+ const float doubleLetterCost = SCORING->getDoubleLetterDemotionDistanceCost(
+ terminalIndex, doubleLetterTerminalIndex, doubleLetterLevel);
+ const float compoundDistance = terminalDicNode->getCompoundDistance(languageWeight)
+ + doubleLetterCost;
+ const TerminalAttributes terminalAttributes(traverseSession->getOffsetDict(),
+ terminalDicNode->getFlags(), terminalDicNode->getAttributesPos());
+ const int originalTerminalProbability = terminalDicNode->getProbability();
+
+ // Do not suggest words with a 0 probability, or entries that are blacklisted or do not
+ // represent a word. However, we should still submit their shortcuts if any.
+ const bool isValidWord =
+ originalTerminalProbability > 0 && !terminalAttributes.isBlacklistedOrNotAWord();
+ // Increase output score of top typing suggestion to ensure autocorrection.
+ // TODO: Better integration with java side autocorrection logic.
+ // Force autocorrection for obvious long multi-word suggestions.
+ const bool isForceCommitMultiWords = TRAVERSAL->allowPartialCommit()
+ && (traverseSession->isPartiallyCommited()
+ || (traverseSession->getInputSize() >= MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT
+ && terminalDicNode->hasMultipleWords()));
+
+ const int finalScore = SCORING->calculateFinalScore(
+ compoundDistance, traverseSession->getInputSize(),
+ isForceCommitMultiWords || (isValidWord && SCORING->doesAutoCorrectValidWord()));
+
+ maxScore = max(maxScore, finalScore);
+
+ if (TRAVERSAL->allowPartialCommit()) {
+ // Index for top typing suggestion should be 0.
+ if (isValidWord && outputWordIndex == 0) {
+ terminalDicNode->outputSpacePositionsResult(spaceIndices);
+ }
+ }
+
+ // Do not suggest words with a 0 probability, or entries that are blacklisted or do not
+ // represent a word. However, we should still submit their shortcuts if any.
+ if (isValidWord) {
+ outputTypes[outputWordIndex] = Dictionary::KIND_CORRECTION;
+ frequencies[outputWordIndex] = finalScore;
+ // Populate the outputChars array with the suggested word.
+ const int startIndex = outputWordIndex * MAX_WORD_LENGTH;
+ terminalDicNode->outputResult(&outputCodePoints[startIndex]);
+ ++outputWordIndex;
+ }
+
+ const bool sameAsTyped = TRAVERSAL->sameAsTyped(traverseSession, terminalDicNode);
+ outputWordIndex = ShortcutUtils::outputShortcuts(&terminalAttributes, outputWordIndex,
+ finalScore, outputCodePoints, frequencies, outputTypes, sameAsTyped);
+ DicNode::managedDelete(terminalDicNode);
+ }
+
+ if (hasMostProbableString) {
+ SCORING->safetyNetForMostProbableString(terminalSize, maxScore,
+ &outputCodePoints[0], &frequencies[0]);
+ }
+ return outputWordIndex;
+}
+
+/**
+ * Expands the dicNodes in the current search priority queue by advancing to the possible child
+ * nodes based on the next touch point(s) (or no touch points for lookahead)
+ */
+void Suggest::expandCurrentDicNodes(DicTraverseSession *traverseSession) const {
+ const int inputSize = traverseSession->getInputSize();
+ DicNodeVector childDicNodes(TRAVERSAL->getDefaultExpandDicNodeSize());
+ DicNode omissionDicNode;
+
+ // TODO: Find more efficient caching
+ const bool shouldDepthLevelCache = TRAVERSAL->shouldDepthLevelCache(traverseSession);
+ if (shouldDepthLevelCache) {
+ traverseSession->getDicTraverseCache()->updateLastCachedInputIndex();
+ }
+ if (DEBUG_CACHE) {
+ AKLOGI("expandCurrentDicNodes depth level cache = %d, inputSize = %d",
+ shouldDepthLevelCache, inputSize);
+ }
+ while (traverseSession->getDicTraverseCache()->activeSize() > 0) {
+ DicNode dicNode;
+ traverseSession->getDicTraverseCache()->popActive(&dicNode);
+ if (dicNode.isTotalInputSizeExceedingLimit()) {
+ return;
+ }
+ childDicNodes.clear();
+ const int point0Index = dicNode.getInputIndex(0);
+ const bool canDoLookAheadCorrection =
+ TRAVERSAL->canDoLookAheadCorrection(traverseSession, &dicNode);
+ const bool isLookAheadCorrection = canDoLookAheadCorrection
+ && traverseSession->getDicTraverseCache()->
+ isLookAheadCorrectionInputIndex(static_cast<int>(point0Index));
+ const bool isCompletion = dicNode.isCompletion(inputSize);
+
+ const bool shouldNodeLevelCache =
+ TRAVERSAL->shouldNodeLevelCache(traverseSession, &dicNode);
+ if (shouldDepthLevelCache || shouldNodeLevelCache) {
+ if (DEBUG_CACHE) {
+ dicNode.dump("PUSH_CACHE");
+ }
+ traverseSession->getDicTraverseCache()->copyPushContinue(&dicNode);
+ dicNode.setCached();
+ }
+
+ if (isLookAheadCorrection) {
+ // The algorithm maintains a small set of "deferred" nodes that have not consumed the
+ // latest touch point yet. These are needed to apply look-ahead correction operations
+ // that require special handling of the latest touch point. For example, with insertions
+ // (e.g., "thiis" -> "this") the latest touch point should not be consumed at all.
+ if (CORRECT_TRANSPOSITION) {
+ processDicNodeAsTransposition(traverseSession, &dicNode);
+ }
+ if (CORRECT_INSERTION) {
+ processDicNodeAsInsertion(traverseSession, &dicNode);
+ }
+ } else { // !isLookAheadCorrection
+ // Only consider typing error corrections if the normalized compound distance is
+ // below a spatial distance threshold.
+ // NOTE: the threshold may need to be updated if scoring model changes.
+ // TODO: Remove. Do not prune node here.
+ const bool allowsErrorCorrections = TRAVERSAL->allowsErrorCorrections(&dicNode);
+ // Process for handling space substitution (e.g., hevis => he is)
+ if (allowsErrorCorrections
+ && TRAVERSAL->isSpaceSubstitutionTerminal(traverseSession, &dicNode)) {
+ createNextWordDicNode(traverseSession, &dicNode, true /* spaceSubstitution */);
+ }
+
+ DicNodeUtils::getAllChildDicNodes(
+ &dicNode, traverseSession->getOffsetDict(), &childDicNodes);
+
+ const int childDicNodesSize = childDicNodes.getSizeAndLock();
+ for (int i = 0; i < childDicNodesSize; ++i) {
+ DicNode *const childDicNode = childDicNodes[i];
+ if (isCompletion) {
+ // Handle forward lookahead when the lexicon letter exceeds the input size.
+ processDicNodeAsMatch(traverseSession, childDicNode);
+ continue;
+ }
+ if (allowsErrorCorrections
+ && TRAVERSAL->isOmission(traverseSession, &dicNode, childDicNode)) {
+ // TODO: (Gesture) Change weight between omission and substitution errors
+ // TODO: (Gesture) Terminal node should not be handled as omission
+ omissionDicNode.initByCopy(childDicNode);
+ processDicNodeAsOmission(traverseSession, &omissionDicNode);
+ }
+ const ProximityType proximityType = TRAVERSAL->getProximityType(
+ traverseSession, &dicNode, childDicNode);
+ switch (proximityType) {
+ // TODO: Consider the difference of proximityType here
+ case MATCH_CHAR:
+ case PROXIMITY_CHAR:
+ processDicNodeAsMatch(traverseSession, childDicNode);
+ break;
+ case ADDITIONAL_PROXIMITY_CHAR:
+ if (allowsErrorCorrections) {
+ processDicNodeAsAdditionalProximityChar(traverseSession, &dicNode,
+ childDicNode);
+ }
+ break;
+ case SUBSTITUTION_CHAR:
+ if (allowsErrorCorrections) {
+ processDicNodeAsSubstitution(traverseSession, &dicNode, childDicNode);
+ }
+ break;
+ case UNRELATED_CHAR:
+ // Just drop this node and do nothing.
+ break;
+ default:
+ // Just drop this node and do nothing.
+ break;
+ }
+ }
+
+ // Push the node for look-ahead correction
+ if (allowsErrorCorrections && canDoLookAheadCorrection) {
+ traverseSession->getDicTraverseCache()->copyPushNextActive(&dicNode);
+ }
+ }
+ }
+}
+
+void Suggest::processTerminalDicNode(
+ DicTraverseSession *traverseSession, DicNode *dicNode) const {
+ if (dicNode->getCompoundDistance() >= static_cast<float>(MAX_VALUE_FOR_WEIGHTING)) {
+ return;
+ }
+ if (!dicNode->isTerminalWordNode()) {
+ return;
+ }
+ if (TRAVERSAL->needsToTraverseAllUserInput()
+ && dicNode->getInputIndex(0) < traverseSession->getInputSize()) {
+ return;
+ }
+
+ if (dicNode->shouldBeFilterdBySafetyNetForBigram()) {
+ return;
+ }
+ // Create a non-cached node here.
+ DicNode terminalDicNode;
+ DicNodeUtils::initByCopy(dicNode, &terminalDicNode);
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TERMINAL, traverseSession, 0,
+ &terminalDicNode, traverseSession->getBigramCacheMap());
+ traverseSession->getDicTraverseCache()->copyPushTerminal(&terminalDicNode);
+}
+
+/**
+ * Adds the expanded dicNode to the next search priority queue. Also creates an additional next word
+ * (by the space omission error correction) search path if input dicNode is on a terminal node.
+ */
+void Suggest::processExpandedDicNode(
+ DicTraverseSession *traverseSession, DicNode *dicNode) const {
+ processTerminalDicNode(traverseSession, dicNode);
+ if (dicNode->getCompoundDistance() < static_cast<float>(MAX_VALUE_FOR_WEIGHTING)) {
+ if (TRAVERSAL->isSpaceOmissionTerminal(traverseSession, dicNode)) {
+ createNextWordDicNode(traverseSession, dicNode, false /* spaceSubstitution */);
+ }
+ const int allowsLookAhead = !(dicNode->hasMultipleWords()
+ && dicNode->isCompletion(traverseSession->getInputSize()));
+ if (dicNode->hasChildren() && allowsLookAhead) {
+ traverseSession->getDicTraverseCache()->copyPushNextActive(dicNode);
+ }
+ }
+ DicNode::managedDelete(dicNode);
+}
+
+void Suggest::processDicNodeAsMatch(DicTraverseSession *traverseSession,
+ DicNode *childDicNode) const {
+ weightChildNode(traverseSession, childDicNode);
+ processExpandedDicNode(traverseSession, childDicNode);
+}
+
+void Suggest::processDicNodeAsAdditionalProximityChar(DicTraverseSession *traverseSession,
+ DicNode *dicNode, DicNode *childDicNode) const {
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_ADDITIONAL_PROXIMITY,
+ traverseSession, dicNode, childDicNode, 0 /* bigramCacheMap */);
+ weightChildNode(traverseSession, childDicNode);
+ processExpandedDicNode(traverseSession, childDicNode);
+}
+
+void Suggest::processDicNodeAsSubstitution(DicTraverseSession *traverseSession,
+ DicNode *dicNode, DicNode *childDicNode) const {
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SUBSTITUTION, traverseSession,
+ dicNode, childDicNode, 0 /* bigramCacheMap */);
+ weightChildNode(traverseSession, childDicNode);
+ processExpandedDicNode(traverseSession, childDicNode);
+}
+
+/**
+ * Handle the dicNode as an omission error (e.g., ths => this). Skip the current letter and consider
+ * matches for all possible next letters. Note that just skipping the current letter without any
+ * other conditions tends to flood the search dic nodes cache with omission nodes. Instead, check
+ * the possible *next* letters after the omission to better limit search to plausible omissions.
+ * Note that apostrophes are handled as omissions.
+ */
+void Suggest::processDicNodeAsOmission(
+ DicTraverseSession *traverseSession, DicNode *dicNode) const {
+ // If the omission is surely intentional that it should incur zero cost.
+ const bool isZeroCostOmission = dicNode->isZeroCostOmission();
+ DicNodeVector childDicNodes;
+
+ DicNodeUtils::getAllChildDicNodes(dicNode, traverseSession->getOffsetDict(), &childDicNodes);
+
+ const int size = childDicNodes.getSizeAndLock();
+ for (int i = 0; i < size; i++) {
+ DicNode *const childDicNode = childDicNodes[i];
+ if (!isZeroCostOmission) {
+ // Treat this word as omission
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_OMISSION, traverseSession,
+ dicNode, childDicNode, 0 /* bigramCacheMap */);
+ }
+ weightChildNode(traverseSession, childDicNode);
+
+ if (!TRAVERSAL->isPossibleOmissionChildNode(traverseSession, dicNode, childDicNode)) {
+ DicNode::managedDelete(childDicNode);
+ continue;
+ }
+ processExpandedDicNode(traverseSession, childDicNode);
+ }
+}
+
+/**
+ * Handle the dicNode as an insertion error (e.g., thiis => this). Skip the current touch point and
+ * consider matches for the next touch point.
+ */
+void Suggest::processDicNodeAsInsertion(DicTraverseSession *traverseSession,
+ DicNode *dicNode) const {
+ const int16_t pointIndex = dicNode->getInputIndex(0);
+ DicNodeVector childDicNodes;
+ DicNodeUtils::getProximityChildDicNodes(dicNode, traverseSession->getOffsetDict(),
+ traverseSession->getProximityInfoState(0), pointIndex + 1, true, &childDicNodes);
+ const int size = childDicNodes.getSizeAndLock();
+ for (int i = 0; i < size; i++) {
+ DicNode *const childDicNode = childDicNodes[i];
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_INSERTION, traverseSession,
+ dicNode, childDicNode, 0 /* bigramCacheMap */);
+ processExpandedDicNode(traverseSession, childDicNode);
+ }
+}
+
+/**
+ * Handle the dicNode as a transposition error (e.g., thsi => this). Swap the next two touch points.
+ */
+void Suggest::processDicNodeAsTransposition(DicTraverseSession *traverseSession,
+ DicNode *dicNode) const {
+ const int16_t pointIndex = dicNode->getInputIndex(0);
+ DicNodeVector childDicNodes1;
+ DicNodeUtils::getProximityChildDicNodes(dicNode, traverseSession->getOffsetDict(),
+ traverseSession->getProximityInfoState(0), pointIndex + 1, false, &childDicNodes1);
+ const int childSize1 = childDicNodes1.getSizeAndLock();
+ for (int i = 0; i < childSize1; i++) {
+ if (childDicNodes1[i]->hasChildren()) {
+ DicNodeVector childDicNodes2;
+ DicNodeUtils::getProximityChildDicNodes(
+ childDicNodes1[i], traverseSession->getOffsetDict(),
+ traverseSession->getProximityInfoState(0), pointIndex, false, &childDicNodes2);
+ const int childSize2 = childDicNodes2.getSizeAndLock();
+ for (int j = 0; j < childSize2; j++) {
+ DicNode *const childDicNode2 = childDicNodes2[j];
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_TRANSPOSITION,
+ traverseSession, childDicNodes1[i], childDicNode2, 0 /* bigramCacheMap */);
+ processExpandedDicNode(traverseSession, childDicNode2);
+ }
+ }
+ DicNode::managedDelete(childDicNodes1[i]);
+ }
+}
+
+/**
+ * Weight child node by aligning it to the key
+ */
+void Suggest::weightChildNode(DicTraverseSession *traverseSession, DicNode *dicNode) const {
+ const int inputSize = traverseSession->getInputSize();
+ if (dicNode->isCompletion(inputSize)) {
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_COMPLETION, traverseSession,
+ 0 /* parentDicNode */, dicNode, 0 /* bigramCacheMap */);
+ } else { // completion
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_MATCH, traverseSession,
+ 0 /* parentDicNode */, dicNode, 0 /* bigramCacheMap */);
+ }
+}
+
+/**
+ * Creates a new dicNode that represents a space insertion at the end of the input dicNode. Also
+ * incorporates the unigram / bigram score for the ending word into the new dicNode.
+ */
+void Suggest::createNextWordDicNode(DicTraverseSession *traverseSession, DicNode *dicNode,
+ const bool spaceSubstitution) const {
+ if (!TRAVERSAL->isGoodToTraverseNextWord(dicNode)) {
+ return;
+ }
+
+ // Create a non-cached node here.
+ DicNode newDicNode;
+ DicNodeUtils::initAsRootWithPreviousWord(traverseSession->getDicRootPos(),
+ traverseSession->getOffsetDict(), dicNode, &newDicNode);
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_NEW_WORD, traverseSession, dicNode,
+ &newDicNode, traverseSession->getBigramCacheMap());
+ if (spaceSubstitution) {
+ // Merge this with CT_NEW_WORD
+ Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SPACE_SUBSTITUTION,
+ traverseSession, 0, &newDicNode, 0 /* bigramCacheMap */);
+ }
+ traverseSession->getDicTraverseCache()->copyPushNextActive(&newDicNode);
+}
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
new file mode 100644
index 000000000..a1e7e7a94
--- /dev/null
+++ b/native/jni/src/suggest/core/suggest.h
@@ -0,0 +1,95 @@
+/*
+ * 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_SUGGEST_IMPL_H
+#define LATINIME_SUGGEST_IMPL_H
+
+#include "defines.h"
+#include "suggest/core/suggest_interface.h"
+#include "suggest/core/policy/suggest_policy.h"
+
+namespace latinime {
+
+class DicNode;
+class DicTraverseSession;
+class ProximityInfo;
+class Scoring;
+class Traversal;
+class Weighting;
+
+class Suggest : public SuggestInterface {
+ public:
+ AK_FORCE_INLINE Suggest(const SuggestPolicy *const suggestPolicy)
+ : TRAVERSAL(suggestPolicy->getTraversal()),
+ SCORING(suggestPolicy->getScoring()), WEIGHTING(suggestPolicy->getWeighting()) {}
+ AK_FORCE_INLINE virtual ~Suggest() {}
+ int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
+ int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
+ int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Suggest);
+ void createNextWordDicNode(DicTraverseSession *traverseSession, DicNode *dicNode,
+ const bool spaceSubstitution) const;
+ int outputSuggestions(DicTraverseSession *traverseSession, int *frequencies,
+ int *outputCodePoints, int *outputIndices, int *outputTypes) const;
+ void initializeSearch(DicTraverseSession *traverseSession, int commitPoint) const;
+ void expandCurrentDicNodes(DicTraverseSession *traverseSession) const;
+ void processTerminalDicNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ void processExpandedDicNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ void weightChildNode(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ float getAutocorrectScore(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ void generateFeatures(
+ DicTraverseSession *traverseSession, DicNode *dicNode, float *features) const;
+ void processDicNodeAsOmission(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ void processDicNodeAsTransposition(DicTraverseSession *traverseSession,
+ DicNode *dicNode) const;
+ void processDicNodeAsInsertion(DicTraverseSession *traverseSession, DicNode *dicNode) const;
+ void processDicNodeAsAdditionalProximityChar(DicTraverseSession *traverseSession,
+ DicNode *dicNode, DicNode *childDicNode) const;
+ void processDicNodeAsSubstitution(DicTraverseSession *traverseSession, DicNode *dicNode,
+ DicNode *childDicNode) const;
+ void processDicNodeAsMatch(DicTraverseSession *traverseSession,
+ DicNode *childDicNode) const;
+
+ // Dic nodes cache size for lookahead (autocompletion)
+ static const int LOOKAHEAD_DIC_NODES_CACHE_SIZE;
+ // Max characters to lookahead
+ static const int MAX_LOOKAHEAD;
+ // Inputs longer than this will autocorrect if the suggestion is multi-word
+ static const int MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT;
+ static const int MIN_CONTINUOUS_SUGGESTION_INPUT_SIZE;
+ // Base value for converting costs into scores (low so will not autocorrect without classifier)
+ static const float BASE_OUTPUT_SCORE;
+
+ // Threshold for autocorrection classifier
+ static const float AUTOCORRECT_CLASSIFICATION_THRESHOLD;
+ // Threshold for computing the language model feature for autocorrect classification
+ static const float AUTOCORRECT_LANGUAGE_FEATURE_THRESHOLD;
+
+ // Typing error correction settings
+ static const bool CORRECT_SPACE_OMISSION;
+ static const bool CORRECT_TRANSPOSITION;
+ static const bool CORRECT_INSERTION;
+
+ const Traversal *const TRAVERSAL;
+ const Scoring *const SCORING;
+ const Weighting *const WEIGHTING;
+
+ static const bool CORRECT_OMISSION_G;
+};
+} // namespace latinime
+#endif // LATINIME_SUGGEST_IMPL_H
diff --git a/native/jni/src/suggest/suggest_interface.h b/native/jni/src/suggest/core/suggest_interface.h
index 0bb85d7e5..0bb85d7e5 100644
--- a/native/jni/src/suggest/suggest_interface.h
+++ b/native/jni/src/suggest/core/suggest_interface.h
diff --git a/native/jni/src/suggest/gesture_suggest.h b/native/jni/src/suggest/gesture_suggest.h
deleted file mode 100644
index 82c3a69ad..000000000
--- a/native/jni/src/suggest/gesture_suggest.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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_GESTURE_SUGGEST_H
-#define LATINIME_GESTURE_SUGGEST_H
-
-#include "defines.h"
-#include "suggest_interface.h"
-
-namespace latinime {
-
-class ProximityInfo;
-
-class GestureSuggest : public SuggestInterface {
- public:
- GestureSuggest() : mSuggestInterface(getGestureSuggestInstance()) {}
-
- virtual ~GestureSuggest();
-
- int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
- int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
- int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const {
- if (!mSuggestInterface) {
- return 0;
- }
- return mSuggestInterface->getSuggestions(pInfo, traverseSession, inputXs, inputYs, times,
- pointerIds, inputCodePoints, inputSize, commitPoint, outWords, frequencies,
- outputIndices, outputTypes);
- }
-
- static void setGestureSuggestFactoryMethod(SuggestInterface *(*factoryMethod)()) {
- sGestureSuggestFactoryMethod = factoryMethod;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GestureSuggest);
- static SuggestInterface *getGestureSuggestInstance() {
- if (!sGestureSuggestFactoryMethod) {
- return 0;
- }
- return sGestureSuggestFactoryMethod();
- }
-
- static SuggestInterface *(*sGestureSuggestFactoryMethod)();
- SuggestInterface *mSuggestInterface;
-};
-} // namespace latinime
-#endif // LATINIME_GESTURE_SUGGEST_H
diff --git a/native/jni/src/suggest/typing_suggest.cpp b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp
index 56bd5b69a..6d3173937 100644
--- a/native/jni/src/suggest/typing_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp
@@ -14,12 +14,8 @@
* limitations under the License.
*/
-#include "typing_suggest.h"
+#include "gesture_suggest_policy_factory.h"
namespace latinime {
- SuggestInterface *(*TypingSuggest::sTypingSuggestFactoryMethod)() = 0;
-
- TypingSuggest::~TypingSuggest() {
- delete mSuggestInterface;
- }
+ const SuggestPolicy *(*GestureSuggestPolicyFactory::sGestureSuggestFactoryMethod)() = 0;
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h
new file mode 100644
index 000000000..509b01fc0
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/gesture/gesture_suggest_policy_factory.h
@@ -0,0 +1,44 @@
+/*
+ * 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_GESTURE_SUGGEST_POLICY_FACTORY_H
+#define LATINIME_GESTURE_SUGGEST_POLICY_FACTORY_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class SuggestPolicy;
+
+class GestureSuggestPolicyFactory {
+ public:
+ static void setGestureSuggestPolicyFactoryMethod(const SuggestPolicy *(*factoryMethod)()) {
+ sGestureSuggestFactoryMethod = factoryMethod;
+ }
+
+ static const SuggestPolicy *getGestureSuggestPolicy() {
+ if (!sGestureSuggestFactoryMethod) {
+ return 0;
+ }
+ return sGestureSuggestFactoryMethod();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GestureSuggestPolicyFactory);
+ static const SuggestPolicy *(*sGestureSuggestFactoryMethod)();
+};
+} // namespace latinime
+#endif // LATINIME_GESTURE_SUGGEST_POLICY_FACTORY_H
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
new file mode 100644
index 000000000..0fa684f01
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+// TODO: RENAME all
+const float ScoringParams::MAX_SPATIAL_DISTANCE = 1.0f;
+const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY = 40;
+const int ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED = 120;
+const float ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD = 1.0f;
+const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE = 125;
+const int ScoringParams::THRESHOLD_SHORT_WORD_LENGTH = 4;
+
+const float ScoringParams::DISTANCE_WEIGHT_LENGTH = 0.132f;
+const float ScoringParams::PROXIMITY_COST = 0.086f;
+const float ScoringParams::FIRST_PROXIMITY_COST = 0.104f;
+const float ScoringParams::OMISSION_COST = 0.388f;
+const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.431f;
+const float ScoringParams::OMISSION_COST_FIRST_CHAR = 0.532f;
+const float ScoringParams::INSERTION_COST = 0.670f;
+const float ScoringParams::INSERTION_COST_SAME_CHAR = 0.526f;
+const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.563f;
+const float ScoringParams::TRANSPOSITION_COST = 0.494f;
+const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.239f;
+const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.380f;
+const float ScoringParams::SUBSTITUTION_COST = 0.363f;
+const float ScoringParams::COST_NEW_WORD = 0.054f;
+const float ScoringParams::COST_NEW_WORD_CAPITALIZED = 0.174f;
+const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.123f;
+const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.462f;
+const float ScoringParams::COST_LOOKAHEAD = 0.092f;
+const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.126f;
+const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.056f;
+const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.136f;
+const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
+const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
+const float ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT = 0.1f;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.h b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
new file mode 100644
index 000000000..8f104b362
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
@@ -0,0 +1,66 @@
+/*
+ * 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_SCORING_PARAMS_H
+#define LATINIME_SCORING_PARAMS_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class ScoringParams {
+ public:
+ // Fixed model parameters
+ static const float MAX_SPATIAL_DISTANCE;
+ static const int THRESHOLD_NEXT_WORD_PROBABILITY;
+ static const int THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
+ static const float AUTOCORRECT_OUTPUT_THRESHOLD;
+ static const int MAX_CACHE_DIC_NODE_SIZE;
+ static const int THRESHOLD_SHORT_WORD_LENGTH;
+
+ // Numerically optimized parameters (currently for tap typing only).
+ // TODO: add ability to modify these constants programmatically.
+ // TODO: explore optimization of gesture parameters.
+ static const float DISTANCE_WEIGHT_LENGTH;
+ static const float PROXIMITY_COST;
+ static const float FIRST_PROXIMITY_COST;
+ static const float OMISSION_COST;
+ static const float OMISSION_COST_SAME_CHAR;
+ static const float OMISSION_COST_FIRST_CHAR;
+ static const float INSERTION_COST;
+ static const float INSERTION_COST_SAME_CHAR;
+ static const float INSERTION_COST_FIRST_CHAR;
+ static const float TRANSPOSITION_COST;
+ static const float SPACE_SUBSTITUTION_COST;
+ static const float ADDITIONAL_PROXIMITY_COST;
+ static const float SUBSTITUTION_COST;
+ static const float COST_NEW_WORD;
+ static const float COST_NEW_WORD_CAPITALIZED;
+ static const float DISTANCE_WEIGHT_LANGUAGE;
+ static const float COST_FIRST_LOOKAHEAD;
+ static const float COST_LOOKAHEAD;
+ static const float HAS_PROXIMITY_TERMINAL_COST;
+ static const float HAS_EDIT_CORRECTION_TERMINAL_COST;
+ static const float HAS_MULTI_WORD_TERMINAL_COST;
+ static const float TYPING_BASE_OUTPUT_SCORE;
+ static const float TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
+ static const float MAX_NORM_DISTANCE_FOR_EDIT;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ScoringParams);
+};
+} // namespace latinime
+#endif // LATINIME_SCORING_PARAMS_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp b/native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp
new file mode 100644
index 000000000..d8c6175e2
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.cpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/typing/typing_scoring.h"
+
+namespace latinime {
+const TypingScoring TypingScoring::sInstance;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
new file mode 100644
index 000000000..90e2133e7
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_TYPING_SCORING_H
+#define LATINIME_TYPING_SCORING_H
+
+#include "defines.h"
+#include "suggest/core/policy/scoring.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+
+class DicNode;
+class DicTraverseSession;
+
+class TypingScoring : public Scoring {
+ public:
+ static const TypingScoring *getInstance() { return &sInstance; }
+
+ AK_FORCE_INLINE bool getMostProbableString(
+ const DicTraverseSession *const traverseSession, const int terminalSize,
+ const float languageWeight, int *const outputCodePoints, int *const type,
+ int *const freq) const {
+ return false;
+ }
+
+ AK_FORCE_INLINE void safetyNetForMostProbableString(const int terminalSize,
+ const int maxScore, int *const outputCodePoints, int *const frequencies) const {
+ }
+
+ AK_FORCE_INLINE void searchWordWithDoubleLetter(DicNode *terminals,
+ const int terminalSize, int *doubleLetterTerminalIndex,
+ DoubleLetterLevel *doubleLetterLevel) const {
+ }
+
+ AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
+ DicNode *const terminals, const int size) const {
+ return 1.0f;
+ }
+
+ AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance,
+ const int inputSize, const bool forceCommit) const {
+ const float maxDistance = ScoringParams::DISTANCE_WEIGHT_LANGUAGE
+ + static_cast<float>(inputSize) * ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
+ return static_cast<int>((ScoringParams::TYPING_BASE_OUTPUT_SCORE
+ - (compoundDistance / maxDistance)
+ + (forceCommit ? ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD : 0.0f))
+ * SUGGEST_INTERFACE_OUTPUT_SCALE);
+ }
+
+ AK_FORCE_INLINE float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
+ const int doubleLetterTerminalIndex,
+ const DoubleLetterLevel doubleLetterLevel) const {
+ return 0.0f;
+ }
+
+ AK_FORCE_INLINE bool doesAutoCorrectValidWord() const {
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypingScoring);
+ static const TypingScoring sInstance;
+
+ TypingScoring() {}
+ ~TypingScoring() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SCORING_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp
new file mode 100644
index 000000000..0c2763967
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.cpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/typing/typing_suggest_policy.h"
+
+namespace latinime {
+const TypingSuggestPolicy TypingSuggestPolicy::sInstance;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h
new file mode 100644
index 000000000..35f48097c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_TYPING_SUGGEST_POLICY_H
+#define LATINIME_TYPING_SUGGEST_POLICY_H
+
+#include "defines.h"
+#include "suggest/core/policy/suggest_policy.h"
+#include "suggest/policyimpl/typing/typing_scoring.h"
+#include "suggest/policyimpl/typing/typing_traversal.h"
+#include "suggest/policyimpl/typing/typing_weighting.h"
+
+namespace latinime {
+
+class Scoring;
+class Traversal;
+class Weighting;
+
+class TypingSuggestPolicy : public SuggestPolicy {
+ public:
+ static const TypingSuggestPolicy *getInstance() { return &sInstance; }
+
+ TypingSuggestPolicy() {}
+ virtual ~TypingSuggestPolicy() {}
+ AK_FORCE_INLINE const Traversal *getTraversal() const {
+ return TypingTraversal::getInstance();
+ }
+
+ AK_FORCE_INLINE const Scoring *getScoring() const {
+ return TypingScoring::getInstance();
+ }
+
+ AK_FORCE_INLINE const Weighting *getWeighting() const {
+ return TypingWeighting::getInstance();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypingSuggestPolicy);
+ static const TypingSuggestPolicy sInstance;
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SUGGEST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h
new file mode 100644
index 000000000..a67b45b1b
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_suggest_policy_factory.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
+#define LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
+
+#include "defines.h"
+#include "typing_suggest_policy.h"
+
+namespace latinime {
+
+class SuggestPolicy;
+
+class TypingSuggestPolicyFactory {
+ public:
+ static const SuggestPolicy *getTypingSuggestPolicy() {
+ return TypingSuggestPolicy::getInstance();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypingSuggestPolicyFactory);
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_SUGGEST_POLICY_FACTORY_H
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
new file mode 100644
index 000000000..66f8ba9fa
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/typing/typing_traversal.h"
+
+namespace latinime {
+const bool TypingTraversal::CORRECT_OMISSION = true;
+const bool TypingTraversal::CORRECT_SPACE_SUBSTITUTION = true;
+const bool TypingTraversal::CORRECT_SPACE_OMISSION = true;
+const TypingTraversal TypingTraversal::sInstance;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
new file mode 100644
index 000000000..f22029a2c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_TYPING_TRAVERSAL_H
+#define LATINIME_TYPING_TRAVERSAL_H
+
+#include <stdint.h>
+
+#include "char_utils.h"
+#include "defines.h"
+#include "proximity_info_state.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/policy/traversal.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+class TypingTraversal : public Traversal {
+ public:
+ static const TypingTraversal *getInstance() { return &sInstance; }
+
+ AK_FORCE_INLINE int getMaxPointerCount() const {
+ return MAX_POINTER_COUNT;
+ }
+
+ AK_FORCE_INLINE bool allowsErrorCorrections(const DicNode *const dicNode) const {
+ return dicNode->getNormalizedSpatialDistance()
+ < ScoringParams::MAX_NORM_DISTANCE_FOR_EDIT;
+ }
+
+ AK_FORCE_INLINE bool isOmission(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode, const DicNode *const childDicNode) const {
+ if (!CORRECT_OMISSION) {
+ return false;
+ }
+ const int inputSize = traverseSession->getInputSize();
+ // TODO: Don't refer to isCompletion?
+ if (dicNode->isCompletion(inputSize)) {
+ return false;
+ }
+ if (dicNode->canBeIntentionalOmission()) {
+ return true;
+ }
+ const int point0Index = dicNode->getInputIndex(0);
+ const int currentBaseLowerCodePoint =
+ toBaseLowerCase(childDicNode->getNodeCodePoint());
+ const int typedBaseLowerCodePoint =
+ toBaseLowerCase(traverseSession->getProximityInfoState(0)
+ ->getPrimaryCodePointAt(point0Index));
+ return (currentBaseLowerCodePoint != typedBaseLowerCodePoint);
+ }
+
+ AK_FORCE_INLINE bool isSpaceSubstitutionTerminal(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ if (!CORRECT_SPACE_SUBSTITUTION) {
+ return false;
+ }
+ if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
+ return false;
+ }
+ const int point0Index = dicNode->getInputIndex(0);
+ return dicNode->isTerminalWordNode()
+ && traverseSession->getProximityInfoState(0)->
+ hasSpaceProximity(point0Index);
+ }
+
+ AK_FORCE_INLINE bool isSpaceOmissionTerminal(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ if (!CORRECT_SPACE_OMISSION) {
+ return false;
+ }
+ const int inputSize = traverseSession->getInputSize();
+ // TODO: Don't refer to isCompletion?
+ if (dicNode->isCompletion(inputSize)) {
+ return false;
+ }
+ if (!dicNode->isTerminalWordNode()) {
+ return false;
+ }
+ const int16_t pointIndex = dicNode->getInputIndex(0);
+ return pointIndex <= inputSize && !dicNode->isTotalInputSizeExceedingLimit()
+ && !dicNode->shouldBeFilterdBySafetyNetForBigram();
+ }
+
+ AK_FORCE_INLINE bool shouldDepthLevelCache(
+ const DicTraverseSession *const traverseSession) const {
+ const int inputSize = traverseSession->getInputSize();
+ return traverseSession->isCacheBorderForTyping(inputSize);
+ }
+
+ AK_FORCE_INLINE bool shouldNodeLevelCache(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ return false;
+ }
+
+ AK_FORCE_INLINE bool canDoLookAheadCorrection(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ const int inputSize = traverseSession->getInputSize();
+ return dicNode->canDoLookAheadCorrection(inputSize);
+ }
+
+ AK_FORCE_INLINE ProximityType getProximityType(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+ const DicNode *const childDicNode) const {
+ return traverseSession->getProximityInfoState(0)->getProximityType(
+ dicNode->getInputIndex(0), childDicNode->getNodeCodePoint(),
+ true /* checkProximityChars */);
+ }
+
+ AK_FORCE_INLINE bool needsToTraverseAllUserInput() const {
+ return true;
+ }
+
+ AK_FORCE_INLINE float getMaxSpatialDistance() const {
+ return ScoringParams::MAX_SPATIAL_DISTANCE;
+ }
+
+ AK_FORCE_INLINE bool allowPartialCommit() const {
+ return true;
+ }
+
+ AK_FORCE_INLINE int getDefaultExpandDicNodeSize() const {
+ return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION;
+ }
+
+ AK_FORCE_INLINE bool sameAsTyped(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ return traverseSession->getProximityInfoState(0)->sameAsTyped(
+ dicNode->getOutputWordBuf(), dicNode->getDepth());
+ }
+
+ AK_FORCE_INLINE int getMaxCacheSize() const {
+ return ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
+ }
+
+ AK_FORCE_INLINE bool isPossibleOmissionChildNode(
+ const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+ const DicNode *const dicNode) const {
+ const ProximityType proximityType =
+ getProximityType(traverseSession, parentDicNode, dicNode);
+ if (!DicNodeUtils::isProximityChar(proximityType)) {
+ return false;
+ }
+ return true;
+ }
+
+ AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const {
+ const int probability = dicNode->getProbability();
+ if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
+ return false;
+ }
+ const int c = dicNode->getOutputWordBuf()[0];
+ const bool shortCappedWord = dicNode->getDepth()
+ < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && isAsciiUpper(c);
+ return !shortCappedWord
+ || probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypingTraversal);
+ static const bool CORRECT_OMISSION;
+ static const bool CORRECT_SPACE_SUBSTITUTION;
+ static const bool CORRECT_SPACE_OMISSION;
+ static const TypingTraversal sInstance;
+
+ TypingTraversal() {}
+ ~TypingTraversal() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_TRAVERSAL_H
diff --git a/native/jni/src/suggest/gesture_suggest.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index fce5621d5..1500341bd 100644
--- a/native/jni/src/suggest/gesture_suggest.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#include "gesture_suggest.h"
+#include "suggest/policyimpl/typing/typing_weighting.h"
-namespace latinime {
- SuggestInterface *(*GestureSuggest::sGestureSuggestFactoryMethod)() = 0;
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
- GestureSuggest::~GestureSuggest() {
- delete mSuggestInterface;
- }
-} // namespace latinime
+namespace latinime {
+const TypingWeighting TypingWeighting::sInstance;
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
new file mode 100644
index 000000000..52d54eb0f
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -0,0 +1,195 @@
+/*
+ * 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_TYPING_WEIGHTING_H
+#define LATINIME_TYPING_WEIGHTING_H
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/policy/weighting.h"
+#include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/policyimpl/typing/scoring_params.h"
+
+namespace latinime {
+
+class DicNode;
+struct DicNode_InputStateG;
+
+class TypingWeighting : public Weighting {
+ public:
+ static const TypingWeighting *getInstance() { return &sInstance; }
+
+ protected:
+ float getTerminalSpatialCost(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ float cost = 0.0f;
+ if (dicNode->hasMultipleWords()) {
+ cost += ScoringParams::HAS_MULTI_WORD_TERMINAL_COST;
+ }
+ if (dicNode->getProximityCorrectionCount() > 0) {
+ cost += ScoringParams::HAS_PROXIMITY_TERMINAL_COST;
+ }
+ if (dicNode->getEditCorrectionCount() > 0) {
+ cost += ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST;
+ }
+ return cost;
+ }
+
+ float getOmissionCost(const DicNode *const parentDicNode, const DicNode *const dicNode) const {
+ bool sameCodePoint = false;
+ bool isFirstLetterOmission = false;
+ float cost = 0.0f;
+ sameCodePoint = dicNode->isSameNodeCodePoint(parentDicNode);
+ // If the traversal omitted the first letter then the dicNode should now be on the second.
+ isFirstLetterOmission = dicNode->getDepth() == 2;
+ if (isFirstLetterOmission) {
+ cost = ScoringParams::OMISSION_COST_FIRST_CHAR;
+ } else {
+ cost = sameCodePoint ? ScoringParams::OMISSION_COST_SAME_CHAR
+ : ScoringParams::OMISSION_COST;
+ }
+ return cost;
+ }
+
+ float getMatchedCost(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+ DicNode_InputStateG *inputStateG) const {
+ const int pointIndex = dicNode->getInputIndex(0);
+ // Note: min() required since length can be MAX_POINT_TO_KEY_LENGTH for characters not on
+ // the keyboard (like accented letters)
+ const float length = min(ScoringParams::MAX_SPATIAL_DISTANCE,
+ traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+ pointIndex, dicNode->getNodeCodePoint()));
+ const float weightedDistance = length * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+ const bool isFirstChar = pointIndex == 0;
+ const bool isProximity = isProximityDicNode(traverseSession, dicNode);
+ const float cost = isProximity ? (isFirstChar ? ScoringParams::FIRST_PROXIMITY_COST
+ : ScoringParams::PROXIMITY_COST) : 0.0f;
+ return weightedDistance + cost;
+ }
+
+ bool isProximityDicNode(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ const int pointIndex = dicNode->getInputIndex(0);
+ const int primaryCodePoint = toBaseLowerCase(
+ traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(pointIndex));
+ const int dicNodeChar = toBaseLowerCase(dicNode->getNodeCodePoint());
+ return primaryCodePoint != dicNodeChar;
+ }
+
+ float getTranspositionCost(
+ const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
+ const DicNode *const dicNode) const {
+ const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
+ const int prevCodePoint = parentDicNode->getNodeCodePoint();
+ const float distance1 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+ parentPointIndex + 1, prevCodePoint);
+ const int codePoint = dicNode->getNodeCodePoint();
+ const float distance2 = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+ parentPointIndex, codePoint);
+ const float distance = distance1 + distance2;
+ const float weightedLengthDistance =
+ distance * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+ return ScoringParams::TRANSPOSITION_COST + weightedLengthDistance;
+ }
+
+ float getInsertionCost(
+ const DicTraverseSession *const traverseSession,
+ const DicNode *const parentDicNode, const DicNode *const dicNode) const {
+ const int16_t parentPointIndex = parentDicNode->getInputIndex(0);
+ const int prevCodePoint =
+ traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(parentPointIndex);
+
+ const int currentCodePoint = dicNode->getNodeCodePoint();
+ const bool sameCodePoint = prevCodePoint == currentCodePoint;
+ const float dist = traverseSession->getProximityInfoState(0)->getPointToKeyLength(
+ parentPointIndex + 1, currentCodePoint);
+ const float weightedDistance = dist * ScoringParams::DISTANCE_WEIGHT_LENGTH;
+ const bool singleChar = dicNode->getDepth() == 1;
+ const float cost = (singleChar ? ScoringParams::INSERTION_COST_FIRST_CHAR : 0.0f)
+ + (sameCodePoint ? ScoringParams::INSERTION_COST_SAME_CHAR
+ : ScoringParams::INSERTION_COST);
+ return cost + weightedDistance;
+ }
+
+ float getNewWordCost(const DicNode *const dicNode) const {
+ const bool isCapitalized = dicNode->isCapitalized();
+ return isCapitalized ?
+ ScoringParams::COST_NEW_WORD_CAPITALIZED : ScoringParams::COST_NEW_WORD;
+ }
+
+ float getNewWordBigramCost(
+ const DicTraverseSession *const traverseSession, const DicNode *const dicNode,
+ hash_map_compat<int, int16_t> *const bigramCacheMap) const {
+ return DicNodeUtils::getBigramNodeImprobability(traverseSession->getOffsetDict(),
+ dicNode, bigramCacheMap);
+ }
+
+ float getCompletionCost(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const {
+ // The auto completion starts when the input index is same as the input size
+ const bool firstCompletion = dicNode->getInputIndex(0)
+ == traverseSession->getInputSize();
+ // TODO: Change the cost for the first completion for the gesture?
+ const float cost = firstCompletion ? ScoringParams::COST_FIRST_LOOKAHEAD
+ : ScoringParams::COST_LOOKAHEAD;
+ return cost;
+ }
+
+ float getTerminalLanguageCost(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode, const float dicNodeLanguageImprobability) const {
+ const bool hasEditCount = dicNode->getEditCorrectionCount() > 0;
+ const bool isSameLength = dicNode->getDepth() == traverseSession->getInputSize();
+ const bool hasMultipleWords = dicNode->hasMultipleWords();
+ const bool hasProximityErrors = dicNode->getProximityCorrectionCount() > 0;
+ // Gesture input is always assumed to have proximity errors
+ // because the input word shouldn't be treated as perfect
+ const bool isExactMatch = !hasEditCount && !hasMultipleWords
+ && !hasProximityErrors && isSameLength;
+
+ const float totalPrevWordsLanguageCost = dicNode->getTotalPrevWordsLanguageCost();
+ const float languageImprobability = isExactMatch ? 0.0f : dicNodeLanguageImprobability;
+ const float languageWeight = ScoringParams::DISTANCE_WEIGHT_LANGUAGE;
+ // TODO: Caveat: The following equation should be:
+ // totalPrevWordsLanguageCost + (languageImprobability * languageWeight);
+ return (totalPrevWordsLanguageCost + languageImprobability) * languageWeight;
+ }
+
+ AK_FORCE_INLINE bool needsToNormalizeCompoundDistance() const {
+ return false;
+ }
+
+ AK_FORCE_INLINE float getAdditionalProximityCost() const {
+ return ScoringParams::ADDITIONAL_PROXIMITY_COST;
+ }
+
+ AK_FORCE_INLINE float getSubstitutionCost() const {
+ return ScoringParams::SUBSTITUTION_COST;
+ }
+
+ AK_FORCE_INLINE float getSpaceSubstitutionCost() const {
+ return ScoringParams::SPACE_SUBSTITUTION_COST;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypingWeighting);
+ static const TypingWeighting sInstance;
+
+ TypingWeighting() {}
+ ~TypingWeighting() {}
+};
+} // namespace latinime
+#endif // LATINIME_TYPING_WEIGHTING_H
diff --git a/native/jni/src/suggest/typing_suggest.h b/native/jni/src/suggest/typing_suggest.h
deleted file mode 100644
index 678037aa2..000000000
--- a/native/jni/src/suggest/typing_suggest.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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_TYPING_SUGGEST_H
-#define LATINIME_TYPING_SUGGEST_H
-
-#include "defines.h"
-#include "suggest_interface.h"
-
-namespace latinime {
-
-class ProximityInfo;
-
-class TypingSuggest : public SuggestInterface {
- public:
- TypingSuggest() : mSuggestInterface(getTypingSuggestInstance()) {}
-
- virtual ~TypingSuggest();
-
- int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
- int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
- int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const {
- if (!mSuggestInterface) {
- return 0;
- }
- return mSuggestInterface->getSuggestions(pInfo, traverseSession, inputXs, inputYs, times,
- pointerIds, inputCodePoints, inputSize, commitPoint, outWords, frequencies,
- outputIndices, outputTypes);
- }
-
- static void setTypingSuggestFactoryMethod(SuggestInterface *(*factoryMethod)()) {
- sTypingSuggestFactoryMethod = factoryMethod;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TypingSuggest);
- static SuggestInterface *getTypingSuggestInstance() {
- if (!sTypingSuggestFactoryMethod) {
- return 0;
- }
- return sTypingSuggestFactoryMethod();
- }
-
- static SuggestInterface *(*sTypingSuggestFactoryMethod)();
- SuggestInterface *mSuggestInterface;
-};
-} // namespace latinime
-#endif // LATINIME_TYPING_SUGGEST_H
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 80ba412a3..33795cade 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -22,6 +22,7 @@
#include "char_utils.h"
#include "defines.h"
#include "dictionary.h"
+#include "digraph_utils.h"
#include "proximity_info.h"
#include "terminal_attributes.h"
#include "unigram_dictionary.h"
@@ -30,15 +31,6 @@
namespace latinime {
-const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] =
- { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS
- { 'o', 'e', 0x00F6 }, // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS
- { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS
-
-const UnigramDictionary::digraph_t UnigramDictionary::FRENCH_LIGATURES_DIGRAPHS[] =
- { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE
- { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE
-
// TODO: check the header
UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, const unsigned int flags)
: DICT_ROOT(streamStart), ROOT_POS(0),
@@ -58,7 +50,7 @@ static void addWord(int *word, int length, int probability, WordsPriorityQueue *
// Return the replacement code point for a digraph, or 0 if none.
int UnigramDictionary::getDigraphReplacement(const int *codes, const int i, const int inputSize,
- const digraph_t *const digraphs, const unsigned int digraphsSize) const {
+ const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const {
// There can't be a digraph if we don't have at least 2 characters to examine
if (i + 2 > inputSize) return false;
@@ -74,7 +66,7 @@ int UnigramDictionary::getDigraphReplacement(const int *codes, const int i, cons
// It's an interesting digraph if the second char matches too.
if (digraphs[lastDigraphIndex].second == codes[i + 1]) {
- return digraphs[lastDigraphIndex].replacement;
+ return digraphs[lastDigraphIndex].compositeGlyph;
} else {
return 0;
}
@@ -93,7 +85,7 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit
const bool useFullEditDistance, const int *codesSrc,
const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
WordsPriorityQueuePool *queuePool,
- const digraph_t *const digraphs, const unsigned int digraphsSize) const {
+ const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const {
ASSERT(sizeof(codesDest[0]) == sizeof(codesSrc[0]));
ASSERT(sizeof(xCoordinatesBuffer[0]) == sizeof(xcoordinates[0]));
ASSERT(sizeof(yCoordinatesBuffer[0]) == sizeof(ycoordinates[0]));
@@ -169,7 +161,10 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
queuePool.clearAll();
Correction masterCorrection;
masterCorrection.resetCorrection();
- if (BinaryFormat::REQUIRES_GERMAN_UMLAUT_PROCESSING & FLAGS)
+ const DigraphUtils::digraph_t *digraphs = 0;
+ const int digraphsSize =
+ DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(FLAGS, &digraphs);
+ if (digraphsSize > 0)
{ // Incrementally tune the word and try all possibilities
int codesBuffer[sizeof(*inputCodePoints) * inputSize];
int xCoordinatesBuffer[inputSize];
@@ -177,15 +172,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x
getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
xCoordinatesBuffer, yCoordinatesBuffer, inputSize, bigramMap, bigramFilter,
useFullEditDistance, inputCodePoints, inputSize, 0, codesBuffer, &masterCorrection,
- &queuePool, GERMAN_UMLAUT_DIGRAPHS, NELEMS(GERMAN_UMLAUT_DIGRAPHS));
- } else if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & FLAGS) {
- int codesBuffer[sizeof(*inputCodePoints) * inputSize];
- int xCoordinatesBuffer[inputSize];
- int yCoordinatesBuffer[inputSize];
- getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer,
- xCoordinatesBuffer, yCoordinatesBuffer, inputSize, bigramMap, bigramFilter,
- useFullEditDistance, inputCodePoints, inputSize, 0, codesBuffer, &masterCorrection,
- &queuePool, FRENCH_LIGATURES_DIGRAPHS, NELEMS(FRENCH_LIGATURES_DIGRAPHS));
+ &queuePool, digraphs, digraphsSize);
} else { // Normal processing
getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, inputCodePoints, inputSize,
bigramMap, bigramFilter, useFullEditDistance, &masterCorrection, &queuePool);
diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h
index c1955e8bb..1a01758fe 100644
--- a/native/jni/src/unigram_dictionary.h
+++ b/native/jni/src/unigram_dictionary.h
@@ -20,6 +20,7 @@
#include <map>
#include <stdint.h>
#include "defines.h"
+#include "digraph_utils.h"
namespace latinime {
@@ -29,8 +30,6 @@ class TerminalAttributes;
class WordsPriorityQueuePool;
class UnigramDictionary {
- typedef struct { int first; int second; int replacement; } digraph_t;
-
public:
// Error tolerances
static const int DEFAULT_MAX_ERRORS = 2;
@@ -57,13 +56,13 @@ class UnigramDictionary {
const bool useFullEditDistance, Correction *correction,
WordsPriorityQueuePool *queuePool) const;
int getDigraphReplacement(const int *codes, const int i, const int inputSize,
- const digraph_t *const digraphs, const unsigned int digraphsSize) const;
+ const DigraphUtils::digraph_t *const digraphs, const unsigned int digraphsSize) const;
void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo, const int *xcoordinates,
const int *ycoordinates, const int *codesBuffer, int *xCoordinatesBuffer,
int *yCoordinatesBuffer, const int codesBufferSize, const std::map<int, int> *bigramMap,
const uint8_t *bigramFilter, const bool useFullEditDistance, const int *codesSrc,
const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
- WordsPriorityQueuePool *queuePool, const digraph_t *const digraphs,
+ WordsPriorityQueuePool *queuePool, const DigraphUtils::digraph_t *const digraphs,
const unsigned int digraphsSize) const;
void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
const int *ycoordinates, const int *codes, const int inputSize,
@@ -111,9 +110,6 @@ class UnigramDictionary {
const int ROOT_POS;
const int MAX_DIGRAPH_SEARCH_DEPTH;
const int FLAGS;
-
- static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
- static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
};
} // namespace latinime
#endif // LATINIME_UNIGRAM_DICTIONARY_H
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java b/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java
new file mode 100644
index 000000000..3ff5aa485
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/internal/HermiteInterpolatorTests.java
@@ -0,0 +1,203 @@
+/*
+ * 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.internal;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class HermiteInterpolatorTests extends AndroidTestCase {
+ private final HermiteInterpolator mInterpolator = new HermiteInterpolator();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ private static final float EPSLION = 0.0000005f;
+
+ private static void assertFloatEquals(final String message, float expected, float actual) {
+ if (Math.abs(expected - actual) >= EPSLION) {
+ fail(String.format("%s expected:<%s> but was:<%s>", message, expected, actual));
+ }
+ }
+
+ // t=0 p0=(0,1)
+ // t=1 p1=(1,0)
+ // t=2 p2=(3,2)
+ // t=3 p3=(2,3)
+ // y
+ // |
+ // 3 + o p3
+ // |
+ // 2 + o p2
+ // |
+ // 1 o p0
+ // | p1
+ // 0 +---o---+---+-- x
+ // 0 1 2 3
+ private final int[] mXCoords = { 0, 1, 3, 2 };
+ private final int[] mYCoords = { 1, 0, 2, 3 };
+ private static final int p0 = 0;
+ private static final int p1 = 1;
+ private static final int p2 = 2;
+ private static final int p3 = 3;
+
+ public void testP0P1() {
+ // [(p0 p1) p2 p3]
+ mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+ mInterpolator.setInterval(p0 - 1, p0, p1, p1 + 1);
+ assertEquals("p0x", mXCoords[p0], mInterpolator.mP1X);
+ assertEquals("p0y", mYCoords[p0], mInterpolator.mP1Y);
+ assertEquals("p1x", mXCoords[p1], mInterpolator.mP2X);
+ assertEquals("p1y", mYCoords[p1], mInterpolator.mP2Y);
+ // XY-slope at p0=3.0 (-0.75/-0.25)
+ assertFloatEquals("slope x p0", -0.25f, mInterpolator.mSlope1X);
+ assertFloatEquals("slope y p0", -0.75f, mInterpolator.mSlope1Y);
+ // XY-slope at p1=1/3.0 (0.50/1.50)
+ assertFloatEquals("slope x p1", 1.50f, mInterpolator.mSlope2X);
+ assertFloatEquals("slope y p1", 0.50f, mInterpolator.mSlope2Y);
+ // t=0.0 (p0)
+ mInterpolator.interpolate(0.0f);
+ assertFloatEquals("t=0.0 x", 0.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.0 y", 1.0f, mInterpolator.mInterpolatedY);
+ // t=0.2
+ mInterpolator.interpolate(0.2f);
+ assertFloatEquals("t=0.2 x", 0.02400f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.2 y", 0.78400f, mInterpolator.mInterpolatedY);
+ // t=0.5
+ mInterpolator.interpolate(0.5f);
+ assertFloatEquals("t=0.5 x", 0.28125f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.5 y", 0.34375f, mInterpolator.mInterpolatedY);
+ // t=0.8
+ mInterpolator.interpolate(0.8f);
+ assertFloatEquals("t=0.8 x", 0.69600f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.8 y", 0.01600f, mInterpolator.mInterpolatedY);
+ // t=1.0 (p1)
+ mInterpolator.interpolate(1.0f);
+ assertFloatEquals("t=1.0 x", 1.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=1.0 y", 0.0f, mInterpolator.mInterpolatedY);
+ }
+
+ public void testP1P2() {
+ // [p0 (p1 p2) p3]
+ mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+ mInterpolator.setInterval(p1 - 1, p1, p2, p2 + 1);
+ assertEquals("p1x", mXCoords[p1], mInterpolator.mP1X);
+ assertEquals("p1y", mYCoords[p1], mInterpolator.mP1Y);
+ assertEquals("p2x", mXCoords[p2], mInterpolator.mP2X);
+ assertEquals("p2y", mYCoords[p2], mInterpolator.mP2Y);
+ // XY-slope at p1=1/3.0 (0.50/1.50)
+ assertFloatEquals("slope x p1", 1.50f, mInterpolator.mSlope1X);
+ assertFloatEquals("slope y p1", 0.50f, mInterpolator.mSlope1Y);
+ // XY-slope at p2=3.0 (1.50/0.50)
+ assertFloatEquals("slope x p2", 0.50f, mInterpolator.mSlope2X);
+ assertFloatEquals("slope y p2", 1.50f, mInterpolator.mSlope2Y);
+ // t=0.0 (p1)
+ mInterpolator.interpolate(0.0f);
+ assertFloatEquals("t=0.0 x", 1.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.0 y", 0.0f, mInterpolator.mInterpolatedY);
+ // t=0.2
+ mInterpolator.interpolate(0.2f);
+ assertFloatEquals("t=0.2 x", 1.384f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.2 y", 0.224f, mInterpolator.mInterpolatedY);
+ // t=0.5
+ mInterpolator.interpolate(0.5f);
+ assertFloatEquals("t=0.5 x", 2.125f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.5 y", 0.875f, mInterpolator.mInterpolatedY);
+ // t=0.8
+ mInterpolator.interpolate(0.8f);
+ assertFloatEquals("t=0.8 x", 2.776f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.8 y", 1.616f, mInterpolator.mInterpolatedY);
+ // t=1.0 (p2)
+ mInterpolator.interpolate(1.0f);
+ assertFloatEquals("t=1.0 x", 3.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=1.0 y", 2.0f, mInterpolator.mInterpolatedY);
+ }
+
+ public void testP2P3() {
+ // [p0 p1 (p2 p3)]
+ mInterpolator.reset(mXCoords, mYCoords, p0, p3 + 1);
+ mInterpolator.setInterval(p2 - 1, p2, p3, p3 + 1);
+ assertEquals("p2x", mXCoords[p2], mInterpolator.mP1X);
+ assertEquals("p2y", mYCoords[p2], mInterpolator.mP1Y);
+ assertEquals("p3x", mXCoords[p3], mInterpolator.mP2X);
+ assertEquals("p3y", mYCoords[p3], mInterpolator.mP2Y);
+ // XY-slope at p2=3.0 (1.50/0.50)
+ assertFloatEquals("slope x p2", 0.50f, mInterpolator.mSlope1X);
+ assertFloatEquals("slope y p2", 1.50f, mInterpolator.mSlope1Y);
+ // XY-slope at p3=1/3.0 (-0.25/-0.75)
+ assertFloatEquals("slope x p3", -0.75f, mInterpolator.mSlope2X);
+ assertFloatEquals("slope y p3", -0.25f, mInterpolator.mSlope2Y);
+ // t=0.0 (p2)
+ mInterpolator.interpolate(0.0f);
+ assertFloatEquals("t=0.0 x", 3.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.0 y", 2.0f, mInterpolator.mInterpolatedY);
+ // t=0.2
+ mInterpolator.interpolate(0.2f);
+ assertFloatEquals("t=0.2 x", 2.98400f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.2 y", 2.30400f, mInterpolator.mInterpolatedY);
+ // t=0.5
+ mInterpolator.interpolate(0.5f);
+ assertFloatEquals("t=0.5 x", 2.65625f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.5 y", 2.71875f, mInterpolator.mInterpolatedY);
+ // t=0.8
+ mInterpolator.interpolate(0.8f);
+ assertFloatEquals("t=0.8 x", 2.21600f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.8 y", 2.97600f, mInterpolator.mInterpolatedY);
+ // t=1.0 (p3)
+ mInterpolator.interpolate(1.0f);
+ assertFloatEquals("t=1.0 x", 2.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=1.0 y", 3.0f, mInterpolator.mInterpolatedY);
+ }
+
+ public void testJustP1P2() {
+ // [(p1 p2)]
+ mInterpolator.reset(mXCoords, mYCoords, p1, p2 + 1);
+ mInterpolator.setInterval(p1 - 1, p1, p2, p2 + 1);
+ assertEquals("p1x", mXCoords[p1], mInterpolator.mP1X);
+ assertEquals("p1y", mYCoords[p1], mInterpolator.mP1Y);
+ assertEquals("p2x", mXCoords[p2], mInterpolator.mP2X);
+ assertEquals("p2y", mYCoords[p2], mInterpolator.mP2Y);
+ // XY-slope at p1=1.0 (2.0/2.0)
+ assertFloatEquals("slope x p1", 2.00f, mInterpolator.mSlope1X);
+ assertFloatEquals("slope y p1", 2.00f, mInterpolator.mSlope1Y);
+ // XY-slope at p2=1.0 (2.0/2.0)
+ assertFloatEquals("slope x p2", 2.00f, mInterpolator.mSlope2X);
+ assertFloatEquals("slope y p2", 2.00f, mInterpolator.mSlope2Y);
+ // t=0.0 (p1)
+ mInterpolator.interpolate(0.0f);
+ assertFloatEquals("t=0.0 x", 1.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.0 y", 0.0f, mInterpolator.mInterpolatedY);
+ // t=0.2
+ mInterpolator.interpolate(0.2f);
+ assertFloatEquals("t=0.2 x", 1.4f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.2 y", 0.4f, mInterpolator.mInterpolatedY);
+ // t=0.5
+ mInterpolator.interpolate(0.5f);
+ assertFloatEquals("t=0.5 x", 2.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.5 y", 1.0f, mInterpolator.mInterpolatedY);
+ // t=0.8
+ mInterpolator.interpolate(0.8f);
+ assertFloatEquals("t=0.8 x", 2.6f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=0.8 y", 1.6f, mInterpolator.mInterpolatedY);
+ // t=1.0 (p2)
+ mInterpolator.interpolate(1.0f);
+ assertFloatEquals("t=1.0 x", 3.0f, mInterpolator.mInterpolatedX);
+ assertFloatEquals("t=1.0 y", 2.0f, mInterpolator.mInterpolatedY);
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 4ccbf4857..04e1f932a 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -130,7 +130,9 @@ public class InputTestsBase extends ServiceTestCase<LatinIME> {
protected void setUp() throws Exception {
super.setUp();
mTextView = new MyTextView(getContext());
- mTextView.setInputType(InputType.TYPE_CLASS_TEXT);
+ final int inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+ | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+ mTextView.setInputType(inputType);
mTextView.setEnabled(true);
setupService();
mLatinIME = getService();
@@ -138,9 +140,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIME> {
mLatinIME.onCreate();
setDebugMode(previousDebugSetting);
final EditorInfo ei = new EditorInfo();
- ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
final InputConnection ic = mTextView.onCreateInputConnection(ei);
- ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
final LayoutInflater inflater =
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ViewGroup vg = new FrameLayout(getContext());
@@ -181,17 +181,21 @@ public class InputTestsBase extends ServiceTestCase<LatinIME> {
// a message that calls it instead of calling it directly.
Looper.loop();
- // Once #quit() has been called, the message queue has an "mQuiting" field that prevents
- // any subsequent post in this queue. However the queue itself is still fully functional!
- // If we have a way of resetting "queue.mQuiting" then we can continue using it as normal,
- // coming back to this method to run the messages.
+ // Once #quit() has been called, the looper is not functional any more (it used to be,
+ // but now it SIGSEGV's if it's used again).
+ // It won't accept creating a new looper for this thread and switching to it...
+ // ...unless we can trick it into throwing out the old looper and believing it hasn't
+ // been initialized before.
MessageQueue queue = Looper.myQueue();
try {
- // However there is no way of doing it externally, and mQuiting is private.
+ // However there is no way of doing it externally, and the static ThreadLocal
+ // field into which it's stored is private.
// So... get out the big guns.
- java.lang.reflect.Field f = MessageQueue.class.getDeclaredField("mQuiting");
- f.setAccessible(true); // What do you mean "private"?
- f.setBoolean(queue, false);
+ java.lang.reflect.Field f = Looper.class.getDeclaredField("sThreadLocal");
+ f.setAccessible(true); // private lolwut
+ final ThreadLocal<Looper> a = (ThreadLocal<Looper>) f.get(looper);
+ a.set(null);
+ looper.prepare();
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {