diff options
Diffstat (limited to 'java')
31 files changed, 594 insertions, 415 deletions
diff --git a/java/res/values-fa/donottranslate-more-keys.xml b/java/res/values-fa/donottranslate-more-keys.xml new file mode 100644 index 000000000..3e13c795a --- /dev/null +++ b/java/res/values-fa/donottranslate-more-keys.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+061F: "؟" ARABIC QUESTION MARK + U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064D: "ٍ" ARABIC KASRATAN + U+064B: "ً" ARABIC FATHATAN + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0655: "ٕ" ARABIC HAMZA BELOW + U+0654: "ٔ" ARABIC HAMZA ABOVE --> + <!-- U+064F: "ُ" ARABIC DAMMA + U+064C: "ٌ" ARABIC DAMMATAN + U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+0640: "ـ" ARABIC TATWEEL --> + <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',-,:,!,؟,،,؛,ِ,َ,ٍ,ً,ٖ,ٰ,ٕ,ٔ,ُ,ٌ,ّ,ْ,ٓ,ـــ|ـ,/"</string> + <string name="keyhintlabel_for_punctuation">ً</string> + <!-- U+0661: "١" ARABIC-INDIC DIGIT ONE --> + <string name="keylabel_for_symbols_1">١</string> + <!-- U+0662: "٢" ARABIC-INDIC DIGIT TWO --> + <string name="keylabel_for_symbols_2">٢</string> + <!-- U+0663: "٣" ARABIC-INDIC DIGIT THREE --> + <string name="keylabel_for_symbols_3">٣</string> + <!-- U+0664: "٤" ARABIC-INDIC DIGIT FOUR --> + <string name="keylabel_for_symbols_4">٤</string> + <!-- U+0665: "٥" ARABIC-INDIC DIGIT FIVE --> + <string name="keylabel_for_symbols_5">٥</string> + <!-- U+0666: "٦" ARABIC-INDIC DIGIT SIX --> + <string name="keylabel_for_symbols_6">٦</string> + <!-- U+0667: "٧" ARABIC-INDIC DIGIT SEVEN --> + <string name="keylabel_for_symbols_7">٧</string> + <!-- U+0668: "٨" ARABIC-INDIC DIGIT EIGHT --> + <string name="keylabel_for_symbols_8">٨</string> + <!-- U+0669: "٩" ARABIC-INDIC DIGIT NINE --> + <string name="keylabel_for_symbols_9">٩</string> + <!-- U+0660: "٠" ARABIC-INDIC DIGIT ZERO --> + <string name="keylabel_for_symbols_0">٠</string> + <string name="additional_more_keys_for_symbols_1">1</string> + <string name="additional_more_keys_for_symbols_2">2</string> + <string name="additional_more_keys_for_symbols_3">3</string> + <string name="additional_more_keys_for_symbols_4">4</string> + <string name="additional_more_keys_for_symbols_5">5</string> + <string name="additional_more_keys_for_symbols_6">6</string> + <string name="additional_more_keys_for_symbols_7">7</string> + <string name="additional_more_keys_for_symbols_8">8</string> + <string name="additional_more_keys_for_symbols_9">9</string> + <!-- U+066B: "٫" ARABIC DECIMAL SEPARATOR + U+066C: "٬" ARABIC THOUSANDS SEPARATOR --> + <string name="additional_more_keys_for_symbols_0">0,٫,٬</string> + <!-- U+060C: "،" ARABIC COMMA --> + <string name="keylabel_for_comma">،</string> + <string name="more_keys_for_comma">"\\,"</string> + <string name="keylabel_for_symbols_question">؟</string> + <string name="keylabel_for_symbols_semicolon">؛</string> + <!-- U+066A: "٪" ARABIC PERCENT SIGN --> + <string name="keylabel_for_symbols_percent">٪</string> + <string name="more_keys_for_symbols_question">\?</string> + <string name="more_keys_for_symbols_semicolon">;</string> + <!-- U+2030: "‰" PER MILLE SIGN --> + <string name="more_keys_for_symbols_percent">%,‰</string> + <!-- U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON + U+061F: "؟" ARABIC QUESTION MARK --> + <string name="keylabel_for_apostrophe">،</string> + <string name="keylabel_for_dash">"."</string> + <string name="keyhintlabel_for_apostrophe">؟</string> + <string name="keyhintlabel_for_dash">ً</string> + <string name="more_keys_for_apostrophe">"؟,؛,!,:,-,/,\',\""</string> + <!-- U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+064C: "ٌ" ARABIC DAMMATAN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+064F: "ُ" ARABIC DAMMA --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064B: "ً" ARABIC FATHATAN + U+0640: "ـ" ARABIC TATWEEL + U+064D: "ٍ" ARABIC KASRATAN --> + <!-- U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0654: "ٔ" ARABIC HAMZA ABOVE + U+0655: "ٕ" ARABIC HAMZA BELOW --> + <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> + <string name="more_keys_for_dash">"ّ,ْ,ٌ,ٓ,ُ,ِ,َ,ً,ـــ|ـ,ٍ,ٔ,ٖ,ٕ,ٰ"</string> + <!-- U+266A: "♪" EIGHTH NOTE --> + <string name="more_keys_for_bullet">♪</string> + <!-- U+2605: "★" BLACK STAR + U+066D: "٭" ARABIC FIVE POINTED STAR --> + <string name="more_keys_for_star">★,٭</string> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- U+0029: ")" RIGHT PARENTHESIS --> + <integer name="keycode_for_left_parenthesis">0x0029</integer> + <!-- U+0028: "(" LEFT PARENTHESIS --> + <integer name="keycode_for_right_parenthesis">0x0028</integer> + <!-- U+FD3E: "﴾" ORNATE LEFT PARENTHESIS + U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS --> + <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!4,﴾|﴿,<|>,{|},[|]</string> + <string name="more_keys_for_right_parenthesis">!fixedColumnOrder!4,﴿|﴾,>|<,}|{,]|[</string> + <!-- U+003E: ">" GREATER-THAN SIGN --> + <integer name="keycode_for_less_than">0x003E</integer> + <!-- U+003C: "<" LESS-THAN SIGN --> + <integer name="keycode_for_greater_than">0x003C</integer> + <!-- U+2264: "≤" LESS-THAN OR EQUAL TO + U+2265: "≥" GREATER-THAN EQUAL TO + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + The following characters don't need BIDI mirroring. + U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <string name="more_keys_for_less_than">!fixedColumnOrder!3,‹|›,≤|≥,«|»</string> + <string name="more_keys_for_greater_than">!fixedColumnOrder!3,›|‹,≥|≤,»|«</string> + <!-- U+005D: "]" RIGHT SQUARE BRACKET --> + <integer name="keycode_for_left_square_bracket">0x005D</integer> + <!-- U+005B: "[" LEFT SQUARE BRACKET --> + <integer name="keycode_for_right_square_bracket">0x005B</integer> + <!-- U+007D: "}" RIGHT CURLY BRACKET --> + <integer name="keycode_for_left_curly_bracket">0x007D</integer> + <!-- U+007B: "{" LEFT CURLY BRACKET --> + <integer name="keycode_for_right_curly_bracket">0x007B</integer> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«,‘,’,‚,‛</string> +</resources> diff --git a/java/res/values-fa/donottranslate.xml b/java/res/values-fa/donottranslate.xml new file mode 100644 index 000000000..57de2538b --- /dev/null +++ b/java/res/values-fa/donottranslate.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- Symbols that are suggested between words --> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> +</resources> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index 1f03a05a7..f10d613f2 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -45,7 +45,7 @@ <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string> - <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Bawaan"</string> + <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string> <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kenalan"</string> <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kenalan untuk saran dan koreksi"</string> <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string> diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index d4a50b6cf..8df51d648 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -114,7 +114,7 @@ <attr name="shadowColor" format="color" /> <attr name="shadowRadius" format="float" /> - <attr name="backgroundDimAmount" format="float" /> + <attr name="backgroundDimAlpha" format="integer" /> <attr name="keyTextStyle" format="enum"> <!-- This should be aligned with Typeface.NORMAL etc. --> @@ -139,7 +139,7 @@ <enum name="alwaysDisplay" value="-1" /> </attr> <attr name="delayBeforeFadeoutLangageOnSpacebar" format="integer" /> - <attr name="finalFadeoutFactorOfLanguageOnSpacebar" format="float" /> + <attr name="finalAlphaOfLanguageOnSpacebar" format="integer" /> <!-- Key detection hysteresis distance. --> <attr name="keyHysteresisDistance" format="dimension" /> <!-- Touch noise threshold time in millisecond --> diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml index eb2f9bb03..eaca642b6 100644 --- a/java/res/values/styles.xml +++ b/java/res/values/styles.xml @@ -65,7 +65,7 @@ <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item> <item name="shadowColor">#BB000000</item> <item name="shadowRadius">2.75</item> - <item name="backgroundDimAmount">0.5</item> + <item name="backgroundDimAlpha">128</item> <!-- Common attributes of LatinKeyboardView --> <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> @@ -80,7 +80,7 @@ <item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item> <item name="durationOfFadeoutLanguageOnSpacebar">200</item> <item name="delayBeforeFadeoutLangageOnSpacebar">1200</item> - <item name="finalFadeoutFactorOfLanguageOnSpacebar">0.5</item> + <item name="finalAlphaOfLanguageOnSpacebar">128</item> </style> <style name="LatinKeyboardView" diff --git a/java/res/xml-fa/keyboard_set.xml b/java/res/xml-fa/keyboard_set.xml new file mode 100644 index 000000000..9bd105093 --- /dev/null +++ b/java/res/xml-fa/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fa" > + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_arabic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml index 2fa8b3812..b206f0e54 100644 --- a/java/res/xml-sw600dp/key_styles_common.xml +++ b/java/res/xml-sw600dp/key_styles_common.xml @@ -79,9 +79,12 @@ latin:code="@integer/key_space" latin:keyActionFlags="noKeyPreview" /> <key-style - latin:styleName="nonSpecialBackgroundSpaceKeyStyle" - latin:code="@integer/key_space" - latin:keyActionFlags="noKeyPreview" /> + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" + latin:altCode="@integer/key_space" + latin:keyActionFlags="altCodeWhileTyping" /> <key-style latin:styleName="smileyKeyStyle" latin:keyLabel=":-)" diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml index 3c2f06d02..eec35b078 100644 --- a/java/res/xml-sw600dp/row_qwerty4.xml +++ b/java/res/xml-sw600dp/row_qwerty4.xml @@ -50,10 +50,24 @@ latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="30.750%p" - latin:keyWidth="39.750%p" /> + <switch> + <case + latin:languageCode="fa" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="30.850%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="39.750%p" /> + </default> + </switch> <switch> <case latin:languageCode="iw" diff --git a/java/res/xml-sw600dp/rows_number_normal.xml b/java/res/xml-sw600dp/rows_number_normal.xml index 3704c5284..be5776b20 100644 --- a/java/res/xml-sw600dp/rows_number_normal.xml +++ b/java/res/xml-sw600dp/rows_number_normal.xml @@ -143,7 +143,7 @@ latin:keyStyle="numTabKeyStyle" latin:keyWidth="11.00%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" + latin:keyStyle="spaceKeyStyle" latin:keyWidth="27.75%p" latin:keyXPos="12.75%p" /> <Key diff --git a/java/res/xml-sw600dp/rows_phone.xml b/java/res/xml-sw600dp/rows_phone.xml index 4c896e962..e8926936f 100644 --- a/java/res/xml-sw600dp/rows_phone.xml +++ b/java/res/xml-sw600dp/rows_phone.xml @@ -112,7 +112,7 @@ latin:keyStyle="numTabKeyStyle" latin:keyWidth="11.00%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" + latin:keyStyle="spaceKeyStyle" latin:keyWidth="27.75%p" latin:keyXPos="12.75%p" /> <Key diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml index 5c35f1cfb..069fc63b9 100644 --- a/java/res/xml-sw768dp/key_styles_common.xml +++ b/java/res/xml-sw768dp/key_styles_common.xml @@ -78,9 +78,12 @@ latin:code="@integer/key_space" latin:keyActionFlags="noKeyPreview" /> <key-style - latin:styleName="nonSpecialBackgroundSpaceKeyStyle" - latin:code="@integer/key_space" - latin:keyActionFlags="noKeyPreview" /> + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" + latin:altCode="@integer/key_space" + latin:keyActionFlags="altCodeWhileTyping" /> <key-style latin:styleName="smileyKeyStyle" latin:keyLabel=":-)" diff --git a/java/res/xml-sw768dp/row_qwerty4.xml b/java/res/xml-sw768dp/row_qwerty4.xml index 24c081eb7..0aa04f8f7 100644 --- a/java/res/xml-sw768dp/row_qwerty4.xml +++ b/java/res/xml-sw768dp/row_qwerty4.xml @@ -76,10 +76,30 @@ </switch> </default> </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="31.250%p" - latin:keyWidth="37.500%p" /> + <switch> + <case + latin:languageCode="fa" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="29.453%p" /> + <!-- U+200C: "" ZERO WIDTH NON-JOINER + U+200D: "" ZERO WIDTH JOINER --> + <Key + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" + latin:altCode="@integer/key_space" + latin:keyActionFlags="altCodeWhileTyping" /> + </case> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="37.500%p" /> + </default> + </switch> <switch> <case latin:languageCode="iw" diff --git a/java/res/xml-sw768dp/rows_number_normal.xml b/java/res/xml-sw768dp/rows_number_normal.xml index 8bf1a173f..2eeb6c9d4 100644 --- a/java/res/xml-sw768dp/rows_number_normal.xml +++ b/java/res/xml-sw768dp/rows_number_normal.xml @@ -145,7 +145,7 @@ latin:keyboardLayout="@xml/key_settings" latin:keyWidth="8.047%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" + latin:keyStyle="spaceKeyStyle" latin:keyXPos="13.829%p" latin:keyWidth="24.140%p" /> <Key diff --git a/java/res/xml-sw768dp/rows_phone.xml b/java/res/xml-sw768dp/rows_phone.xml index 69c9e86ff..216fbedfb 100644 --- a/java/res/xml-sw768dp/rows_phone.xml +++ b/java/res/xml-sw768dp/rows_phone.xml @@ -114,7 +114,7 @@ latin:keyboardLayout="@xml/key_settings" latin:keyWidth="8.047%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" + latin:keyStyle="spaceKeyStyle" latin:keyXPos="13.829%p" latin:keyWidth="24.140%p" /> <Key diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index f153a7d96..7b526c07f 100644 --- a/java/res/xml/key_styles_common.xml +++ b/java/res/xml/key_styles_common.xml @@ -108,6 +108,14 @@ latin:keyActionFlags="noKeyPreview|enableLongPress" latin:backgroundType="functional" /> <key-style + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" + latin:altCode="@integer/key_space" + latin:keyActionFlags="altCodeWhileTyping" + latin:backgroundType="functional" /> + <key-style latin:styleName="shortcutKeyStyle" latin:code="@integer/key_shortcut" latin:keyIcon="iconShortcutKey" @@ -123,6 +131,8 @@ latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress" latin:altCode="@integer/key_space" latin:backgroundType="functional" /> + <!-- U+200C: "" ZERO WIDTH NON-JOINER + U+200D: "" ZERO WIDTH JOINER --> <key-style latin:styleName="tabKeyStyle" latin:code="@integer/key_tab" diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index f330b268e..cdcea0ed0 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -33,6 +33,7 @@ en_GB: English Great Britain/qwerty es: Spanish/spanish et: Estonian/nordic + fa: Persian/arabic fi: Finnish/nordic fr: French/azerty fr_CA: French Canada/qwerty @@ -140,6 +141,12 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="fa" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="fi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml index 0dd2177e8..b2b47e9b5 100644 --- a/java/res/xml/row_qwerty4.xml +++ b/java/res/xml/row_qwerty4.xml @@ -59,6 +59,28 @@ </switch> <switch> <case + latin:languageCode="fa" + latin:languageSwitchKeyEnabled="true" + > + <Key + latin:keyStyle="languageSwitchKeyStyle" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <case + latin:languageCode="fa" + latin:languageSwitchKeyEnabled="false" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <case latin:languageSwitchKeyEnabled="true" > <Key diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index dc7c12ba6..dd43166af 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -36,7 +36,6 @@ import com.android.inputmethod.keyboard.KeyboardView; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Set; /** * Exposes a virtual view sub-tree for {@link KeyboardView} and generates @@ -135,9 +134,9 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info); // Add the virtual children of the root View. - // TODO(alanv): Need to assign a unique ID to each key. + // TODO: Need to assign a unique ID to each key. final Keyboard keyboard = mKeyboardView.getKeyboard(); - final Set<Key> keys = keyboard.mKeys; + final Key[] keys = keyboard.mKeys; for (Key key : keys) { final int childVirtualViewId = generateVirtualViewIdForKey(key); info.addChild(mKeyboardView, childVirtualViewId); @@ -342,8 +341,8 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat mVirtualViewIdToKey.clear(); - final Set<Key> keySet = keyboard.mKeys; - for (Key key : keySet) { + final Key[] keys = keyboard.mKeys; + for (Key key : keys) { final int virtualViewId = generateVirtualViewIdForKey(key); mVirtualViewIdToKey.put(virtualViewId, key); } diff --git a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java index eca922e68..9a523011a 100644 --- a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java @@ -17,7 +17,7 @@ package com.android.inputmethod.compat; public class MotionEventCompatUtils { - // TODO(alanv): Remove after these are added to MotionEventCompat. + // TODO: Remove after these are added to MotionEventCompat. public static final int ACTION_HOVER_ENTER = 0x9; public static final int ACTION_HOVER_EXIT = 0xA; } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index b7f1ddde6..44c6a4966 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -40,12 +40,9 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -125,16 +122,17 @@ public class Keyboard { /** Maximum column for more keys keyboard */ public final int mMaxMoreKeysKeyboardColumn; - /** List of keys and icons in this keyboard */ - public final Set<Key> mKeys; - public final Set<Key> mShiftKeys; + /** Array of keys and icons in this keyboard */ + public final Key[] mKeys; + public final Key[] mShiftKeys; + public final Key[] mAltCodeKeysWhileTyping; public final KeyboardIconsSet mIconsSet; - private final Map<Integer, Key> mKeyCache = new HashMap<Integer, Key>(); + private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>(); private final ProximityInfo mProximityInfo; - public final Map<Integer, List<Integer>> mAdditionalProximityChars; + private final Map<Integer, List<Integer>> mAdditionalProximityChars; public Keyboard(Params params) { mId = params.mId; @@ -149,8 +147,10 @@ public class Keyboard { mTopPadding = params.mTopPadding; mVerticalGap = params.mVerticalGap; - mKeys = Collections.unmodifiableSet(params.mKeys); - mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys); + mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]); + mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]); + mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray( + new Key[params.mAltCodeKeysWhileTyping.size()]); mIconsSet = params.mIconsSet; mAdditionalProximityChars = params.mAdditionalProximityChars; @@ -225,8 +225,9 @@ public class Keyboard { public int GRID_WIDTH; public int GRID_HEIGHT; - public final Set<Key> mKeys = new HashSet<Key>(); - public final Set<Key> mShiftKeys = new HashSet<Key>(); + public final ArrayList<Key> mKeys = new ArrayList<Key>(); + public final ArrayList<Key> mShiftKeys = new ArrayList<Key>(); + public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>(); public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); // TODO: Should be in Key instead of Keyboard.Params? public final Map<Integer, List<Integer>> mAdditionalProximityChars = @@ -308,12 +309,15 @@ public class Keyboard { if (key.mCode == Keyboard.CODE_SHIFT) { mShiftKeys.add(key); } + if (key.altCodeWhileTyping()) { + mAltCodeKeysWhileTyping.add(key); + } } private int mMaxHeightCount = 0; private int mMaxWidthCount = 0; - private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); - private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); + private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); + private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); private void clearHistogram() { mMostCommonKeyHeight = 0; @@ -325,7 +329,8 @@ public class Keyboard { mWidthHistogram.clear(); } - private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) { + private static int updateHistogramCounter(HashMap<Integer, Integer> histogram, + Integer key) { final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; histogram.put(key, count); return count; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index decd73d45..4c65522ec 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -44,11 +44,12 @@ import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.StringUtils; import java.util.HashMap; +import java.util.HashSet; /** * A view that renders a virtual {@link Keyboard}. * - * @attr ref R.styleable#KeyboardView_backgroundDimAmount + * @attr ref R.styleable#KeyboardView_backgroundDimAlpha * @attr ref R.styleable#KeyboardView_keyBackground * @attr ref R.styleable#KeyboardView_keyLetterRatio * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio @@ -81,7 +82,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // XML attributes protected final float mVerticalCorrection; protected final int mMoreKeysLayout; - private final float mBackgroundDimAmount; + private final int mBackgroundDimAlpha; // HORIZONTAL ELLIPSIS "...", character for popup hint. private static final String POPUP_HINT_CHAR = "\u2026"; @@ -110,12 +111,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private boolean mNeedsToDimBackground; /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/ private boolean mBufferNeedsUpdate; - /** The dirty region in the keyboard bitmap */ - private final Rect mDirtyRect = new Rect(); - /** The key to invalidate. */ - private Key mInvalidatedKey; - /** The dirty region for single key drawing */ - private final Rect mInvalidatedKeyRect = new Rect(); + /** True if all keys should be drawn */ + private boolean mInvalidateAllKeys; + /** The keys that should be drawn */ + private final HashSet<Key> mInvalidatedKeys = new HashSet<Key>(); + /** The region of invalidated keys */ + private final Rect mInvalidatedKeysRect = new Rect(); /** The keyboard bitmap buffer for faster updates */ private Bitmap mBuffer; /** The canvas for the above mutable keyboard bitmap */ @@ -335,7 +336,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mVerticalCorrection = a.getDimensionPixelOffset( R.styleable.KeyboardView_verticalCorrection, 0); mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0); - mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f); + mBackgroundDimAlpha = a.getInt(R.styleable.KeyboardView_backgroundDimAlpha, 0); a.recycle(); mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout; @@ -366,8 +367,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(keyboard); requestLayout(); - mDirtyRect.set(0, 0, getWidth(), getHeight()); - mBufferNeedsUpdate = true; invalidateAllKeys(); final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mKeyDrawParams.updateKeyHeight(keyHeight); @@ -434,47 +433,50 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (mBuffer != null) mBuffer.recycle(); mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - mDirtyRect.union(0, 0, width, height); + mInvalidateAllKeys = true; if (mCanvas != null) { mCanvas.setBitmap(mBuffer); } else { mCanvas = new Canvas(mBuffer); } } - final Canvas canvas = mCanvas; - canvas.clipRect(mDirtyRect, Op.REPLACE); - canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); if (mKeyboard == null) return; + final Canvas canvas = mCanvas; + final Paint paint = mPaint; final KeyDrawParams params = mKeyDrawParams; - if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) { - // Draw a single key. - final int keyDrawX = mInvalidatedKey.mX + mInvalidatedKey.mVisualInsetsLeft - + getPaddingLeft(); - final int keyDrawY = mInvalidatedKey.mY + getPaddingTop(); - canvas.translate(keyDrawX, keyDrawY); - onDrawKey(mInvalidatedKey, canvas, mPaint, params); - canvas.translate(-keyDrawX, -keyDrawY); - } else { + + if (mInvalidateAllKeys || mInvalidatedKeys.isEmpty()) { + mInvalidatedKeysRect.set(0, 0, getWidth(), getHeight()); + canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE); + canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); // Draw all keys. for (final Key key : mKeyboard.mKeys) { - final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft(); - final int keyDrawY = key.mY + getPaddingTop(); - canvas.translate(keyDrawX, keyDrawY); - onDrawKey(key, canvas, mPaint, params); - canvas.translate(-keyDrawX, -keyDrawY); + onDrawKey(key, canvas, paint, params); + } + } else { + // Draw invalidated keys. + for (final Key key : mInvalidatedKeys) { + final int x = key.mX + getPaddingLeft(); + final int y = key.mY + getPaddingTop(); + mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight); + canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE); + canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); + onDrawKey(key, canvas, paint, params); } } // Overlay a dark rectangle to dim the entire keyboard if (mNeedsToDimBackground) { - mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); - canvas.drawRect(0, 0, width, height, mPaint); + paint.setColor(Color.BLACK); + paint.setAlpha(mBackgroundDimAlpha); + canvas.drawRect(0, 0, width, height, paint); } - mInvalidatedKey = null; - mDirtyRect.setEmpty(); + mInvalidatedKeys.clear(); + mInvalidatedKeysRect.setEmpty(); + mInvalidateAllKeys = false; } public void dimEntireKeyboard(boolean dimmed) { @@ -486,10 +488,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { + final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft(); + final int keyDrawY = key.mY + getPaddingTop(); + canvas.translate(keyDrawX, keyDrawY); + if (!key.isSpacer()) { onDrawKeyBackground(key, canvas, params); } onDrawKeyTopVisuals(key, canvas, paint, params); + + canvas.translate(-keyDrawX, -keyDrawY); } // Draw key background. @@ -905,9 +913,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { * @see #invalidateKey(Key) */ public void invalidateAllKeys() { - mDirtyRect.union(0, 0, getWidth(), getHeight()); + mInvalidatedKeys.clear(); + mInvalidateAllKeys = true; mBufferNeedsUpdate = true; - mInvalidatedKey = null; invalidate(); } @@ -920,22 +928,21 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { */ @Override public void invalidateKey(Key key) { - if (key == null) - return; - mInvalidatedKey = key; + if (mInvalidateAllKeys) return; + if (key == null) return; + mInvalidatedKeys.add(key); final int x = key.mX + getPaddingLeft(); final int y = key.mY + getPaddingTop(); - mInvalidatedKeyRect.set(x, y, x + key.mWidth, y + key.mHeight); - mDirtyRect.union(mInvalidatedKeyRect); + mInvalidatedKeysRect.union(x, y, x + key.mWidth, y + key.mHeight); mBufferNeedsUpdate = true; - invalidate(mInvalidatedKeyRect); + invalidate(mInvalidatedKeysRect); } public void closing() { PointerTracker.dismissAllKeyPreviews(); cancelAllMessages(); - mDirtyRect.union(0, 0, getWidth(), getHeight()); + mInvalidateAllKeys = true; requestLayout(); } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 9168d0775..f4e766cb0 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; @@ -77,13 +76,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private Drawable mSpaceIcon; // Stuff to draw language name on spacebar. private ValueAnimator mLanguageOnSpacebarAnimator; - private float mFinalFadeoutFactorOfLanguageOnSpacebar; + private int mFinalAlphaOfLanguageOnSpacebar; private int mDurationOfFadeoutLanguageOnSpacebar; + private static final int ALPHA_OPAQUE = 255; private static final int LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY = 0; private static final int LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY = -1; private boolean mNeedsToDisplayLanguage; private Locale mSpacebarLocale; - private float mSpacebarTextFadeFactor = 0.0f; + private int mSpacebarTextAlpha; private final float mSpacebarTextRatio; private float mSpacebarTextSize; private final int mSpacebarTextColor; @@ -344,8 +344,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY); final int delayBeforeFadeoutLanguageOnSpacebar = a.getInt( R.styleable.LatinKeyboardView_delayBeforeFadeoutLangageOnSpacebar, 0); - mFinalFadeoutFactorOfLanguageOnSpacebar = a.getFloat( - R.styleable.LatinKeyboardView_finalFadeoutFactorOfLanguageOnSpacebar, 0.0f); + mFinalAlphaOfLanguageOnSpacebar = a.getInt( + R.styleable.LatinKeyboardView_finalAlphaOfLanguageOnSpacebar, 0); final KeyTimerParams keyTimerParams = new KeyTimerParams(a); mPointerTrackerParams = new PointerTrackerParams(a); @@ -361,8 +361,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke PointerTracker.setParameters(mPointerTrackerParams); - mLanguageOnSpacebarAnimator = ValueAnimator.ofFloat( - 1.0f, mFinalFadeoutFactorOfLanguageOnSpacebar); + mLanguageOnSpacebarAnimator = ValueAnimator.ofInt( + ALPHA_OPAQUE, mFinalAlphaOfLanguageOnSpacebar); mLanguageOnSpacebarAnimator.setStartDelay(delayBeforeFadeoutLanguageOnSpacebar); if (mDurationOfFadeoutLanguageOnSpacebar > 0) { mLanguageOnSpacebarAnimator.setDuration(mDurationOfFadeoutLanguageOnSpacebar); @@ -370,7 +370,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mLanguageOnSpacebarAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - mSpacebarTextFadeFactor = (Float)animation.getAnimatedValue(); + mSpacebarTextAlpha = (Integer)animation.getAnimatedValue(); invalidateKey(mSpaceKey); } }); @@ -794,15 +794,15 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mLanguageOnSpacebarAnimator.cancel(); mNeedsToDisplayLanguage = needsToDisplayLanguage; if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_NEVER_DISPLAY) { - mSpacebarTextFadeFactor = 0.0f; + mNeedsToDisplayLanguage = false; } else if (mDurationOfFadeoutLanguageOnSpacebar == LANGUAGE_ON_SPACEBAR_ALWAYS_DISPLAY) { - mSpacebarTextFadeFactor = 1.0f; + mSpacebarTextAlpha = ALPHA_OPAQUE; } else { if (subtypeChanged && needsToDisplayLanguage) { - mSpacebarTextFadeFactor = 1.0f; + mSpacebarTextAlpha = ALPHA_OPAQUE; mLanguageOnSpacebarAnimator.start(); } else { - mSpacebarTextFadeFactor = mFinalFadeoutFactorOfLanguageOnSpacebar; + mSpacebarTextAlpha = mFinalAlphaOfLanguageOnSpacebar; } } invalidateKey(mSpaceKey); @@ -835,12 +835,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } - private static int getSpacebarTextColor(int color, float fadeFactor) { - final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor), - Color.red(color), Color.green(color), Color.blue(color)); - return newColor; - } - // Compute width of text with specified text size using paint. private int getTextWidth(Paint paint, String text, float textSize) { paint.setTextSize(textSize); @@ -888,7 +882,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final int width = key.mWidth; final int height = key.mHeight; - // If application locales are explicitly selected. + // If input subtypes are explicitly selected. if (mNeedsToDisplayLanguage) { final String language = layoutLanguageOnSpacebar(paint, mSpacebarLocale, width, mSpacebarTextSize); @@ -898,9 +892,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final float descent = paint.descent(); final float textHeight = -paint.ascent() + descent; final float baseline = height / 2 + textHeight / 2; - paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor)); + paint.setColor(mSpacebarTextShadowColor); + paint.setAlpha(mSpacebarTextAlpha); canvas.drawText(language, width / 2, baseline - descent - 1, paint); - paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor)); + paint.setColor(mSpacebarTextColor); + paint.setAlpha(mSpacebarTextAlpha); canvas.drawText(language, width / 2, baseline - descent, paint); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 7a9915be0..607b33bb4 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -25,8 +25,6 @@ import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; import java.util.ArrayList; -import java.util.List; -import java.util.Set; public class PointerTracker { private static final String TAG = PointerTracker.class.getSimpleName(); @@ -109,7 +107,7 @@ public class PointerTracker { private static LatinKeyboardView.PointerTrackerParams sParams; private static int sTouchNoiseThresholdDistanceSquared; - private static final List<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); + private static final ArrayList<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); private static PointerTrackerQueue sPointerTrackerQueue; public final int mPointerId; @@ -120,7 +118,6 @@ public class PointerTracker { private KeyboardActionListener mListener = EMPTY_LISTENER; private Keyboard mKeyboard; - private Set<Key> mKeys; private int mKeyQuarterWidthSquared; private final TextView mKeyPreviewText; @@ -180,7 +177,7 @@ public class PointerTracker { } public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { - final List<PointerTracker> trackers = sTrackers; + final ArrayList<PointerTracker> trackers = sTrackers; // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = trackers.size(); i <= id; i++) { @@ -303,7 +300,6 @@ public class PointerTracker { private void setKeyDetectorInner(KeyDetector keyDetector) { mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); - mKeys = mKeyboard.mKeys; final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4; mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth; } @@ -326,57 +322,76 @@ public class PointerTracker { private void setReleasedKeyGraphics(Key key) { mDrawingProxy.dismissKeyPreview(this); - if (key != null && key.isEnabled()) { - key.onReleased(); - mDrawingProxy.invalidateKey(key); - - if (key.isShift()) { - for (final Key shiftKey : mKeyboard.mShiftKeys) { - if (shiftKey != key) { - shiftKey.onReleased(); - mDrawingProxy.invalidateKey(shiftKey); - } + if (key == null || !key.isEnabled()) { + return; + } + + updateReleaseKeyGraphics(key); + + if (key.isShift()) { + for (final Key shiftKey : mKeyboard.mShiftKeys) { + if (shiftKey != key) { + updateReleaseKeyGraphics(shiftKey); } } + } - if (key.altCodeWhileTyping()) { - final Key altKey = mKeyboard.getKey(key.mAltCode); - if (altKey != null) { - altKey.onReleased(); - mDrawingProxy.invalidateKey(altKey); + if (key.altCodeWhileTyping()) { + final int altCode = key.mAltCode; + final Key altKey = mKeyboard.getKey(altCode); + if (altKey != null) { + updateReleaseKeyGraphics(altKey); + } + for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { + if (k != key && k.mAltCode == altCode) { + updateReleaseKeyGraphics(k); } } } } private void setPressedKeyGraphics(Key key) { - if (key != null && key.isEnabled()) { - if (!key.noKeyPreview()) { - mDrawingProxy.showKeyPreview(this); - } - key.onPressed(); - mDrawingProxy.invalidateKey(key); - - if (key.isShift()) { - for (final Key shiftKey : mKeyboard.mShiftKeys) { - if (shiftKey != key) { - shiftKey.onPressed(); - mDrawingProxy.invalidateKey(shiftKey); - } + if (key == null || !key.isEnabled()) { + return; + } + + if (!key.noKeyPreview()) { + mDrawingProxy.showKeyPreview(this); + } + updatePressKeyGraphics(key); + + if (key.isShift()) { + for (final Key shiftKey : mKeyboard.mShiftKeys) { + if (shiftKey != key) { + updatePressKeyGraphics(shiftKey); } } + } - if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) { - final Key altKey = mKeyboard.getKey(key.mAltCode); - if (altKey != null) { - // TODO: Show altKey's preview. - altKey.onPressed(); - mDrawingProxy.invalidateKey(altKey); + if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) { + final int altCode = key.mAltCode; + final Key altKey = mKeyboard.getKey(altCode); + if (altKey != null) { + updatePressKeyGraphics(altKey); + } + for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { + if (k != key && k.mAltCode == altCode) { + updatePressKeyGraphics(k); } } } } + private void updateReleaseKeyGraphics(Key key) { + key.onReleased(); + mDrawingProxy.invalidateKey(key); + } + + private void updatePressKeyGraphics(Key key) { + key.onPressed(); + mDrawingProxy.invalidateKey(key); + } + public int getLastX() { return mLastX; } @@ -691,7 +706,7 @@ public class PointerTracker { } private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, Key newKey) { - if (mKeys == null || mKeyDetector == null) + if (mKeyDetector == null) throw new NullPointerException("keyboard and/or key detector not set"); Key curKey = mCurrentKey; if (newKey == curKey) { diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 8a65a5fc6..e2a48306a 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; public class ProximityInfo { public static final int MAX_PROXIMITY_CHARS_SIZE = 16; @@ -50,8 +49,8 @@ public class ProximityInfo { private final String mLocaleStr; ProximityInfo(String localeStr, int gridWidth, int gridHeight, int minWidth, int height, - int mostCommonKeyWidth, - int mostCommonKeyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection, + int mostCommonKeyWidth, int mostCommonKeyHeight, final Key[] keys, + TouchPositionCorrection touchPositionCorrection, Map<Integer, List<Integer>> additionalProximityChars) { if (TextUtils.isEmpty(localeStr)) { mLocaleStr = ""; @@ -77,8 +76,8 @@ public class ProximityInfo { } public static ProximityInfo createDummyProximityInfo() { - return new ProximityInfo("", 1, 1, 1, 1, 1, 1, Collections.<Key> emptySet(), - null, Collections.<Integer, List<Integer>> emptyMap()); + return new ProximityInfo("", 1, 1, 1, 1, 1, 1, EMPTY_KEY_ARRAY, null, + Collections.<Integer, List<Integer>> emptyMap()); } public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) { @@ -106,8 +105,7 @@ public class ProximityInfo { private native void releaseProximityInfoNative(long nativeProximityInfo); private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth, - int keyboardHeight, Set<Key> keys, - TouchPositionCorrection touchPositionCorrection) { + int keyboardHeight, final Key[] keys, TouchPositionCorrection touchPositionCorrection) { final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE); for (int i = 0; i < mGridSize; ++i) { @@ -117,7 +115,7 @@ public class ProximityInfo { gridNeighborKeys[i][j].mCode; } } - final int keyCount = keys.size(); + final int keyCount = keys.length; final int[] keyXCoordinates = new int[keyCount]; final int[] keyYCoordinates = new int[keyCount]; final int[] keyWidths = new int[keyCount]; @@ -132,8 +130,8 @@ public class ProximityInfo { sweetSpotCenterYs = new float[keyCount]; sweetSpotRadii = new float[keyCount]; calculateSweetSpotParams = true; - int i = 0; - for (final Key key : keys) { + for (int i = 0; i < keyCount; i++) { + final Key key = keys[i]; keyXCoordinates[i] = key.mX; keyYCoordinates[i] = key.mY; keyWidths[i] = key.mWidth; @@ -156,7 +154,6 @@ public class ProximityInfo { hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); } } - i++; } } else { sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; @@ -186,17 +183,17 @@ public class ProximityInfo { } } - private void computeNearestNeighbors(int defaultWidth, Set<Key> keys, + private void computeNearestNeighbors(int defaultWidth, final Key[] keys, TouchPositionCorrection touchPositionCorrection, Map<Integer, List<Integer>> additionalProximityChars) { - final Map<Integer, Key> keyCodeMap = new HashMap<Integer, Key>(); + final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>(); for (final Key key : keys) { keyCodeMap.put(key.mCode, key); } final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE); final int threshold = thresholdBase * thresholdBase; // Round-up so we don't have any pixels outside the grid - final Key[] neighborKeys = new Key[keys.size()]; + final Key[] neighborKeys = new Key[keys.length]; final int gridWidth = mGridWidth * mCellWidth; final int gridHeight = mGridHeight * mCellHeight; for (int x = 0; x < gridWidth; x += mCellWidth) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index ca711ec7d..9b9c86179 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -24,7 +24,6 @@ import android.util.Log; import com.android.inputmethod.latin.R; import java.util.HashMap; -import java.util.Map; public class KeyboardIconsSet { private static final String TAG = KeyboardIconsSet.class.getSimpleName(); @@ -35,8 +34,9 @@ public class KeyboardIconsSet { private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1]; - private static final Map<Integer, Integer> ATTR_ID_TO_ICON_ID = new HashMap<Integer, Integer>(); - private static final Map<String, Integer> NAME_TO_ICON_ID = new HashMap<String, Integer>(); + private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID + = new HashMap<Integer, Integer>(); + private static final HashMap<String, Integer> NAME_TO_ICON_ID = new HashMap<String, Integer>(); private static final String[] ICON_NAMES = new String[NUM_ICONS + 1]; private static final int ATTR_UNDEFINED = 0; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index dc5bd2efc..def639dce 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -72,6 +72,7 @@ import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -925,10 +926,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final List<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords = SuggestedWords.Builder.getFromApplicationSpecifiedCompletions( applicationSpecifiedCompletions); - SuggestedWords.Builder builder = new SuggestedWords.Builder() - .addWords(applicationSuggestedWords) - .setTypedWordValid(false) - .setHasMinimalSuggestion(false); + SuggestedWords.Builder builder = new SuggestedWords.Builder(applicationSuggestedWords, + false /* typedWordValid */, + false /* hasMinimalSuggestion */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */); // When in fullscreen mode, show completions generated by the application final SuggestedWords words = builder.build(); final boolean isAutoCorrection = false; @@ -1767,6 +1769,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // getSuggestedWordBuilder handles gracefully a null value of prevWord final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(mWordComposer, prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); + final SuggestedWords suggestions = builder.build(); // Basically, we update the suggestion strip only when suggestion count > 1. However, // there is an exception: We update the suggestion strip whenever typed word's length @@ -1774,16 +1777,24 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // in most cases, suggestion count is 1 when typed word's length is 1, but we do always // need to clear the previous state when the user starts typing a word (i.e. typed word's // length == 1). - if (builder.size() > 1 || typedWord.length() == 1 || !builder.allowsToBeAutoCorrected() + if (suggestions.size() > 1 || typedWord.length() == 1 + || !suggestions.mAllowsToBeAutoCorrected || mSuggestionsView.isShowingAddToDictionaryHint()) { - showSuggestions(builder.build(), typedWord); + showSuggestions(suggestions, typedWord); } else { SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); if (previousSuggestions == mSettingsValues.mSuggestPuncList) { previousSuggestions = SuggestedWords.EMPTY; } - final SuggestedWords.Builder obsoleteSuggestionsBuilder = new SuggestedWords.Builder() - .addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); + final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = + SuggestedWords.Builder.getTypedWordAndPreviousSuggestions( + typedWord, previousSuggestions); + final SuggestedWords.Builder obsoleteSuggestionsBuilder = + new SuggestedWords.Builder(typedWordAndPreviousSuggestions, + false /* typedWordValid */, + false /* hasMinimalSuggestion */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */); showSuggestions(obsoleteSuggestionsBuilder.build(), typedWord); } } diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 7e7702002..0a4aea140 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -183,9 +183,11 @@ public class SettingsValues { KeySpecParser.getLabel(puncSpec))); } } - final SuggestedWords.Builder builder = new SuggestedWords.Builder() - .addWords(puncList) - .setIsPunctuationSuggestions(); + final SuggestedWords.Builder builder = new SuggestedWords.Builder(puncList, + false /* typedWordValid */, + false /* hasMinimalSuggestion */, + false /* allowsToBeAutoCorrected */, + true /* isPunctuationSuggestions */); return builder.build(); } @@ -203,9 +205,11 @@ public class SettingsValues { } } } - final SuggestedWords.Builder builder = new SuggestedWords.Builder() - .addWords(puncOutputTextList) - .setIsPunctuationSuggestions(); + final SuggestedWords.Builder builder = new SuggestedWords.Builder(puncOutputTextList, + false /* typedWordValid */, + false /* hasMinimalSuggestion */, + false /* allowsToBeAutoCorrected */, + true /* isPunctuationSuggestions */); return builder.build(); } diff --git a/java/src/com/android/inputmethod/latin/StringBuilderPool.java b/java/src/com/android/inputmethod/latin/StringBuilderPool.java deleted file mode 100644 index a663ed43e..000000000 --- a/java/src/com/android/inputmethod/latin/StringBuilderPool.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.latin; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A pool of string builders to be used from anywhere. - */ -public class StringBuilderPool { - // Singleton - private static final StringBuilderPool sInstance = new StringBuilderPool(); - private static final boolean DEBUG = false; - private StringBuilderPool() {} - // TODO: Make this a normal array with a size of 20, or a ConcurrentQueue - private final List<StringBuilder> mPool = - Collections.synchronizedList(new ArrayList<StringBuilder>()); - - public static StringBuilder getStringBuilder(final int initialSize) { - // TODO: although the pool is synchronized, the following is not thread-safe. - // Two threads entering this at the same time could take the same size of the pool and the - // second to attempt removing this index from the pool would crash with an - // IndexOutOfBoundsException. - // At the moment this pool is only used in Suggest.java and only in one thread so it's - // okay. The simplest thing to do here is probably to replace the ArrayList with a - // ConcurrentQueue. - final int poolSize = sInstance.mPool.size(); - final StringBuilder sb = poolSize > 0 ? (StringBuilder) sInstance.mPool.remove(poolSize - 1) - : new StringBuilder(initialSize); - sb.setLength(0); - return sb; - } - - public static void recycle(final StringBuilder garbage) { - if (DEBUG) { - final int gid = garbage.hashCode(); - for (final StringBuilder q : sInstance.mPool) { - if (gid == q.hashCode()) throw new RuntimeException("Duplicate id " + gid); - } - } - sInstance.mPool.add(garbage); - } - - public static void ensureCapacity(final int capacity, final int initialSize) { - for (int i = sInstance.mPool.size(); i < capacity; ++i) { - final StringBuilder sb = new StringBuilder(initialSize); - sInstance.mPool.add(sb); - } - } - - public static int getSize() { - return sInstance.mPool.size(); - } -} diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java index 81c3b4edf..7b34cae63 100644 --- a/java/src/com/android/inputmethod/latin/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -142,7 +142,7 @@ public class StringUtils { for (int j = 0; j < i; j++) { CharSequence previous = suggestions.get(j); if (TextUtils.equals(cur, previous)) { - removeFromSuggestions(suggestions, i); + suggestions.remove(i); i--; break; } @@ -151,14 +151,6 @@ public class StringUtils { } } - private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions, - final int index) { - final CharSequence garbage = suggestions.remove(index); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - } - } - public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { if (returnsNameInThisLocale) { return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index e04a4e8d1..4dee4f3b4 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -98,7 +98,7 @@ public class Suggest implements Dictionary.WordCallback { private int[] mBigramScores = new int[PREF_MAX_BIGRAMS]; private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>(); - ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); + private ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); private CharSequence mConsideredWord; // TODO: Remove these member variables by passing more context to addWord() callback method @@ -122,7 +122,6 @@ public class Suggest implements Dictionary.WordCallback { private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { mWhiteListDictionary = new WhitelistDictionary(context, locale); addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); - StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength()); } private void initAsynchronously(final Context context, final int dictionaryResId, @@ -181,7 +180,7 @@ public class Suggest implements Dictionary.WordCallback { return mUnigramDictionaries; } - public int getApproxMaxWordLength() { + public static int getApproxMaxWordLength() { return APPROX_MAX_WORD_LENGTH; } @@ -216,27 +215,11 @@ public class Suggest implements Dictionary.WordCallback { mAutoCorrectionThreshold = threshold; } - /** - * Number of suggestions to generate from the input key sequence. This has - * to be a number between 1 and 100 (inclusive). - * @param maxSuggestions - * @throws IllegalArgumentException if the number is out of range - */ - public void setMaxSuggestions(int maxSuggestions) { - if (maxSuggestions < 1 || maxSuggestions > 100) { - throw new IllegalArgumentException("maxSuggestions must be between 1 and 100"); - } - mPrefMaxSuggestions = maxSuggestions; - mScores = new int[mPrefMaxSuggestions]; - mBigramScores = new int[PREF_MAX_BIGRAMS]; - collectGarbage(mSuggestions, mPrefMaxSuggestions); - StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength()); - } - - private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) { + private static CharSequence capitalizeWord(final boolean all, final boolean first, + final CharSequence word) { if (TextUtils.isEmpty(word) || !(all || first)) return word; final int wordLength = word.length(); - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); // TODO: Must pay attention to locale when changing case. if (all) { sb.append(word.toString().toUpperCase()); @@ -250,12 +233,7 @@ public class Suggest implements Dictionary.WordCallback { } protected void addBigramToSuggestions(CharSequence bigram) { - // TODO: Try to be a little more shrewd with resource allocation. - // At the moment we copy this object because the StringBuilders are pooled (see - // StringBuilderPool.java) and when we are finished using mSuggestions and - // mBigramSuggestions we will take everything from both and insert them back in the - // pool, so we can't allow the same object to be in both lists at the same time. - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); sb.append(bigram); mSuggestions.add(sb); } @@ -266,7 +244,7 @@ public class Suggest implements Dictionary.WordCallback { mIsFirstCharCapitalized = false; mIsAllUpperCase = false; mTrailingSingleQuotesCount = 0; - collectGarbage(mSuggestions, mPrefMaxSuggestions); + mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions); Arrays.fill(mScores, 0); // Treating USER_TYPED as UNIGRAM suggestion for logging now. @@ -274,7 +252,7 @@ public class Suggest implements Dictionary.WordCallback { mConsideredWord = ""; Arrays.fill(mBigramScores, 0); - collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS); + mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS); CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) { @@ -291,10 +269,12 @@ public class Suggest implements Dictionary.WordCallback { StringUtils.removeDupes(mSuggestions); - return new SuggestedWords.Builder() - .addWords(SuggestedWords.Builder.getFromCharSequenceList(mSuggestions)) - .setAllowsToBeAutoCorrected(false) - .setHasAutoCorrection(false); + return new SuggestedWords.Builder( + SuggestedWords.Builder.getFromCharSequenceList(mSuggestions), + false /* typedWordValid */, + false /* hasMinimalSuggestion */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */); } // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder @@ -305,7 +285,7 @@ public class Suggest implements Dictionary.WordCallback { mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); mIsAllUpperCase = wordComposer.isAllUpperCase(); mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); - collectGarbage(mSuggestions, mPrefMaxSuggestions); + mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions); Arrays.fill(mScores, 0); final String typedWord = wordComposer.getTypedWord(); @@ -328,7 +308,7 @@ public class Suggest implements Dictionary.WordCallback { if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) { // At first character typed, search only the bigrams Arrays.fill(mBigramScores, 0); - collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS); + mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS); if (!TextUtils.isEmpty(prevWordForBigram)) { CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); @@ -413,6 +393,7 @@ public class Suggest implements Dictionary.WordCallback { StringUtils.removeDupes(mSuggestions); final SuggestedWords.Builder builder; + final ArrayList<SuggestedWords.SuggestedWordInfo> scoreInfoList; if (DBG) { // TODO: this doesn't take into account the fact that removing dupes from mSuggestions // may have made mScores[] and mSuggestions out of sync. @@ -421,8 +402,7 @@ public class Suggest implements Dictionary.WordCallback { double normalizedScore = BinaryDictionary.calcNormalizedScore( typedWord, autoCorrectionSuggestion.toString(), autoCorrectionSuggestionScore); - ArrayList<SuggestedWords.SuggestedWordInfo> scoreInfoList = - new ArrayList<SuggestedWords.SuggestedWordInfo>(); + scoreInfoList = new ArrayList<SuggestedWords.SuggestedWordInfo>(); scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(autoCorrectionSuggestion, "+", false)); final int suggestionsSize = mSuggestions.size(); @@ -446,14 +426,8 @@ public class Suggest implements Dictionary.WordCallback { scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(mSuggestions.get(i), "--", false)); } - builder = new SuggestedWords.Builder().addWords(scoreInfoList) - .setAllowsToBeAutoCorrected(allowsToBeAutoCorrected) - .setHasAutoCorrection(hasAutoCorrection); } else { - builder = new SuggestedWords.Builder() - .addWords(SuggestedWords.Builder.getFromCharSequenceList(mSuggestions)) - .setAllowsToBeAutoCorrected(allowsToBeAutoCorrected) - .setHasAutoCorrection(hasAutoCorrection); + scoreInfoList = SuggestedWords.Builder.getFromCharSequenceList(mSuggestions); } boolean autoCorrectionAvailable = hasAutoCorrection; @@ -463,10 +437,20 @@ public class Suggest implements Dictionary.WordCallback { } // Don't auto-correct words with multiple capital letter autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); - builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( - autoCorrectionAvailable); - if (allowsToBeAutoCorrected && builder.size() > 1 && mAutoCorrectionThreshold > 0 - && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord, builder.getWord(1))) { + final boolean shouldBlockAutoCorrectionBySatefyNet; + if (allowsToBeAutoCorrected && scoreInfoList.size() > 1 && mAutoCorrectionThreshold > 0 + && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord, + scoreInfoList.get(1).mWord)) { + shouldBlockAutoCorrectionBySatefyNet = true; + } else { + shouldBlockAutoCorrectionBySatefyNet = false; + } + builder = new SuggestedWords.Builder(scoreInfoList, + !allowsToBeAutoCorrected /* typedWordValid */, + autoCorrectionAvailable /* hasMinimalSuggestion */, + allowsToBeAutoCorrected /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */); + if (shouldBlockAutoCorrectionBySatefyNet) { builder.setShouldBlockAutoCorrectionBySafetyNet(); } return builder; @@ -542,7 +526,7 @@ public class Suggest implements Dictionary.WordCallback { System.arraycopy(sortedScores, pos, sortedScores, pos + 1, prefMaxSuggestions - pos - 1); sortedScores[pos] = score; - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); // TODO: Must pay attention to locale when changing case. if (mIsAllUpperCase) { sb.append(new String(word, offset, length).toUpperCase()); @@ -559,10 +543,7 @@ public class Suggest implements Dictionary.WordCallback { } suggestions.add(pos, sb); if (suggestions.size() > prefMaxSuggestions) { - final CharSequence garbage = suggestions.remove(prefMaxSuggestions); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - } + suggestions.remove(prefMaxSuggestions); } else { LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog); } @@ -573,40 +554,22 @@ public class Suggest implements Dictionary.WordCallback { // TODO This is almost O(n^2). Might need fix. // search whether the word appeared in bigram data int bigramSuggestSize = mBigramSuggestions.size(); - for(int i = 0; i < bigramSuggestSize; i++) { - if(mBigramSuggestions.get(i).length() == length) { + for (int i = 0; i < bigramSuggestSize; i++) { + if (mBigramSuggestions.get(i).length() == length) { boolean chk = true; - for(int j = 0; j < length; j++) { - if(mBigramSuggestions.get(i).charAt(j) != word[offset+j]) { + for (int j = 0; j < length; j++) { + if (mBigramSuggestions.get(i).charAt(j) != word[offset+j]) { chk = false; break; } } - if(chk) return i; + if (chk) return i; } } return -1; } - private static void collectGarbage(ArrayList<CharSequence> suggestions, - int prefMaxSuggestions) { - int poolSize = StringBuilderPool.getSize(); - int garbageSize = suggestions.size(); - while (poolSize < prefMaxSuggestions && garbageSize > 0) { - final CharSequence garbage = suggestions.get(garbageSize - 1); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - poolSize++; - } - garbageSize--; - } - if (poolSize == prefMaxSuggestions + 1) { - Log.w("Suggest", "String pool got too big: " + poolSize); - } - suggestions.clear(); - } - public void close() { final Set<Dictionary> dictionaries = new HashSet<Dictionary>(); dictionaries.addAll(mUnigramDictionaries.values()); diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 7dd85f65b..bc89941a1 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin; -import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; @@ -26,21 +25,25 @@ import java.util.List; public class SuggestedWords { public static final SuggestedWords EMPTY = new SuggestedWords(false, false, false, false, - Collections.<SuggestedWordInfo>emptyList()); + false, Collections.<SuggestedWordInfo>emptyList()); public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; + public final boolean mAllowsToBeAutoCorrected; private final List<SuggestedWordInfo> mSuggestedWordInfoList; - SuggestedWords(boolean typedWordValid, - boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions, - boolean shouldBlockAutoCorrectionBySafetyNet, - List<SuggestedWordInfo> suggestedWordInfoList) { + SuggestedWords(final boolean typedWordValid, + final boolean hasAutoCorrectionCandidate, + final boolean isPunctuationSuggestions, + final boolean shouldBlockAutoCorrectionBySafetyNet, + final boolean allowsToBeAutoCorrected, + final List<SuggestedWordInfo> suggestedWordInfoList) { mTypedWordValid = typedWordValid; mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate && !shouldBlockAutoCorrectionBySafetyNet; mIsPunctuationSuggestions = isPunctuationSuggestions; + mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; mSuggestedWordInfoList = suggestedWordInfoList; } @@ -74,44 +77,26 @@ public class SuggestedWords { } public static class Builder { - private boolean mTypedWordValid; - private boolean mHasMinimalSuggestion; - private boolean mIsPunctuationSuggestions; + private final boolean mTypedWordValid; + private final boolean mHasMinimalSuggestion; + private final boolean mIsPunctuationSuggestions; private boolean mShouldBlockAutoCorrectionBySafetyNet; - private boolean mAllowsToBeAutoCorrected; - private boolean mHasAutoCorrection; - private List<SuggestedWordInfo> mSuggestedWordInfoList = - new ArrayList<SuggestedWordInfo>(); - - public Builder() { - // Nothing to do here. - } - - // TODO: the following method is a wrapper to satisfy tests. Update tests and remove it. - public Builder addWords(final List<CharSequence> words, - final List<SuggestedWordInfo> suggestedWordInfoList) { - return addWords(suggestedWordInfoList); - } - - public Builder addWords(List<SuggestedWordInfo> suggestedWordInfoList) { - final int N = suggestedWordInfoList.size(); - for (int i = 0; i < N; ++i) { - SuggestedWordInfo suggestedWordInfo = suggestedWordInfoList.get(i); - addWord(suggestedWordInfo.mWord, suggestedWordInfo); - } - return this; - } - - /* package for tests */ - Builder addWord(CharSequence word, SuggestedWordInfo suggestedWordInfo) { - if (!TextUtils.isEmpty(suggestedWordInfo.mWord)) { - // It's okay if suggestedWordInfo is null since it's checked where it's used. - mSuggestedWordInfoList.add(suggestedWordInfo); - } - return this; + private final boolean mAllowsToBeAutoCorrected; + private final List<SuggestedWordInfo> mSuggestedWordInfoList; + + public Builder(final List<SuggestedWordInfo> suggestedWordInfoList, + final boolean typedWordValid, + final boolean hasMinimalSuggestion, + final boolean allowsToBeAutoCorrected, + final boolean isPunctuationSuggestions) { + mSuggestedWordInfoList = suggestedWordInfoList; + mTypedWordValid = typedWordValid; + mHasMinimalSuggestion = hasMinimalSuggestion; + mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; + mIsPunctuationSuggestions = isPunctuationSuggestions; } - public static List<SuggestedWordInfo> getFromCharSequenceList( + public static ArrayList<SuggestedWordInfo> getFromCharSequenceList( final List<CharSequence> wordList) { final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); for (CharSequence word : wordList) { @@ -129,62 +114,35 @@ public class SuggestedWords { return result; } - public Builder setTypedWordValid(boolean typedWordValid) { - mTypedWordValid = typedWordValid; - return this; - } - - public Builder setHasMinimalSuggestion(boolean hasMinimalSuggestion) { - mHasMinimalSuggestion = hasMinimalSuggestion; - return this; - } - - public Builder setIsPunctuationSuggestions() { - mIsPunctuationSuggestions = true; - return this; - } - public Builder setShouldBlockAutoCorrectionBySafetyNet() { mShouldBlockAutoCorrectionBySafetyNet = true; return this; } - public Builder setAllowsToBeAutoCorrected(final boolean allowsToBeAutoCorrected) { - mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; - return this; - } - - public Builder setHasAutoCorrection(final boolean hasAutoCorrection) { - mHasAutoCorrection = hasAutoCorrection; - return this; - } - // Should get rid of the first one (what the user typed previously) from suggestions // and replace it with what the user currently typed. - public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord, - SuggestedWords previousSuggestions) { - mSuggestedWordInfoList.clear(); + public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions( + final CharSequence typedWord, final SuggestedWords previousSuggestions) { + final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>(); final HashSet<String> alreadySeen = new HashSet<String>(); - addWord(typedWord, new SuggestedWordInfo(typedWord, null, false)); + suggestionsList.add(new SuggestedWordInfo(typedWord, null, false)); alreadySeen.add(typedWord.toString()); final int previousSize = previousSuggestions.size(); for (int pos = 1; pos < previousSize; pos++) { final String prevWord = previousSuggestions.getWord(pos).toString(); // Filter out duplicate suggestion. if (!alreadySeen.contains(prevWord)) { - addWord(prevWord, new SuggestedWordInfo(prevWord, null, true)); + suggestionsList.add(new SuggestedWordInfo(prevWord, null, true)); alreadySeen.add(prevWord); } } - mTypedWordValid = false; - mHasMinimalSuggestion = false; - return this; + return suggestionsList; } public SuggestedWords build() { return new SuggestedWords(mTypedWordValid, mHasMinimalSuggestion, mIsPunctuationSuggestions, mShouldBlockAutoCorrectionBySafetyNet, - mSuggestedWordInfoList); + mAllowsToBeAutoCorrected, mSuggestedWordInfoList); } public int size() { @@ -199,10 +157,6 @@ public class SuggestedWords { return mAllowsToBeAutoCorrected; } - public boolean hasAutoCorrection() { - return mHasAutoCorrection; - } - @Override public String toString() { // Pretty-print method to help debug @@ -216,7 +170,7 @@ public class SuggestedWords { } public static class SuggestedWordInfo { - private final CharSequence mWord; + public final CharSequence mWord; private final CharSequence mDebugString; private final boolean mPreviousSuggestedWord; |