aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values/attrs.xml2
-rw-r--r--java/res/values/keypress-vibration-durations.xml9
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java15
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java16
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java18
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java26
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/WordListPreference.java20
-rw-r--r--java/src/com/android/inputmethod/latin/AssetFileAddress.java2
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java49
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java23
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java1
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java7
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java15
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java126
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java113
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java561
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java581
-rw-r--r--native/jni/Android.mk18
-rw-r--r--native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp3
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp14
-rw-r--r--native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp6
-rw-r--r--native/jni/src/bigram_dictionary.cpp15
-rw-r--r--native/jni/src/char_utils.h88
-rw-r--r--native/jni/src/correction.cpp12
-rw-r--r--native/jni/src/correction.h11
-rw-r--r--native/jni/src/dic_traverse_wrapper.cpp2
-rw-r--r--native/jni/src/dic_traverse_wrapper.h12
-rw-r--r--native/jni/src/geometry_utils.h53
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.cpp2
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h16
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h4
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_properties.h2
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_state.h8
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h2
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h2
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_utils.cpp25
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_vector.h2
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp6
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_nodes_cache.h2
-rw-r--r--native/jni/src/suggest/core/dictionary/binary_format.h (renamed from native/jni/src/binary_format.h)7
-rw-r--r--native/jni/src/suggest/core/dictionary/bloom_filter.h (renamed from native/jni/src/bloom_filter.h)0
-rw-r--r--native/jni/src/suggest/core/dictionary/char_utils.cpp (renamed from native/jni/src/char_utils.cpp)17
-rw-r--r--native/jni/src/suggest/core/dictionary/char_utils.h93
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.cpp (renamed from native/jni/src/dictionary.cpp)21
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.h (renamed from native/jni/src/dictionary.h)7
-rw-r--r--native/jni/src/suggest/core/dictionary/digraph_utils.cpp (renamed from native/jni/src/digraph_utils.cpp)9
-rw-r--r--native/jni/src/suggest/core/dictionary/digraph_utils.h (renamed from native/jni/src/digraph_utils.h)2
-rw-r--r--native/jni/src/suggest/core/dictionary/multi_bigram_map.h (renamed from native/jni/src/multi_bigram_map.h)3
-rw-r--r--native/jni/src/suggest/core/dictionary/shortcut_utils.h2
-rw-r--r--native/jni/src/suggest/core/dictionary/terminal_attributes.h (renamed from native/jni/src/terminal_attributes.h)3
-rw-r--r--native/jni/src/suggest/core/layout/additional_proximity_chars.cpp (renamed from native/jni/src/additional_proximity_chars.cpp)2
-rw-r--r--native/jni/src/suggest/core/layout/additional_proximity_chars.h (renamed from native/jni/src/additional_proximity_chars.h)0
-rw-r--r--native/jni/src/suggest/core/layout/geometry_utils.h59
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info.cpp (renamed from native/jni/src/proximity_info.cpp)23
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info.h (renamed from native/jni/src/proximity_info.h)2
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_params.cpp (renamed from native/jni/src/proximity_info_params.cpp)2
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_params.h (renamed from native/jni/src/proximity_info_params.h)0
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state.cpp (renamed from native/jni/src/proximity_info_state.cpp)24
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state.h (renamed from native/jni/src/proximity_info_state.h)5
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp (renamed from native/jni/src/proximity_info_state_utils.cpp)58
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state_utils.h (renamed from native/jni/src/proximity_info_state_utils.h)0
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_utils.h (renamed from native/jni/src/proximity_info_utils.h)21
-rw-r--r--native/jni/src/suggest/core/layout/touch_position_correction_utils.h (renamed from native/jni/src/suggest_utils.h)12
-rw-r--r--native/jni/src/suggest/core/policy/weighting.cpp1
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.cpp12
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.h12
-rw-r--r--native/jni/src/suggest/core/suggest.cpp9
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.h10
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.h9
-rw-r--r--native/jni/src/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h14
-rw-r--r--native/jni/src/suggest_options.h13
-rw-r--r--native/jni/src/unigram_dictionary.cpp21
-rw-r--r--native/jni/src/unigram_dictionary.h3
73 files changed, 1274 insertions, 1091 deletions
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 478a5c020..80bf704db 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -161,7 +161,7 @@
<declare-styleable name="SuggestionStripView">
<attr name="suggestionStripOption" format="integer">
- <!-- This should be aligned with SuggestionStripViewParams.AUTO_CORRECT_* and etc. -->
+ <!-- This should be aligned with SuggestionStripLayoutHelper.AUTO_CORRECT_* and etc. -->
<flag name="autoCorrectBold" value="0x01" />
<flag name="autoCorrectUnderline" value="0x02" />
<flag name="validTypedWordBold" value="0x04" />
diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml
index ad6beadb6..0474b1c92 100644
--- a/java/res/values/keypress-vibration-durations.xml
+++ b/java/res/values/keypress-vibration-durations.xml
@@ -39,10 +39,19 @@
<item>MODEL=(SAMSUNG-)?SCH-(J021|R530|I535|I939):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?(SCL21|SC-06D|SC-03E):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?(SHV-210[KLS]?|SPH-L710):MANUFACTURER=samsung,8</item>
+ <!-- Samsung Galaxy S4 -->
+ <item>MODEL=(SAMSUNG-)?GT-I(950[0258][G]?):MANUFACTURER=samsung,7</item>
+ <item>MODEL=(SAMSUNG-)?SGH-(I337|M919|N045):MANUFACTURER=samsung,7</item>
+ <item>MODEL=(SAMSUNG-)?SCH-(I545|I959|R970):MANUFACTURER=samsung,7</item>
+ <item>MODEL=(SAMSUNG-)?SPH-(L720):MANUFACTURER=samsung,7</item>
+ <item>MODEL=(SAMSUNG-)?(SC-04E):MANUFACTURER=samsung,7</item>
+ <item>MODEL=(SAMSUNG-)?(SHV-E300[KLS]?):MANUFACTURER=samsung,7</item>
<!-- LG Optimus G -->
<item>MODEL=LG-E97[013]|LS970|L-01E:MANUFACTURER=LGE,15</item>
<!-- HTC One X -->
<item>MODEL=HTC One X:MANUFACTURER=HTC,20</item>
+ <!-- HTC One -->
+ <item>MODEL=HTC One:MANUFACTURER=HTC,15</item>
<!-- Motorola Razor M -->
<item>MODEL=XT907:MANUFACTURER=motorola,30</item>
<!-- Sony Xperia Z -->
diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
index 5ab94a429..c5aca174a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
@@ -57,6 +57,11 @@ public class ButtonSwitcher extends FrameLayout {
super(context, attrs, defStyle);
}
+ public void reset() {
+ mStatus = NOT_INITIALIZED;
+ mAnimateToStatus = NOT_INITIALIZED;
+ }
+
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right,
final int bottom) {
@@ -64,9 +69,7 @@ public class ButtonSwitcher extends FrameLayout {
mInstallButton = (Button)findViewById(R.id.dict_install_button);
mCancelButton = (Button)findViewById(R.id.dict_cancel_button);
mDeleteButton = (Button)findViewById(R.id.dict_delete_button);
- mInstallButton.setOnClickListener(mOnClickListener);
- mCancelButton.setOnClickListener(mOnClickListener);
- mDeleteButton.setOnClickListener(mOnClickListener);
+ setInternalOnClickListener(mOnClickListener);
setButtonPositionWithoutAnimation(mStatus);
if (mAnimateToStatus != NOT_INITIALIZED) {
// We have been asked to animate before we were ready, so we took a note of it.
@@ -139,6 +142,12 @@ public class ButtonSwitcher extends FrameLayout {
public void setInternalOnClickListener(final OnClickListener listener) {
mOnClickListener = listener;
+ if (null != mInstallButton) {
+ // Already laid out : do it now
+ mInstallButton.setOnClickListener(mOnClickListener);
+ mCancelButton.setOnClickListener(mOnClickListener);
+ mDeleteButton.setOnClickListener(mOnClickListener);
+ }
}
private ViewPropertyAnimator animateButton(final View button, final int direction) {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
index de3711c27..5ad5900d4 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
@@ -16,8 +16,11 @@
package com.android.inputmethod.dictionarypack;
+import android.view.View;
+
import com.android.inputmethod.latin.CollectionUtils;
+import java.util.ArrayList;
import java.util.HashMap;
/**
@@ -37,6 +40,7 @@ public class DictionaryListInterfaceState {
}
private HashMap<String, State> mWordlistToState = CollectionUtils.newHashMap();
+ private ArrayList<View> mViewCache = CollectionUtils.newArrayList();
public boolean isOpen(final String wordlistId) {
final State state = mWordlistToState.get(wordlistId);
@@ -64,4 +68,16 @@ public class DictionaryListInterfaceState {
state.mOpen = false;
}
}
+
+ public View findFirstOrphanedView() {
+ for (final View v : mViewCache) {
+ if (null == v.getParent()) return v;
+ }
+ return null;
+ }
+
+ public View addToCacheAndReturnView(final View view) {
+ mViewCache.add(view);
+ return view;
+ }
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 618322357..4b89d20bb 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -222,7 +222,9 @@ public final class DictionarySettingsFragment extends PreferenceFragment
refreshNetworkState();
removeAnyDictSettings(prefScreen);
+ int i = 0;
for (Preference preference : prefList) {
+ preference.setOrder(i++);
prefScreen.addPreference(preference);
}
}
@@ -302,7 +304,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment
// the description.
final String key = matchLevelString + "." + description + "." + wordlistId;
final WordListPreference existingPref = prefMap.get(key);
- if (null == existingPref || hasPriority(status, existingPref.mStatus)) {
+ if (null == existingPref || existingPref.hasPriorityOver(status)) {
final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
final WordListPreference pref;
if (null != oldPreference
@@ -313,7 +315,7 @@ public final class DictionarySettingsFragment extends PreferenceFragment
// need to be the same, others have been tested through the key of the
// map. Also, status may differ so we don't want to use #equals() here.
pref = oldPreference;
- pref.mStatus = status;
+ pref.setStatus(status);
} else {
// Otherwise, discard it and create a new one instead.
pref = new WordListPreference(activity, mDictionaryListInterfaceState,
@@ -329,18 +331,6 @@ public final class DictionarySettingsFragment extends PreferenceFragment
}
}
- /**
- * Finds out if a given status has priority over another for display order.
- *
- * @param newStatus
- * @param oldStatus
- * @return whether newStatus has priority over oldStatus.
- */
- private static boolean hasPriority(final int newStatus, final int oldStatus) {
- // Both of these should be one of MetadataDbHelper.STATUS_*
- return newStatus > oldStatus;
- }
-
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 03ed267c3..1511dbcfe 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -572,7 +572,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
* If several clients use the same metadata URL, we know to only download it once, and
* dispatch the update process across all relevant clients when the download ends. This means
* several clients may share a single download ID if they share a metadata URI.
- * The dispatching is done in {@link UpdateHandler#downloadFinished(Context, Intent)}, which
+ * The dispatching is done in
+ * {@link UpdateHandler#downloadFinished(Context, android.content.Intent)}, which
* finds out about the list of relevant clients by calling this method.
*
* @param context a context instance to open the databases
@@ -863,17 +864,20 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
r.getAsString(WORDLISTID_COLUMN),
Integer.toString(STATUS_INSTALLED) },
null, null, null);
- if (c.moveToFirst()) {
- // There should never be more than one file, but if there are, it's a bug
- // and we should remove them all. I think it might happen if the power of the
- // phone is suddenly cut during an update.
- final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
- do {
- Utils.l("Setting for removal", c.getString(filenameIndex));
- filenames.add(c.getString(filenameIndex));
- } while (c.moveToNext());
+ try {
+ if (c.moveToFirst()) {
+ // There should never be more than one file, but if there are, it's a bug
+ // and we should remove them all. I think it might happen if the power of
+ // the phone is suddenly cut during an update.
+ final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
+ do {
+ Utils.l("Setting for removal", c.getString(filenameIndex));
+ filenames.add(c.getString(filenameIndex));
+ } while (c.moveToNext());
+ }
+ } finally {
+ c.close();
}
-
r.put(STATUS_COLUMN, STATUS_INSTALLED);
db.beginTransactionNonExclusive();
// Delete all old entries. There should never be any stalled entries, but if
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index 451a0fb82..7ec7e9c13 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -61,7 +61,7 @@ public final class WordListPreference extends Preference {
public final Locale mLocale;
public final String mDescription;
// The status
- public int mStatus;
+ private int mStatus;
// The size of the dictionary file
private final int mFilesize;
@@ -92,12 +92,25 @@ public final class WordListPreference extends Preference {
setKey(wordlistId);
}
- private void setStatus(final int status) {
+ public void setStatus(final int status) {
if (status == mStatus) return;
mStatus = status;
setSummary(getSummary(status));
}
+ @Override
+ public View onCreateView(final ViewGroup parent) {
+ final View orphanedView = mInterfaceState.findFirstOrphanedView();
+ if (null != orphanedView) return orphanedView; // Will be sent to onBindView
+ final View newView = super.onCreateView(parent);
+ return mInterfaceState.addToCacheAndReturnView(newView);
+ }
+
+ public boolean hasPriorityOver(final int otherPrefStatus) {
+ // Both of these should be one of MetadataDbHelper.STATUS_*
+ return mStatus > otherPrefStatus;
+ }
+
private String getSummary(final int status) {
switch (status) {
// If we are deleting the word list, for the user it's like it's already deleted.
@@ -209,6 +222,9 @@ public final class WordListPreference extends Preference {
final ButtonSwitcher buttonSwitcher =
(ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
+ // We need to clear the state of the button switcher, because we reuse views; if we didn't
+ // reset it would animate from whatever its old state was.
+ buttonSwitcher.reset();
if (mInterfaceState.isOpen(mWordlistId)) {
// The button is open.
final int previousStatus = mInterfaceState.getStatus(mWordlistId);
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index 47c750f54..875192554 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -24,7 +24,7 @@ import java.io.File;
* the package file. Open it correctly thus requires the name of the package it is in, but
* also the offset in the file and the length of this data. This class encapsulates these three.
*/
-final class AssetFileAddress {
+public final class AssetFileAddress {
public final String mFilename;
public final long mOffset;
public final long mLength;
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index a9b58de44..c038db87c 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -32,6 +32,7 @@ import com.android.inputmethod.latin.DictionaryInfoUtils.DictionaryInfo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -319,20 +320,12 @@ public final class BinaryDictionaryFileDumper {
// Try the next method.
} finally {
// Ignore exceptions while closing files.
- try {
- if (null != afd) afd.close();
- if (null != inputStream) inputStream.close();
- if (null != uncompressedStream) uncompressedStream.close();
- if (null != decryptedStream) decryptedStream.close();
- if (null != bufferedInputStream) bufferedInputStream.close();
- } catch (Exception e) {
- Log.e(TAG, "Exception while closing a file descriptor", e);
- }
- try {
- if (null != bufferedOutputStream) bufferedOutputStream.close();
- } catch (Exception e) {
- Log.e(TAG, "Exception while closing a file", e);
- }
+ closeAssetFileDescriptorAndReportAnyException(afd);
+ closeCloseableAndReportAnyException(inputStream);
+ closeCloseableAndReportAnyException(uncompressedStream);
+ closeCloseableAndReportAnyException(decryptedStream);
+ closeCloseableAndReportAnyException(bufferedInputStream);
+ closeCloseableAndReportAnyException(bufferedOutputStream);
}
}
@@ -352,6 +345,26 @@ public final class BinaryDictionaryFileDumper {
}
}
+ // Ideally the two following methods should be merged, but AssetFileDescriptor does not
+ // implement Closeable although it does implement #close(), and Java does not have
+ // structural typing.
+ private static void closeAssetFileDescriptorAndReportAnyException(
+ final AssetFileDescriptor file) {
+ try {
+ if (null != file) file.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while closing a file", e);
+ }
+ }
+
+ private static void closeCloseableAndReportAnyException(final Closeable file) {
+ try {
+ if (null != file) file.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while closing a file", e);
+ }
+ }
+
/**
* Queries a content provider for word list data for some locale and cache the returned files
*
@@ -363,8 +376,14 @@ public final class BinaryDictionaryFileDumper {
*/
public static void cacheWordListsFromContentProvider(final Locale locale,
final Context context, final boolean hasDefaultWordList) {
- final ContentProviderClient providerClient = context.getContentResolver().
+ final ContentProviderClient providerClient;
+ try {
+ providerClient = context.getContentResolver().
acquireContentProviderClient(getProviderUriBuilder("").build());
+ } catch (final SecurityException e) {
+ Log.e(TAG, "No permission to communicate with the dictionary provider", e);
+ return;
+ }
if (null == providerClient) {
Log.e(TAG, "Can't establish communication with the dictionary provider");
return;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 40e51672a..4514ec2ec 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -21,6 +21,8 @@ import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
+
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -126,21 +128,22 @@ public final class DictionaryFactory {
/**
* Create a dictionary from passed data. This is intended for unit tests only.
- * @param dictionary the file to read
- * @param startOffset the offset in the file where the data starts
- * @param length the length of the data
+ * @param dictionaryList the list of files to read, with their offsets and lengths
* @param useFullEditDistance whether to use the full edit distance in suggestions
* @return the created dictionary, or null.
*/
- public static Dictionary createDictionaryForTest(File dictionary, long startOffset, long length,
+ @UsedForTesting
+ public static Dictionary createDictionaryForTest(final AssetFileAddress[] dictionaryList,
final boolean useFullEditDistance, Locale locale) {
- if (dictionary.isFile()) {
- return new BinaryDictionary(dictionary.getAbsolutePath(), startOffset, length,
- useFullEditDistance, locale, Dictionary.TYPE_MAIN);
- } else {
- Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
- return null;
+ final DictionaryCollection dictionaryCollection =
+ new DictionaryCollection(Dictionary.TYPE_MAIN);
+ for (final AssetFileAddress address : dictionaryList) {
+ final BinaryDictionary binaryDictionary = new BinaryDictionary(address.mFilename,
+ address.mOffset, address.mLength, useFullEditDistance, locale,
+ Dictionary.TYPE_MAIN);
+ dictionaryCollection.addDictionary(binaryDictionary);
}
+ return dictionaryCollection;
}
/**
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index cebc93c18..c9a42a3a4 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -855,6 +855,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestionStrip();
+ if (mWordComposer.isComposingWord()) mConnection.finishComposingText();
resetComposingState(true /* alsoResetLastComposedWord */);
// Notify ResearchLogger
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 5d580f29b..e783e6d51 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -23,7 +23,6 @@ import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
@@ -77,9 +76,9 @@ public final class Suggest {
}
@UsedForTesting
- Suggest(final File dictionary, final long startOffset, final long length, final Locale locale) {
- final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(dictionary,
- startOffset, length /* useFullEditDistance */, false, locale);
+ Suggest(final AssetFileAddress[] dictionaryList, final Locale locale) {
+ final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(dictionaryList,
+ false /* useFullEditDistance */, locale);
mLocale = locale;
mMainDictionary = mainDict;
addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, mainDict);
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 1f453273b..7a16595a7 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -24,6 +24,9 @@ import java.util.Arrays;
import java.util.HashSet;
public final class SuggestedWords {
+ public static final int INDEX_OF_TYPED_WORD = 0;
+ public static final int INDEX_OF_AUTO_CORRECTION = 1;
+
private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST =
CollectionUtils.newArrayList(0);
public static final SuggestedWords EMPTY = new SuggestedWords(
@@ -61,12 +64,12 @@ public final class SuggestedWords {
return mSuggestedWordInfoList.size();
}
- public String getWord(int pos) {
- return mSuggestedWordInfoList.get(pos).mWord;
+ public String getWord(final int index) {
+ return mSuggestedWordInfoList.get(index).mWord;
}
- public SuggestedWordInfo getInfo(int pos) {
- return mSuggestedWordInfoList.get(pos);
+ public SuggestedWordInfo getInfo(final int index) {
+ return mSuggestedWordInfoList.get(index);
}
public boolean willAutoCorrect() {
@@ -108,8 +111,8 @@ public final class SuggestedWords {
SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_USER_TYPED));
alreadySeen.add(typedWord.toString());
final int previousSize = previousSuggestions.size();
- for (int pos = 1; pos < previousSize; pos++) {
- final SuggestedWordInfo prevWordInfo = previousSuggestions.getInfo(pos);
+ for (int index = 1; index < previousSize; index++) {
+ final SuggestedWordInfo prevWordInfo = previousSuggestions.getInfo(index);
final String prevWord = prevWordInfo.mWord;
// Filter out duplicate suggestion.
if (!alreadySeen.contains(prevWord)) {
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 0f96c54dc..949720fda 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -64,7 +64,8 @@ public final class Utils {
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete.
*/
- public static void cancelTask(AsyncTask<?, ?, ?> task, boolean mayInterruptIfRunning) {
+ public static void cancelTask(final AsyncTask<?, ?, ?> task,
+ final boolean mayInterruptIfRunning) {
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(mayInterruptIfRunning);
}
@@ -86,26 +87,34 @@ public final class Utils {
private RingCharBuffer() {
// Intentional empty constructor for singleton.
}
+
@UsedForTesting
public static RingCharBuffer getInstance() {
return sRingCharBuffer;
}
- public static RingCharBuffer init(InputMethodService context, boolean enabled,
- boolean usabilityStudy) {
- if (!(enabled || usabilityStudy)) return null;
+
+ public static RingCharBuffer init(final InputMethodService context, final boolean enabled,
+ final boolean usabilityStudy) {
+ if (!(enabled || usabilityStudy)) {
+ return null;
+ }
sRingCharBuffer.mContext = context;
sRingCharBuffer.mEnabled = true;
UsabilityStudyLogUtils.getInstance().init(context);
return sRingCharBuffer;
}
- private static int normalize(int in) {
+
+ private static int normalize(final int in) {
int ret = in % BUFSIZE;
return ret < 0 ? ret + BUFSIZE : ret;
}
+
// TODO: accept code points
@UsedForTesting
- public void push(char c, int x, int y) {
- if (!mEnabled) return;
+ public void push(final char c, final int x, final int y) {
+ if (!mEnabled) {
+ return;
+ }
mCharBuf[mEnd] = c;
mXBuf[mEnd] = x;
mYBuf[mEnd] = y;
@@ -114,52 +123,54 @@ public final class Utils {
++mLength;
}
}
+
public char pop() {
if (mLength < 1) {
return PLACEHOLDER_DELIMITER_CHAR;
- } else {
- mEnd = normalize(mEnd - 1);
- --mLength;
- return mCharBuf[mEnd];
}
+ mEnd = normalize(mEnd - 1);
+ --mLength;
+ return mCharBuf[mEnd];
}
- public char getBackwardNthChar(int n) {
+
+ public char getBackwardNthChar(final int n) {
if (mLength <= n || n < 0) {
return PLACEHOLDER_DELIMITER_CHAR;
- } else {
- return mCharBuf[normalize(mEnd - n - 1)];
}
+ return mCharBuf[normalize(mEnd - n - 1)];
}
- public int getPreviousX(char c, int back) {
- int index = normalize(mEnd - 2 - back);
+
+ public int getPreviousX(final char c, final int back) {
+ final int index = normalize(mEnd - 2 - back);
if (mLength <= back
|| Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
return INVALID_COORDINATE;
- } else {
- return mXBuf[index];
}
+ return mXBuf[index];
}
- public int getPreviousY(char c, int back) {
+
+ public int getPreviousY(final char c, final int back) {
int index = normalize(mEnd - 2 - back);
if (mLength <= back
|| Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
return INVALID_COORDINATE;
- } else {
- return mYBuf[index];
}
+ return mYBuf[index];
}
- public String getLastWord(int ignoreCharCount) {
- StringBuilder sb = new StringBuilder();
+
+ public String getLastWord(final int ignoreCharCount) {
+ final StringBuilder sb = new StringBuilder();
+ final LatinIME latinIme = (LatinIME)mContext;
int i = ignoreCharCount;
for (; i < mLength; ++i) {
- char c = mCharBuf[normalize(mEnd - 1 - i)];
- if (!((LatinIME)mContext).isWordSeparator(c)) {
+ final char c = mCharBuf[normalize(mEnd - 1 - i)];
+ if (!latinIme.isWordSeparator(c)) {
break;
}
}
for (; i < mLength; ++i) {
char c = mCharBuf[normalize(mEnd - 1 - i)];
- if (!((LatinIME)mContext).isWordSeparator(c)) {
+ if (!latinIme.isWordSeparator(c)) {
sb.append(c);
} else {
break;
@@ -167,6 +178,7 @@ public final class Utils {
}
return sb.reverse().toString();
}
+
public void reset() {
mLength = 0;
}
@@ -174,11 +186,11 @@ public final class Utils {
// Get the current stack trace
public static String getStackTrace(final int limit) {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
try {
throw new RuntimeException();
- } catch (RuntimeException e) {
- StackTraceElement[] frames = e.getStackTrace();
+ } catch (final RuntimeException e) {
+ final StackTraceElement[] frames = e.getStackTrace();
// Start at 1 because the first frame is here and we don't care about it
for (int j = 1; j < frames.length && j < limit + 1; ++j) {
sb.append(frames[j].toString() + "\n");
@@ -222,7 +234,7 @@ public final class Utils {
return OnDemandInitializationHolder.sInstance;
}
- public void init(InputMethodService ims) {
+ public void init(final InputMethodService ims) {
mIms = ims;
mDirectory = ims.getFilesDir();
}
@@ -232,17 +244,17 @@ public final class Utils {
&& (mDirectory != null && mDirectory.exists())) {
try {
mWriter = getPrintWriter(mDirectory, FILENAME, false);
- } catch (IOException e) {
+ } catch (final IOException e) {
Log.e(USABILITY_TAG, "Can't create log file.");
}
}
}
- public static void writeBackSpace(int x, int y) {
+ public static void writeBackSpace(final int x, final int y) {
UsabilityStudyLogUtils.getInstance().write("<backspace>\t" + x + "\t" + y);
}
- public void writeChar(char c, int x, int y) {
+ public static void writeChar(final char c, final int x, final int y) {
String inputChar = String.valueOf(c);
switch (c) {
case '\n':
@@ -279,15 +291,15 @@ public final class Utils {
private synchronized String getBufferedLogs() {
mWriter.flush();
- StringBuilder sb = new StringBuilder();
- BufferedReader br = getBufferedReader();
+ final StringBuilder sb = new StringBuilder();
+ final BufferedReader br = getBufferedReader();
String line;
try {
while ((line = br.readLine()) != null) {
sb.append('\n');
sb.append(line);
}
- } catch (IOException e) {
+ } catch (final IOException e) {
Log.e(USABILITY_TAG, "Can't read log file.");
} finally {
if (LatinImeLogger.sDBG) {
@@ -295,7 +307,7 @@ public final class Utils {
}
try {
br.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
// ignore.
}
}
@@ -334,10 +346,10 @@ public final class Utils {
srcStream.close();
dest.close();
destStream.close();
- } catch (FileNotFoundException e1) {
+ } catch (final FileNotFoundException e1) {
Log.w(USABILITY_TAG, e1);
return;
- } catch (IOException e2) {
+ } catch (final IOException e2) {
Log.w(USABILITY_TAG, e2);
return;
}
@@ -387,13 +399,13 @@ public final class Utils {
createLogFileIfNotExist();
try {
return new BufferedReader(new FileReader(mFile));
- } catch (FileNotFoundException e) {
+ } catch (final FileNotFoundException e) {
return null;
}
}
- private PrintWriter getPrintWriter(
- File dir, String filename, boolean renew) throws IOException {
+ private PrintWriter getPrintWriter(final File dir, final String filename,
+ final boolean renew) throws IOException {
mFile = new File(dir, filename);
if (mFile.exists()) {
if (renew) {
@@ -405,8 +417,7 @@ public final class Utils {
}
public static final class Stats {
- public static void onNonSeparator(final char code, final int x,
- final int y) {
+ public static void onNonSeparator(final char code, final int x, final int y) {
RingCharBuffer.getInstance().push(code, x, y);
LatinImeLogger.logOnInputChar();
}
@@ -430,7 +441,9 @@ public final class Utils {
public static void onAutoCorrection(final String typedWord, final String correctedWord,
final String separatorString, final WordComposer wordComposer) {
final boolean isBatchMode = wordComposer.isBatchMode();
- if (!isBatchMode && TextUtils.isEmpty(typedWord)) return;
+ if (!isBatchMode && TextUtils.isEmpty(typedWord)) {
+ return;
+ }
// TODO: this fails when the separator is more than 1 code point long, but
// the backend can't handle it yet. The only case when this happens is with
// smileys and other multi-character keys.
@@ -454,36 +467,43 @@ public final class Utils {
}
public static String getDebugInfo(final SuggestedWords suggestions, final int pos) {
- if (!LatinImeLogger.sDBG) return null;
+ if (!LatinImeLogger.sDBG) {
+ return null;
+ }
final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
- if (wordInfo == null) return null;
+ if (wordInfo == null) {
+ return null;
+ }
final String info = wordInfo.getDebugString();
- if (TextUtils.isEmpty(info)) return null;
+ if (TextUtils.isEmpty(info)) {
+ return null;
+ }
return info;
}
- public static int getAcitivityTitleResId(Context context, Class<? extends Activity> cls) {
+ public static int getAcitivityTitleResId(final Context context,
+ final Class<? extends Activity> cls) {
final ComponentName cn = new ComponentName(context, cls);
try {
final ActivityInfo ai = context.getPackageManager().getActivityInfo(cn, 0);
if (ai != null) {
return ai.labelRes;
}
- } catch (NameNotFoundException e) {
+ } catch (final NameNotFoundException e) {
Log.e(TAG, "Failed to get settings activity title res id.", e);
}
return 0;
}
- public static String getVersionName(Context context) {
+ public static String getVersionName(final Context context) {
try {
if (context == null) {
return "";
}
final String packageName = context.getPackageName();
- PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
+ final PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
return info.versionName;
- } catch (NameNotFoundException e) {
+ } catch (final NameNotFoundException e) {
Log.e(TAG, "Could not find version info.", e);
}
return "";
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index 09f81d4c7..322ae5b0f 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -61,7 +61,7 @@ public final class MoreSuggestions extends Keyboard {
super();
}
- public int layout(final SuggestedWords suggestedWords, final int fromPos,
+ public int layout(final SuggestedWords suggestedWords, final int fromIndex,
final int maxWidth, final int minWidth, final int maxRow, final Paint paint,
final Resources res) {
clearKeys();
@@ -70,53 +70,54 @@ public final class MoreSuggestions extends Keyboard {
final float padding = res.getDimension(R.dimen.more_suggestions_key_horizontal_padding);
int row = 0;
- int pos = fromPos, rowStartPos = fromPos;
+ int index = fromIndex;
+ int rowStartIndex = fromIndex;
final int size = Math.min(suggestedWords.size(), SuggestionStripView.MAX_SUGGESTIONS);
- while (pos < size) {
- final String word = suggestedWords.getWord(pos);
+ while (index < size) {
+ final String word = suggestedWords.getWord(index);
// TODO: Should take care of text x-scaling.
- mWidths[pos] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding);
- final int numColumn = pos - rowStartPos + 1;
+ mWidths[index] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding);
+ final int numColumn = index - rowStartIndex + 1;
final int columnWidth =
(maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
if (numColumn > MAX_COLUMNS_IN_ROW
- || !fitInWidth(rowStartPos, pos + 1, columnWidth)) {
+ || !fitInWidth(rowStartIndex, index + 1, columnWidth)) {
if ((row + 1) >= maxRow) {
break;
}
- mNumColumnsInRow[row] = pos - rowStartPos;
- rowStartPos = pos;
+ mNumColumnsInRow[row] = index - rowStartIndex;
+ rowStartIndex = index;
row++;
}
- mColumnOrders[pos] = pos - rowStartPos;
- mRowNumbers[pos] = row;
- pos++;
+ mColumnOrders[index] = index - rowStartIndex;
+ mRowNumbers[index] = row;
+ index++;
}
- mNumColumnsInRow[row] = pos - rowStartPos;
+ mNumColumnsInRow[row] = index - rowStartIndex;
mNumRows = row + 1;
mBaseWidth = mOccupiedWidth = Math.max(
- minWidth, calcurateMaxRowWidth(fromPos, pos));
+ minWidth, calcurateMaxRowWidth(fromIndex, index));
mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap;
- return pos - fromPos;
+ return index - fromIndex;
}
- private boolean fitInWidth(final int startPos, final int endPos, final int width) {
- for (int pos = startPos; pos < endPos; pos++) {
- if (mWidths[pos] > width)
+ private boolean fitInWidth(final int startIndex, final int endIndex, final int width) {
+ for (int index = startIndex; index < endIndex; index++) {
+ if (mWidths[index] > width)
return false;
}
return true;
}
- private int calcurateMaxRowWidth(final int startPos, final int endPos) {
+ private int calcurateMaxRowWidth(final int startIndex, final int endIndex) {
int maxRowWidth = 0;
- int pos = startPos;
+ int index = startIndex;
for (int row = 0; row < mNumRows; row++) {
final int numColumnInRow = mNumColumnsInRow[row];
int maxKeyWidth = 0;
- while (pos < endPos && mRowNumbers[pos] == row) {
- maxKeyWidth = Math.max(maxKeyWidth, mWidths[pos]);
- pos++;
+ while (index < endIndex && mRowNumbers[index] == row) {
+ maxKeyWidth = Math.max(maxKeyWidth, mWidths[index]);
+ index++;
}
maxRowWidth = Math.max(maxRowWidth,
maxKeyWidth * numColumnInRow + mDividerWidth * (numColumnInRow - 1));
@@ -130,40 +131,40 @@ public final class MoreSuggestions extends Keyboard {
{ 2, 0, 1},
};
- public int getNumColumnInRow(final int pos) {
- return mNumColumnsInRow[mRowNumbers[pos]];
+ public int getNumColumnInRow(final int index) {
+ return mNumColumnsInRow[mRowNumbers[index]];
}
- public int getColumnNumber(final int pos) {
- final int columnOrder = mColumnOrders[pos];
- final int numColumn = getNumColumnInRow(pos);
+ public int getColumnNumber(final int index) {
+ final int columnOrder = mColumnOrders[index];
+ final int numColumn = getNumColumnInRow(index);
return COLUMN_ORDER_TO_NUMBER[numColumn - 1][columnOrder];
}
- public int getX(final int pos) {
- final int columnNumber = getColumnNumber(pos);
- return columnNumber * (getWidth(pos) + mDividerWidth);
+ public int getX(final int index) {
+ final int columnNumber = getColumnNumber(index);
+ return columnNumber * (getWidth(index) + mDividerWidth);
}
- public int getY(final int pos) {
- final int row = mRowNumbers[pos];
+ public int getY(final int index) {
+ final int row = mRowNumbers[index];
return (mNumRows -1 - row) * mDefaultRowHeight + mTopPadding;
}
- public int getWidth(final int pos) {
- final int numColumnInRow = getNumColumnInRow(pos);
+ public int getWidth(final int index) {
+ final int numColumnInRow = getNumColumnInRow(index);
return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
}
- public void markAsEdgeKey(final Key key, final int pos) {
- final int row = mRowNumbers[pos];
+ public void markAsEdgeKey(final Key key, final int index) {
+ final int row = mRowNumbers[index];
if (row == 0)
key.markAsBottomEdge(this);
if (row == mNumRows - 1)
key.markAsTopEdge(this);
final int numColumnInRow = mNumColumnsInRow[row];
- final int column = getColumnNumber(pos);
+ final int column = getColumnNumber(index);
if (column == 0)
key.markAsLeftEdge(this);
if (column == numColumnInRow - 1)
@@ -174,15 +175,15 @@ public final class MoreSuggestions extends Keyboard {
public static final class Builder extends KeyboardBuilder<MoreSuggestionsParam> {
private final MoreSuggestionsView mPaneView;
private SuggestedWords mSuggestedWords;
- private int mFromPos;
- private int mToPos;
+ private int mFromIndex;
+ private int mToIndex;
public Builder(final Context context, final MoreSuggestionsView paneView) {
super(context, new MoreSuggestionsParam());
mPaneView = paneView;
}
- public Builder layout(final SuggestedWords suggestedWords, final int fromPos,
+ public Builder layout(final SuggestedWords suggestedWords, final int fromIndex,
final int maxWidth, final int minWidth, final int maxRow,
final Keyboard parentKeyboard) {
final int xmlId = R.xml.kbd_suggestions_pane_template;
@@ -190,10 +191,10 @@ public final class MoreSuggestions extends Keyboard {
mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2;
mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
- final int count = mParams.layout(suggestedWords, fromPos, maxWidth, minWidth, maxRow,
+ final int count = mParams.layout(suggestedWords, fromIndex, maxWidth, minWidth, maxRow,
mPaneView.newLabelPaint(null /* key */), mResources);
- mFromPos = fromPos;
- mToPos = fromPos + count;
+ mFromIndex = fromIndex;
+ mToIndex = fromIndex + count;
mSuggestedWords = suggestedWords;
return this;
}
@@ -201,20 +202,20 @@ public final class MoreSuggestions extends Keyboard {
@Override
public MoreSuggestions build() {
final MoreSuggestionsParam params = mParams;
- for (int pos = mFromPos; pos < mToPos; pos++) {
- final int x = params.getX(pos);
- final int y = params.getY(pos);
- final int width = params.getWidth(pos);
- final String word = mSuggestedWords.getWord(pos);
- final String info = Utils.getDebugInfo(mSuggestedWords, pos);
- final int index = pos + SUGGESTION_CODE_BASE;
+ for (int index = mFromIndex; index < mToIndex; index++) {
+ final int x = params.getX(index);
+ final int y = params.getY(index);
+ final int width = params.getWidth(index);
+ final String word = mSuggestedWords.getWord(index);
+ final String info = Utils.getDebugInfo(mSuggestedWords, index);
+ final int indexInMoreSuggestions = index + SUGGESTION_CODE_BASE;
final Key key = new Key(
- params, word, info, KeyboardIconsSet.ICON_UNDEFINED, index, null, x, y,
- width, params.mDefaultRowHeight, 0);
- params.markAsEdgeKey(key, pos);
+ params, word, info, KeyboardIconsSet.ICON_UNDEFINED, indexInMoreSuggestions,
+ null, x, y, width, params.mDefaultRowHeight, 0);
+ params.markAsEdgeKey(key, index);
params.onAddKey(key);
- final int columnNumber = params.getColumnNumber(pos);
- final int numColumnInRow = params.getNumColumnInRow(pos);
+ final int columnNumber = params.getColumnNumber(index);
+ final int numColumnInRow = params.getNumColumnInRow(index);
if (columnNumber < numColumnInRow - 1) {
final Divider divider = new Divider(params, params.mDivider, x + width, y,
params.mDividerWidth, params.mDefaultRowHeight);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
new file mode 100644
index 000000000..2f2ec3560
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -0,0 +1,561 @@
+/*
+ * 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.latin.suggestions;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.CharacterStyle;
+import android.text.style.StyleSpan;
+import android.text.style.UnderlineSpan;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.inputmethod.keyboard.ViewLayoutUtils;
+import com.android.inputmethod.latin.AutoCorrection;
+import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.ResourceUtils;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.Utils;
+
+import java.util.ArrayList;
+
+final class SuggestionStripLayoutHelper {
+ private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
+ private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f;
+ private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2;
+ private static final int PUNCTUATIONS_IN_STRIP = 5;
+ private static final float MIN_TEXT_XSCALE = 0.70f;
+
+ public final int mPadding;
+ public final int mDividerWidth;
+ public final int mSuggestionsStripHeight;
+ public final int mSuggestionsCountInStrip;
+ public final int mMoreSuggestionsRowHeight;
+ private int mMaxMoreSuggestionsRow;
+ public final float mMinMoreSuggestionsWidth;
+ public final int mMoreSuggestionsBottomGap;
+ public boolean mMoreSuggestionsAvailable;
+
+ // The index of these {@link ArrayList} is the position in the suggestion strip. The indices
+ // increase towards the right for LTR scripts and the left for RTL scripts, starting with 0.
+ // The position of the most important suggestion is in {@link #mCenterPositionInStrip}
+ private final ArrayList<TextView> mWordViews;
+ private final ArrayList<View> mDividerViews;
+ private final ArrayList<TextView> mDebugInfoViews;
+
+ private final int mColorValidTypedWord;
+ private final int mColorTypedWord;
+ private final int mColorAutoCorrect;
+ private final int mColorSuggested;
+ private final float mAlphaObsoleted;
+ private final float mCenterSuggestionWeight;
+ private final int mCenterPositionInStrip;
+ private final Drawable mMoreSuggestionsHint;
+ private static final String MORE_SUGGESTIONS_HINT = "\u2026";
+ private static final String LEFTWARDS_ARROW = "\u2190";
+
+ private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
+ private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
+
+ private final int mSuggestionStripOption;
+ // These constants are the flag values of
+ // {@link R.styleable#SuggestionStripView_suggestionStripOption} attribute.
+ private static final int AUTO_CORRECT_BOLD = 0x01;
+ private static final int AUTO_CORRECT_UNDERLINE = 0x02;
+ private static final int VALID_TYPED_WORD_BOLD = 0x04;
+
+ private final TextView mWordToSaveView;
+ private final TextView mLeftwardsArrowView;
+ private final TextView mHintToSaveView;
+
+ public SuggestionStripLayoutHelper(final Context context, final AttributeSet attrs,
+ final int defStyle, final ArrayList<TextView> wordViews,
+ final ArrayList<View> dividerViews, final ArrayList<TextView> debugInfoViews) {
+ mWordViews = wordViews;
+ mDividerViews = dividerViews;
+ mDebugInfoViews = debugInfoViews;
+
+ final TextView wordView = wordViews.get(0);
+ final View dividerView = dividerViews.get(0);
+ mPadding = wordView.getCompoundPaddingLeft() + wordView.getCompoundPaddingRight();
+ dividerView.measure(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ mDividerWidth = dividerView.getMeasuredWidth();
+
+ final Resources res = wordView.getResources();
+ mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height);
+
+ final TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripViewStyle);
+ mSuggestionStripOption = a.getInt(
+ R.styleable.SuggestionStripView_suggestionStripOption, 0);
+ final float alphaValidTypedWord = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_alphaValidTypedWord, 1.0f);
+ final float alphaTypedWord = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_alphaTypedWord, 1.0f);
+ final float alphaAutoCorrect = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_alphaAutoCorrect, 1.0f);
+ final float alphaSuggested = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
+ mAlphaObsoleted = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
+ mColorValidTypedWord = applyAlpha(a.getColor(
+ R.styleable.SuggestionStripView_colorValidTypedWord, 0), alphaValidTypedWord);
+ mColorTypedWord = applyAlpha(a.getColor(
+ R.styleable.SuggestionStripView_colorTypedWord, 0), alphaTypedWord);
+ mColorAutoCorrect = applyAlpha(a.getColor(
+ R.styleable.SuggestionStripView_colorAutoCorrect, 0), alphaAutoCorrect);
+ mColorSuggested = applyAlpha(a.getColor(
+ R.styleable.SuggestionStripView_colorSuggested, 0), alphaSuggested);
+ mSuggestionsCountInStrip = a.getInt(
+ R.styleable.SuggestionStripView_suggestionsCountInStrip,
+ DEFAULT_SUGGESTIONS_COUNT_IN_STRIP);
+ mCenterSuggestionWeight = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_centerSuggestionPercentile,
+ DEFAULT_CENTER_SUGGESTION_PERCENTILE);
+ mMaxMoreSuggestionsRow = a.getInt(
+ R.styleable.SuggestionStripView_maxMoreSuggestionsRow,
+ DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
+ mMinMoreSuggestionsWidth = ResourceUtils.getFraction(a,
+ R.styleable.SuggestionStripView_minMoreSuggestionsWidth, 1.0f);
+ a.recycle();
+
+ mMoreSuggestionsHint = getMoreSuggestionsHint(res,
+ res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect);
+ mCenterPositionInStrip = mSuggestionsCountInStrip / 2;
+ mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
+ R.dimen.more_suggestions_bottom_gap);
+ mMoreSuggestionsRowHeight = res.getDimensionPixelSize(R.dimen.more_suggestions_row_height);
+
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
+ mLeftwardsArrowView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
+ mHintToSaveView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
+ }
+
+ public int getMaxMoreSuggestionsRow() {
+ return mMaxMoreSuggestionsRow;
+ }
+
+ private int getMoreSuggestionsHeight() {
+ return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
+ }
+
+ public int setMoreSuggestionsHeight(final int remainingHeight) {
+ final int currentHeight = getMoreSuggestionsHeight();
+ if (currentHeight <= remainingHeight) {
+ return currentHeight;
+ }
+
+ mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
+ / mMoreSuggestionsRowHeight;
+ final int newHeight = getMoreSuggestionsHeight();
+ return newHeight;
+ }
+
+ private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize,
+ final int color) {
+ final Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextAlign(Align.CENTER);
+ paint.setTextSize(textSize);
+ paint.setColor(color);
+ final Rect bounds = new Rect();
+ paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
+ final int width = Math.round(bounds.width() + 0.5f);
+ final int height = Math.round(bounds.height() + 0.5f);
+ final Bitmap buffer = Bitmap.createBitmap(width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(buffer);
+ canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
+ return new BitmapDrawable(res, buffer);
+ }
+
+ private CharSequence getStyledSuggestedWord(final SuggestedWords suggestedWords,
+ final int indexInSuggestedWords) {
+ final String word = suggestedWords.getWord(indexInSuggestedWords);
+ final boolean isAutoCorrect = indexInSuggestedWords == 1
+ && suggestedWords.willAutoCorrect();
+ final boolean isTypedWordValid = indexInSuggestedWords == 0
+ && suggestedWords.mTypedWordValid;
+ if (!isAutoCorrect && !isTypedWordValid) {
+ return word;
+ }
+
+ final int len = word.length();
+ final Spannable spannedWord = new SpannableString(word);
+ final int option = mSuggestionStripOption;
+ if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
+ || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
+ spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
+ spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+ return spannedWord;
+ }
+
+ private int getIndexInSuggestedWords(final int positionInStrip,
+ final SuggestedWords suggestedWords) {
+ // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
+ // suggestions.
+ final int mostImportantIndexInSuggestedWords = suggestedWords.willAutoCorrect()
+ ? SuggestedWords.INDEX_OF_AUTO_CORRECTION : SuggestedWords.INDEX_OF_TYPED_WORD;
+ if (positionInStrip == mCenterPositionInStrip) {
+ return mostImportantIndexInSuggestedWords;
+ }
+ if (positionInStrip == mostImportantIndexInSuggestedWords) {
+ return mCenterPositionInStrip;
+ }
+ return positionInStrip;
+ }
+
+ private int getSuggestionTextColor(final int positionInStrip,
+ final SuggestedWords suggestedWords) {
+ final int indexInSuggestedWords = getIndexInSuggestedWords(positionInStrip, suggestedWords);
+ // TODO: Need to revisit this logic with bigram suggestions
+ final boolean isSuggested = (indexInSuggestedWords != SuggestedWords.INDEX_OF_TYPED_WORD);
+
+ final int color;
+ if (positionInStrip == mCenterPositionInStrip && suggestedWords.willAutoCorrect()) {
+ color = mColorAutoCorrect;
+ } else if (positionInStrip == mCenterPositionInStrip && suggestedWords.mTypedWordValid) {
+ color = mColorValidTypedWord;
+ } else if (isSuggested) {
+ color = mColorSuggested;
+ } else {
+ color = mColorTypedWord;
+ }
+ if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
+ // If we auto-correct, then the autocorrection is in slot 0 and the typed word
+ // is in slot 1.
+ if (positionInStrip == mCenterPositionInStrip
+ && AutoCorrection.shouldBlockAutoCorrectionBySafetyNet(
+ suggestedWords.getWord(SuggestedWords.INDEX_OF_AUTO_CORRECTION),
+ suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD))) {
+ return 0xFFFF0000;
+ }
+ }
+
+ if (suggestedWords.mIsObsoleteSuggestions && isSuggested) {
+ return applyAlpha(color, mAlphaObsoleted);
+ }
+ return color;
+ }
+
+ private static int applyAlpha(final int color, final float alpha) {
+ final int newAlpha = (int)(Color.alpha(color) * alpha);
+ return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
+ }
+
+ private static void addDivider(final ViewGroup stripView, final View dividerView) {
+ stripView.addView(dividerView);
+ final LinearLayout.LayoutParams params =
+ (LinearLayout.LayoutParams)dividerView.getLayoutParams();
+ params.gravity = Gravity.CENTER;
+ }
+
+ public void layout(final SuggestedWords suggestedWords, final ViewGroup stripView,
+ final ViewGroup placerView) {
+ if (suggestedWords.mIsPunctuationSuggestions) {
+ layoutPunctuationSuggestions(suggestedWords, stripView);
+ return;
+ }
+
+ final int countInStrip = mSuggestionsCountInStrip;
+ setupWordViewsTextAndColor(suggestedWords, countInStrip);
+ mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+ int x = 0;
+ for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
+ if (positionInStrip != 0) {
+ final View divider = mDividerViews.get(positionInStrip);
+ // Add divider if this isn't the left most suggestion in suggestions strip.
+ addDivider(stripView, divider);
+ x += divider.getMeasuredWidth();
+ }
+
+ final int width = getSuggestionWidth(positionInStrip, placerView.getWidth());
+ final TextView wordView = layoutWord(positionInStrip, width);
+ stripView.addView(wordView);
+ setLayoutWeight(wordView, getSuggestionWeight(positionInStrip),
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ x += wordView.getMeasuredWidth();
+
+ if (SuggestionStripView.DBG) {
+ layoutDebugInfo(positionInStrip, placerView, x);
+ }
+ }
+ }
+
+ /**
+ * Format appropriately the suggested word in {@link #mWordViews} specified by
+ * <code>positionInStrip</code>. When the suggested word doesn't exist, the corresponding
+ * {@link TextView} will be disabled and never respond to user interaction. The suggested word
+ * may be shrunk or ellipsized to fit in the specified width.
+ *
+ * The <code>positionInStrip</code> argument is the index in the suggestion strip. The indices
+ * increase towards the right for LTR scripts and the left for RTL scripts, starting with 0.
+ * The position of the most important suggestion is in {@link #mCenterPositionInStrip}. This
+ * usually doesn't match the index in <code>suggedtedWords</code> -- see
+ * {@link #getIndexInSuggestedWords(int,SuggestedWords)}.
+ *
+ * @param positionInStrip the position in the suggestion strip.
+ * @param width the maximum width for layout in pixels.
+ * @return the {@link TextView} containing the suggested word appropriately formatted.
+ */
+ private TextView layoutWord(final int positionInStrip, final int width) {
+ final TextView wordView = mWordViews.get(positionInStrip);
+ final CharSequence word = wordView.getText();
+ if (positionInStrip == mCenterPositionInStrip && mMoreSuggestionsAvailable) {
+ // TODO: This "more suggestions hint" should have a nicely designed icon.
+ wordView.setCompoundDrawablesWithIntrinsicBounds(
+ null, null, null, mMoreSuggestionsHint);
+ // HACK: Align with other TextViews that have no compound drawables.
+ wordView.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight());
+ } else {
+ wordView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+ }
+
+ // Disable this suggestion if the suggestion is null or empty.
+ wordView.setEnabled(!TextUtils.isEmpty(word));
+ final CharSequence text = getEllipsizedText(word, width, wordView.getPaint());
+ final float scaleX = wordView.getTextScaleX();
+ wordView.setText(text); // TextView.setText() resets text scale x to 1.0.
+ wordView.setTextScaleX(scaleX);
+ return wordView;
+ }
+
+ private void layoutDebugInfo(final int positionInStrip, final ViewGroup placerView,
+ final int x) {
+ final TextView debugInfoView = mDebugInfoViews.get(positionInStrip);
+ final CharSequence debugInfo = debugInfoView.getText();
+ if (debugInfo == null) {
+ return;
+ }
+ placerView.addView(debugInfoView);
+ debugInfoView.measure(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ final int infoWidth = debugInfoView.getMeasuredWidth();
+ final int y = debugInfoView.getMeasuredHeight();
+ ViewLayoutUtils.placeViewAt(
+ debugInfoView, x - infoWidth, y, infoWidth, debugInfoView.getMeasuredHeight());
+ }
+
+ private int getSuggestionWidth(final int positionInStrip, final int maxWidth) {
+ final int paddings = mPadding * mSuggestionsCountInStrip;
+ final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1);
+ final int availableWidth = maxWidth - paddings - dividers;
+ return (int)(availableWidth * getSuggestionWeight(positionInStrip));
+ }
+
+ private float getSuggestionWeight(final int positionInStrip) {
+ if (positionInStrip == mCenterPositionInStrip) {
+ return mCenterSuggestionWeight;
+ }
+ // TODO: Revisit this for cases of 5 or more suggestions
+ return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1);
+ }
+
+ private void setupWordViewsTextAndColor(final SuggestedWords suggestedWords,
+ final int countInStrip) {
+ final int count = Math.min(suggestedWords.size(), countInStrip);
+ for (int positionInStrip = 0; positionInStrip < count; positionInStrip++) {
+ final int indexInSuggestedWords =
+ getIndexInSuggestedWords(positionInStrip, suggestedWords);
+ final TextView wordView = mWordViews.get(positionInStrip);
+ // {@link TextView#getTag()} is used to get the index in suggestedWords at
+ // {@link SuggestionStripView#onClick(View)}.
+ wordView.setTag(indexInSuggestedWords);
+ wordView.setText(getStyledSuggestedWord(suggestedWords, indexInSuggestedWords));
+ wordView.setTextColor(getSuggestionTextColor(positionInStrip, suggestedWords));
+ if (SuggestionStripView.DBG) {
+ mDebugInfoViews.get(positionInStrip).setText(
+ Utils.getDebugInfo(suggestedWords, indexInSuggestedWords));
+ }
+ }
+ for (int positionInStrip = count; positionInStrip < countInStrip; positionInStrip++) {
+ mWordViews.get(positionInStrip).setText(null);
+ // Make this inactive for touches in {@link #layoutWord(int,int)}.
+ if (SuggestionStripView.DBG) {
+ mDebugInfoViews.get(positionInStrip).setText(null);
+ }
+ }
+ }
+
+ private void layoutPunctuationSuggestions(final SuggestedWords suggestedWords,
+ final ViewGroup stripView) {
+ final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
+ for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
+ if (positionInStrip != 0) {
+ // Add divider if this isn't the left most suggestion in suggestions strip.
+ addDivider(stripView, mDividerViews.get(positionInStrip));
+ }
+
+ final TextView wordView = mWordViews.get(positionInStrip);
+ wordView.setEnabled(true);
+ wordView.setTextColor(mColorAutoCorrect);
+ final String punctuation = suggestedWords.getWord(positionInStrip);
+ wordView.setText(punctuation);
+ wordView.setTextScaleX(1.0f);
+ wordView.setCompoundDrawables(null, null, null, null);
+ stripView.addView(wordView);
+ setLayoutWeight(wordView, 1.0f, mSuggestionsStripHeight);
+ }
+ mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+ }
+
+ public void layoutAddToDictionaryHint(final String word, final ViewGroup stripView,
+ final int stripWidth, final CharSequence hintText, final OnClickListener listener) {
+ final int width = stripWidth - mDividerWidth - mPadding * 2;
+
+ final TextView wordView = mWordToSaveView;
+ wordView.setTextColor(mColorTypedWord);
+ final int wordWidth = (int)(width * mCenterSuggestionWeight);
+ final CharSequence text = getEllipsizedText(word, wordWidth, wordView.getPaint());
+ final float wordScaleX = wordView.getTextScaleX();
+ wordView.setTag(word);
+ wordView.setText(text);
+ wordView.setTextScaleX(wordScaleX);
+ stripView.addView(wordView);
+ setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ stripView.addView(mDividerViews.get(0));
+
+ final TextView leftArrowView = mLeftwardsArrowView;
+ leftArrowView.setTextColor(mColorAutoCorrect);
+ leftArrowView.setText(LEFTWARDS_ARROW);
+ stripView.addView(leftArrowView);
+
+ final TextView hintView = mHintToSaveView;
+ hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ hintView.setTextColor(mColorAutoCorrect);
+ final int hintWidth = width - wordWidth - leftArrowView.getWidth();
+ final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
+ hintView.setText(hintText);
+ hintView.setTextScaleX(hintScaleX);
+ stripView.addView(hintView);
+ setLayoutWeight(
+ hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ wordView.setOnClickListener(listener);
+ leftArrowView.setOnClickListener(listener);
+ hintView.setOnClickListener(listener);
+ }
+
+ public CharSequence getAddToDictionaryWord() {
+ return (CharSequence)mWordToSaveView.getTag();
+ }
+
+ public boolean isAddToDictionaryShowing(final View v) {
+ return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView;
+ }
+
+ private static void setLayoutWeight(final View v, final float weight, final int height) {
+ final ViewGroup.LayoutParams lp = v.getLayoutParams();
+ if (lp instanceof LinearLayout.LayoutParams) {
+ final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
+ llp.weight = weight;
+ llp.width = 0;
+ llp.height = height;
+ }
+ }
+
+ private static float getTextScaleX(final CharSequence text, final int maxWidth,
+ final TextPaint paint) {
+ paint.setTextScaleX(1.0f);
+ final int width = getTextWidth(text, paint);
+ if (width <= maxWidth) {
+ return 1.0f;
+ }
+ return maxWidth / (float)width;
+ }
+
+ private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth,
+ final TextPaint paint) {
+ if (text == null) {
+ return null;
+ }
+ final float scaleX = getTextScaleX(text, maxWidth, paint);
+ if (scaleX >= MIN_TEXT_XSCALE) {
+ paint.setTextScaleX(scaleX);
+ return text;
+ }
+
+ // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
+ // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
+ final CharSequence ellipsized = TextUtils.ellipsize(
+ text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
+ paint.setTextScaleX(MIN_TEXT_XSCALE);
+ return ellipsized;
+ }
+
+ private static int getTextWidth(final CharSequence text, final TextPaint paint) {
+ if (TextUtils.isEmpty(text)) {
+ return 0;
+ }
+ final Typeface savedTypeface = paint.getTypeface();
+ paint.setTypeface(getTextTypeface(text));
+ final int len = text.length();
+ final float[] widths = new float[len];
+ final int count = paint.getTextWidths(text, 0, len, widths);
+ int width = 0;
+ for (int i = 0; i < count; i++) {
+ width += Math.round(widths[i] + 0.5f);
+ }
+ paint.setTypeface(savedTypeface);
+ return width;
+ }
+
+ private static Typeface getTextTypeface(final CharSequence text) {
+ if (!(text instanceof SpannableString)) {
+ return Typeface.DEFAULT;
+ }
+
+ final SpannableString ss = (SpannableString)text;
+ final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
+ if (styles.length == 0) {
+ return Typeface.DEFAULT;
+ }
+
+ if (styles[0].getStyle() == Typeface.BOLD) {
+ return Typeface.DEFAULT_BOLD;
+ }
+ // TODO: BOLD_ITALIC, ITALIC case?
+ return Typeface.DEFAULT;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 9764610b3..b2b9427af 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -18,34 +18,14 @@ package com.android.inputmethod.latin.suggestions;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.CharacterStyle;
-import android.text.style.StyleSpan;
-import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.view.GestureDetector;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
-import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -53,17 +33,13 @@ import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.keyboard.MoreKeysPanel;
-import com.android.inputmethod.keyboard.ViewLayoutUtils;
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
-import com.android.inputmethod.latin.AutoCorrection;
import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.ResourceUtils;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.suggestions.MoreSuggestions.MoreSuggestionsListener;
import com.android.inputmethod.research.ResearchLogger;
@@ -89,516 +65,14 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
private final MoreSuggestionsView mMoreSuggestionsView;
private final MoreSuggestions.Builder mMoreSuggestionsBuilder;
- private final ArrayList<TextView> mWords = CollectionUtils.newArrayList();
- private final ArrayList<TextView> mInfos = CollectionUtils.newArrayList();
- private final ArrayList<View> mDividers = CollectionUtils.newArrayList();
+ private final ArrayList<TextView> mWordViews = CollectionUtils.newArrayList();
+ private final ArrayList<TextView> mDebugInfoViews = CollectionUtils.newArrayList();
+ private final ArrayList<View> mDividerViews = CollectionUtils.newArrayList();
Listener mListener;
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
- private final SuggestionStripViewParams mParams;
- private static final float MIN_TEXT_XSCALE = 0.70f;
-
- private static final class SuggestionStripViewParams {
- private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
- private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f;
- private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2;
- private static final int PUNCTUATIONS_IN_STRIP = 5;
-
- public final int mPadding;
- public final int mDividerWidth;
- public final int mSuggestionsStripHeight;
- public final int mSuggestionsCountInStrip;
- public final int mMoreSuggestionsRowHeight;
- private int mMaxMoreSuggestionsRow;
- public final float mMinMoreSuggestionsWidth;
- public final int mMoreSuggestionsBottomGap;
-
- private final ArrayList<TextView> mWords;
- private final ArrayList<View> mDividers;
- private final ArrayList<TextView> mInfos;
-
- private final int mColorValidTypedWord;
- private final int mColorTypedWord;
- private final int mColorAutoCorrect;
- private final int mColorSuggested;
- private final float mAlphaObsoleted;
- private final float mCenterSuggestionWeight;
- private final int mCenterSuggestionIndex;
- private final Drawable mMoreSuggestionsHint;
- private static final String MORE_SUGGESTIONS_HINT = "\u2026";
- private static final String LEFTWARDS_ARROW = "\u2190";
-
- private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
- private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
- private static final int AUTO_CORRECT_BOLD = 0x01;
- private static final int AUTO_CORRECT_UNDERLINE = 0x02;
- private static final int VALID_TYPED_WORD_BOLD = 0x04;
-
- private final int mSuggestionStripOption;
-
- private final ArrayList<CharSequence> mTexts = CollectionUtils.newArrayList();
-
- public boolean mMoreSuggestionsAvailable;
-
- private final TextView mWordToSaveView;
- private final TextView mLeftwardsArrowView;
- private final TextView mHintToSaveView;
-
- public SuggestionStripViewParams(final Context context, final AttributeSet attrs,
- final int defStyle, final ArrayList<TextView> words, final ArrayList<View> dividers,
- final ArrayList<TextView> infos) {
- mWords = words;
- mDividers = dividers;
- mInfos = infos;
-
- final TextView word = words.get(0);
- final View divider = dividers.get(0);
- mPadding = word.getCompoundPaddingLeft() + word.getCompoundPaddingRight();
- divider.measure(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- mDividerWidth = divider.getMeasuredWidth();
-
- final Resources res = word.getResources();
- mSuggestionsStripHeight = res.getDimensionPixelSize(R.dimen.suggestions_strip_height);
-
- final TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripViewStyle);
- mSuggestionStripOption = a.getInt(
- R.styleable.SuggestionStripView_suggestionStripOption, 0);
- final float alphaValidTypedWord = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaValidTypedWord, 1.0f);
- final float alphaTypedWord = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaTypedWord, 1.0f);
- final float alphaAutoCorrect = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaAutoCorrect, 1.0f);
- final float alphaSuggested = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
- mAlphaObsoleted = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaSuggested, 1.0f);
- mColorValidTypedWord = applyAlpha(a.getColor(
- R.styleable.SuggestionStripView_colorValidTypedWord, 0), alphaValidTypedWord);
- mColorTypedWord = applyAlpha(a.getColor(
- R.styleable.SuggestionStripView_colorTypedWord, 0), alphaTypedWord);
- mColorAutoCorrect = applyAlpha(a.getColor(
- R.styleable.SuggestionStripView_colorAutoCorrect, 0), alphaAutoCorrect);
- mColorSuggested = applyAlpha(a.getColor(
- R.styleable.SuggestionStripView_colorSuggested, 0), alphaSuggested);
- mSuggestionsCountInStrip = a.getInt(
- R.styleable.SuggestionStripView_suggestionsCountInStrip,
- DEFAULT_SUGGESTIONS_COUNT_IN_STRIP);
- mCenterSuggestionWeight = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_centerSuggestionPercentile,
- DEFAULT_CENTER_SUGGESTION_PERCENTILE);
- mMaxMoreSuggestionsRow = a.getInt(
- R.styleable.SuggestionStripView_maxMoreSuggestionsRow,
- DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
- mMinMoreSuggestionsWidth = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_minMoreSuggestionsWidth, 1.0f);
- a.recycle();
-
- mMoreSuggestionsHint = getMoreSuggestionsHint(res,
- res.getDimension(R.dimen.more_suggestions_hint_text_size), mColorAutoCorrect);
- mCenterSuggestionIndex = mSuggestionsCountInStrip / 2;
- mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
- R.dimen.more_suggestions_bottom_gap);
- mMoreSuggestionsRowHeight = res.getDimensionPixelSize(
- R.dimen.more_suggestions_row_height);
-
- final LayoutInflater inflater = LayoutInflater.from(context);
- mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null);
- mLeftwardsArrowView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
- mHintToSaveView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null);
- }
-
- public int getMaxMoreSuggestionsRow() {
- return mMaxMoreSuggestionsRow;
- }
-
- private int getMoreSuggestionsHeight() {
- return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
- }
-
- public int setMoreSuggestionsHeight(final int remainingHeight) {
- final int currentHeight = getMoreSuggestionsHeight();
- if (currentHeight <= remainingHeight) {
- return currentHeight;
- }
-
- mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
- / mMoreSuggestionsRowHeight;
- final int newHeight = getMoreSuggestionsHeight();
- return newHeight;
- }
-
- private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize,
- final int color) {
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setTextAlign(Align.CENTER);
- paint.setTextSize(textSize);
- paint.setColor(color);
- final Rect bounds = new Rect();
- paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
- final int width = Math.round(bounds.width() + 0.5f);
- final int height = Math.round(bounds.height() + 0.5f);
- final Bitmap buffer = Bitmap.createBitmap(
- width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(buffer);
- canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
- return new BitmapDrawable(res, buffer);
- }
-
- private CharSequence getStyledSuggestionWord(final SuggestedWords suggestedWords,
- final int indexInSuggestedWords) {
- final String word = suggestedWords.getWord(indexInSuggestedWords);
- final boolean isAutoCorrect = indexInSuggestedWords == 1
- && suggestedWords.willAutoCorrect();
- final boolean isTypedWordValid = indexInSuggestedWords == 0
- && suggestedWords.mTypedWordValid;
- if (!isAutoCorrect && !isTypedWordValid)
- return word;
-
- final int len = word.length();
- final Spannable spannedWord = new SpannableString(word);
- final int option = mSuggestionStripOption;
- if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
- || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
- spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
- if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
- spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
- return spannedWord;
- }
-
- private int getIndexInSuggestedWords(final int indexInStrip,
- final SuggestedWords suggestedWords) {
- // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more
- // suggestions.
- final int mostImportantIndexInSuggestedWords = suggestedWords.willAutoCorrect() ? 1 : 0;
- if (indexInStrip == mCenterSuggestionIndex) {
- return mostImportantIndexInSuggestedWords;
- } else if (indexInStrip == mostImportantIndexInSuggestedWords) {
- return mCenterSuggestionIndex;
- } else {
- return indexInStrip;
- }
- }
-
- private int getSuggestionTextColor(final int indexInStrip,
- final SuggestedWords suggestedWords) {
- final int indexInSuggestedWords = getIndexInSuggestedWords(
- indexInStrip, suggestedWords);
- // TODO: Need to revisit this logic with bigram suggestions
- final boolean isSuggested = (indexInSuggestedWords != 0);
-
- final int color;
- if (indexInStrip == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) {
- color = mColorAutoCorrect;
- } else if (indexInStrip == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) {
- color = mColorValidTypedWord;
- } else if (isSuggested) {
- color = mColorSuggested;
- } else {
- color = mColorTypedWord;
- }
- if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
- // If we auto-correct, then the autocorrection is in slot 0 and the typed word
- // is in slot 1.
- if (indexInStrip == mCenterSuggestionIndex
- && AutoCorrection.shouldBlockAutoCorrectionBySafetyNet(
- suggestedWords.getWord(1), suggestedWords.getWord(0))) {
- return 0xFFFF0000;
- }
- }
-
- if (suggestedWords.mIsObsoleteSuggestions && isSuggested) {
- return applyAlpha(color, mAlphaObsoleted);
- } else {
- return color;
- }
- }
-
- private static int applyAlpha(final int color, final float alpha) {
- final int newAlpha = (int)(Color.alpha(color) * alpha);
- return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
- }
-
- private static void addDivider(final ViewGroup stripView, final View divider) {
- stripView.addView(divider);
- final LinearLayout.LayoutParams params =
- (LinearLayout.LayoutParams)divider.getLayoutParams();
- params.gravity = Gravity.CENTER;
- }
-
- public void layout(final SuggestedWords suggestedWords, final ViewGroup stripView,
- final ViewGroup placer, final int stripWidth) {
- if (suggestedWords.mIsPunctuationSuggestions) {
- layoutPunctuationSuggestions(suggestedWords, stripView);
- return;
- }
-
- final int countInStrip = mSuggestionsCountInStrip;
- setupTexts(suggestedWords, countInStrip);
- mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
- int x = 0;
- for (int indexInStrip = 0; indexInStrip < countInStrip; indexInStrip++) {
- if (indexInStrip != 0) {
- final View divider = mDividers.get(indexInStrip);
- // Add divider if this isn't the left most suggestion in suggestions strip.
- addDivider(stripView, divider);
- x += divider.getMeasuredWidth();
- }
-
- final int width = getSuggestionWidth(indexInStrip, stripWidth);
- final TextView word = layoutWord(suggestedWords, indexInStrip, width);
- stripView.addView(word);
- setLayoutWeight(word, getSuggestionWeight(indexInStrip),
- ViewGroup.LayoutParams.MATCH_PARENT);
- x += word.getMeasuredWidth();
-
- if (DBG) {
- layoutDebugInfo(suggestedWords, indexInStrip, placer, x);
- }
- }
- }
-
- /**
- * Format appropriately the suggested word indirectly specified by
- * <code>indexInStrip</code> as text in a corresponding {@link TextView}. When the
- * suggested word doesn't exist, the corresponding {@link TextView} will be disabled
- * and never respond to user interaction. The suggested word may be shrunk or ellipsized to
- * fit in the specified width.
- *
- * The <code>indexInStrip</code> argument is the index in the suggestion strip. The indices
- * increase towards the right for LTR scripts and the left for RTL scripts, starting with 0.
- * The index of the most important suggestion is in {@link #mCenterSuggestionIndex}. This
- * usually doesn't match the index in <code>suggedtedWords</code> -- see
- * {@link #getIndexInSuggestedWords(int,SuggestedWords)}.
- *
- * @param suggestedWords the list of suggestions.
- * @param indexInStrip the in the suggestion strip.
- * @param width the maximum width for layout in pixels.
- * @return the {@link TextView} containing the suggested word appropriately formatted.
- */
- private TextView layoutWord(final SuggestedWords suggestedWords, final int indexInStrip,
- final int width) {
- final int indexInSuggestedWords = getIndexInSuggestedWords(
- indexInStrip, suggestedWords);
- final CharSequence styled = mTexts.get(indexInSuggestedWords);
- final TextView word = mWords.get(indexInSuggestedWords);
- if (indexInStrip == mCenterSuggestionIndex && mMoreSuggestionsAvailable) {
- // TODO: This "more suggestions hint" should have a nicely designed icon.
- word.setCompoundDrawablesWithIntrinsicBounds(
- null, null, null, mMoreSuggestionsHint);
- // HACK: Align with other TextViews that have no compound drawables.
- word.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight());
- } else {
- word.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
- }
-
- // Disable this suggestion if the suggestion is null or empty.
- word.setEnabled(!TextUtils.isEmpty(styled));
- word.setTextColor(getSuggestionTextColor(indexInStrip, suggestedWords));
- final CharSequence text = getEllipsizedText(styled, width, word.getPaint());
- final float scaleX = word.getTextScaleX();
- word.setText(text); // TextView.setText() resets text scale x to 1.0.
- word.setTextScaleX(scaleX);
- return word;
- }
-
- private void layoutDebugInfo(final SuggestedWords suggestedWords, final int indexInStrip,
- final ViewGroup placer, final int x) {
- final int indexInSuggestedWords = getIndexInSuggestedWords(
- indexInStrip, suggestedWords);
- if (indexInSuggestedWords >= suggestedWords.size()) {
- return;
- }
- final String debugInfo = Utils.getDebugInfo(suggestedWords, indexInSuggestedWords);
- if (debugInfo == null) {
- return;
- }
- final TextView info = mInfos.get(indexInSuggestedWords);
- info.setText(debugInfo);
- placer.addView(info);
- info.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- final int infoWidth = info.getMeasuredWidth();
- final int y = info.getMeasuredHeight();
- ViewLayoutUtils.placeViewAt(
- info, x - infoWidth, y, infoWidth, info.getMeasuredHeight());
- }
-
- private int getSuggestionWidth(final int indexInStrip, final int maxWidth) {
- final int paddings = mPadding * mSuggestionsCountInStrip;
- final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1);
- final int availableWidth = maxWidth - paddings - dividers;
- return (int)(availableWidth * getSuggestionWeight(indexInStrip));
- }
-
- private float getSuggestionWeight(final int indexInStrip) {
- if (indexInStrip == mCenterSuggestionIndex) {
- return mCenterSuggestionWeight;
- } else {
- // TODO: Revisit this for cases of 5 or more suggestions
- return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1);
- }
- }
-
- private void setupTexts(final SuggestedWords suggestedWords, final int countInStrip) {
- mTexts.clear();
- final int count = Math.min(suggestedWords.size(), countInStrip);
- for (int pos = 0; pos < count; pos++) {
- final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos);
- mTexts.add(styled);
- }
- for (int pos = count; pos < countInStrip; pos++) {
- // Make this inactive for touches in layout().
- mTexts.add(null);
- }
- }
-
- private void layoutPunctuationSuggestions(final SuggestedWords suggestedWords,
- final ViewGroup stripView) {
- final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP);
- for (int indexInStrip = 0; indexInStrip < countInStrip; indexInStrip++) {
- if (indexInStrip != 0) {
- // Add divider if this isn't the left most suggestion in suggestions strip.
- addDivider(stripView, mDividers.get(indexInStrip));
- }
-
- final TextView word = mWords.get(indexInStrip);
- word.setEnabled(true);
- word.setTextColor(mColorAutoCorrect);
- final String text = suggestedWords.getWord(indexInStrip);
- word.setText(text);
- word.setTextScaleX(1.0f);
- word.setCompoundDrawables(null, null, null, null);
- stripView.addView(word);
- setLayoutWeight(word, 1.0f, mSuggestionsStripHeight);
- }
- mMoreSuggestionsAvailable = false;
- }
-
- public void layoutAddToDictionaryHint(final String word, final ViewGroup stripView,
- final int stripWidth, final CharSequence hintText, final OnClickListener listener) {
- final int width = stripWidth - mDividerWidth - mPadding * 2;
-
- final TextView wordView = mWordToSaveView;
- wordView.setTextColor(mColorTypedWord);
- final int wordWidth = (int)(width * mCenterSuggestionWeight);
- final CharSequence text = getEllipsizedText(word, wordWidth, wordView.getPaint());
- final float wordScaleX = wordView.getTextScaleX();
- wordView.setTag(word);
- wordView.setText(text);
- wordView.setTextScaleX(wordScaleX);
- stripView.addView(wordView);
- setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
-
- stripView.addView(mDividers.get(0));
-
- final TextView leftArrowView = mLeftwardsArrowView;
- leftArrowView.setTextColor(mColorAutoCorrect);
- leftArrowView.setText(LEFTWARDS_ARROW);
- stripView.addView(leftArrowView);
-
- final TextView hintView = mHintToSaveView;
- hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
- hintView.setTextColor(mColorAutoCorrect);
- final int hintWidth = width - wordWidth - leftArrowView.getWidth();
- final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
- hintView.setText(hintText);
- hintView.setTextScaleX(hintScaleX);
- stripView.addView(hintView);
- setLayoutWeight(
- hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
-
- wordView.setOnClickListener(listener);
- leftArrowView.setOnClickListener(listener);
- hintView.setOnClickListener(listener);
- }
-
- public CharSequence getAddToDictionaryWord() {
- return (CharSequence)mWordToSaveView.getTag();
- }
-
- public boolean isAddToDictionaryShowing(final View v) {
- return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView;
- }
-
- private static void setLayoutWeight(final View v, final float weight, final int height) {
- final ViewGroup.LayoutParams lp = v.getLayoutParams();
- if (lp instanceof LinearLayout.LayoutParams) {
- final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
- llp.weight = weight;
- llp.width = 0;
- llp.height = height;
- }
- }
-
- private static float getTextScaleX(final CharSequence text, final int maxWidth,
- final TextPaint paint) {
- paint.setTextScaleX(1.0f);
- final int width = getTextWidth(text, paint);
- if (width <= maxWidth) {
- return 1.0f;
- }
- return maxWidth / (float)width;
- }
-
- private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth,
- final TextPaint paint) {
- if (text == null) return null;
- paint.setTextScaleX(1.0f);
- final int width = getTextWidth(text, paint);
- if (width <= maxWidth) {
- return text;
- }
- final float scaleX = maxWidth / (float)width;
- if (scaleX >= MIN_TEXT_XSCALE) {
- paint.setTextScaleX(scaleX);
- return text;
- }
-
- // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
- // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
- final CharSequence ellipsized = TextUtils.ellipsize(
- text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE);
- paint.setTextScaleX(MIN_TEXT_XSCALE);
- return ellipsized;
- }
-
- private static int getTextWidth(final CharSequence text, final TextPaint paint) {
- if (TextUtils.isEmpty(text)) return 0;
- final Typeface savedTypeface = paint.getTypeface();
- paint.setTypeface(getTextTypeface(text));
- final int len = text.length();
- final float[] widths = new float[len];
- final int count = paint.getTextWidths(text, 0, len, widths);
- int width = 0;
- for (int i = 0; i < count; i++) {
- width += Math.round(widths[i] + 0.5f);
- }
- paint.setTypeface(savedTypeface);
- return width;
- }
-
- private static Typeface getTextTypeface(final CharSequence text) {
- if (!(text instanceof SpannableString))
- return Typeface.DEFAULT;
-
- final SpannableString ss = (SpannableString)text;
- final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
- if (styles.length == 0)
- return Typeface.DEFAULT;
-
- switch (styles[0].getStyle()) {
- case Typeface.BOLD: return Typeface.DEFAULT_BOLD;
- // TODO: BOLD_ITALIC, ITALIC case?
- default: return Typeface.DEFAULT;
- }
- }
- }
+ private final SuggestionStripLayoutHelper mLayoutHelper;
/**
* Construct a {@link SuggestionStripView} for showing suggestions to be picked by the user.
@@ -619,19 +93,17 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
for (int pos = 0; pos < MAX_SUGGESTIONS; pos++) {
final TextView word = (TextView)inflater.inflate(R.layout.suggestion_word, null);
- word.setTag(pos);
word.setOnClickListener(this);
word.setOnLongClickListener(this);
- mWords.add(word);
+ mWordViews.add(word);
final View divider = inflater.inflate(R.layout.suggestion_divider, null);
- divider.setTag(pos);
divider.setOnClickListener(this);
- mDividers.add(divider);
- mInfos.add((TextView)inflater.inflate(R.layout.suggestion_info, null));
+ mDividerViews.add(divider);
+ mDebugInfoViews.add((TextView)inflater.inflate(R.layout.suggestion_info, null));
}
- mParams = new SuggestionStripViewParams(
- context, attrs, defStyle, mWords, mDividers, mInfos);
+ mLayoutHelper = new SuggestionStripLayoutHelper(
+ context, attrs, defStyle, mWordViews, mDividerViews, mDebugInfoViews);
mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
@@ -657,24 +129,25 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
public void setSuggestions(final SuggestedWords suggestedWords) {
clear();
mSuggestedWords = suggestedWords;
- mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth());
+ mLayoutHelper.layout(mSuggestedWords, mSuggestionsStrip, this);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords);
}
}
public int setMoreSuggestionsHeight(final int remainingHeight) {
- return mParams.setMoreSuggestionsHeight(remainingHeight);
+ return mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
}
public boolean isShowingAddToDictionaryHint() {
return mSuggestionsStrip.getChildCount() > 0
- && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0));
+ && mLayoutHelper.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0));
}
public void showAddToDictionaryHint(final String word, final CharSequence hintText) {
clear();
- mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this);
+ mLayoutHelper.layoutAddToDictionaryHint(
+ word, mSuggestionsStrip, getWidth(), hintText, this);
}
public boolean dismissAddToDictionaryHint() {
@@ -739,30 +212,30 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
if (parentKeyboard == null) {
return false;
}
- final SuggestionStripViewParams params = mParams;
- if (!params.mMoreSuggestionsAvailable) {
+ final SuggestionStripLayoutHelper layoutHelper = mLayoutHelper;
+ if (!layoutHelper.mMoreSuggestionsAvailable) {
return false;
}
final int stripWidth = getWidth();
final View container = mMoreSuggestionsContainer;
final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight();
final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder;
- builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth,
- (int)(maxWidth * params.mMinMoreSuggestionsWidth),
- params.getMaxMoreSuggestionsRow(), parentKeyboard);
+ builder.layout(mSuggestedWords, layoutHelper.mSuggestionsCountInStrip, maxWidth,
+ (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth),
+ layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard);
mMoreSuggestionsView.setKeyboard(builder.build());
container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView;
final int pointX = stripWidth / 2;
- final int pointY = -params.mMoreSuggestionsBottomGap;
+ final int pointY = -layoutHelper.mMoreSuggestionsBottomGap;
moreKeysPanel.showMoreKeysPanel(this, mMoreSuggestionsController, pointX, pointY,
mMoreSuggestionsListener);
mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING;
mOriginX = mLastX;
mOriginY = mLastY;
- for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
- mWords.get(i).setPressed(false);
+ for (int i = 0; i < layoutHelper.mSuggestionsCountInStrip; i++) {
+ mWordViews.get(i).setPressed(false);
}
return true;
}
@@ -832,18 +305,20 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
@Override
public void onClick(final View view) {
- if (mParams.isAddToDictionaryShowing(view)) {
- mListener.addWordToUserDictionary(mParams.getAddToDictionaryWord().toString());
+ if (mLayoutHelper.isAddToDictionaryShowing(view)) {
+ mListener.addWordToUserDictionary(mLayoutHelper.getAddToDictionaryWord().toString());
clear();
return;
}
final Object tag = view.getTag();
- if (!(tag instanceof Integer))
+ if (!(tag instanceof Integer)) {
return;
+ }
final int index = (Integer) tag;
- if (index >= mSuggestedWords.size())
+ if (index >= mSuggestedWords.size()) {
return;
+ }
final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
mListener.pickSuggestionManually(index, wordInfo);
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index cbe9515fe..1b758c680 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -46,17 +46,9 @@ LATIN_IME_JNI_SRC_FILES := \
jni_common.cpp
LATIN_IME_CORE_SRC_FILES := \
- additional_proximity_chars.cpp \
bigram_dictionary.cpp \
- char_utils.cpp \
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/suggest.cpp \
@@ -64,6 +56,16 @@ LATIN_IME_CORE_SRC_FILES := \
dic_node.cpp \
dic_node_utils.cpp \
dic_nodes_cache.cpp) \
+ $(addprefix suggest/core/dictionary/, \
+ char_utils.cpp \
+ dictionary.cpp \
+ digraph_utils.cpp) \
+ $(addprefix suggest/core/layout/, \
+ additional_proximity_chars.cpp \
+ proximity_info.cpp \
+ proximity_info_params.cpp \
+ proximity_info_state.cpp \
+ proximity_info_state_utils.cpp) \
suggest/core/policy/weighting.cpp \
suggest/core/session/dic_traverse_session.cpp \
suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index dedb02abf..e312aeabc 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -17,10 +17,11 @@
#define LOG_TAG "LatinIME: jni: ProximityInfo"
#include "com_android_inputmethod_keyboard_ProximityInfo.h"
+
#include "defines.h"
#include "jni.h"
#include "jni_common.h"
-#include "proximity_info.h"
+#include "suggest/core/layout/proximity_info.h"
namespace latinime {
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 0e9c29261..9f5e2ae73 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -29,13 +29,14 @@
#include <cstdio> // for fopen() etc.
#endif // USE_MMAP_FOR_DICTIONARY
-#include "binary_format.h"
#include "com_android_inputmethod_latin_BinaryDictionary.h"
+
#include "correction.h"
-#include "dictionary.h"
#include "jni.h"
#include "jni_common.h"
#include "suggest_options.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/dictionary.h"
namespace latinime {
@@ -162,7 +163,7 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz, j
const jsize numberOfOptions = env->GetArrayLength(suggestOptions);
int options[numberOfOptions];
env->GetIntArrayRegion(suggestOptions, 0, numberOfOptions, options);
- SuggestOptions givenOptions(options, numberOfOptions);
+ SuggestOptions givenSuggestOptions(options, numberOfOptions);
// Output values
/* By the way, let's check the output array length here to make sure */
@@ -190,12 +191,11 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz, j
memset(outputTypes, 0, sizeof(outputTypes));
int count;
- if (givenOptions.isGesture() || inputSize > 0) {
+ if (givenSuggestOptions.isGesture() || inputSize > 0) {
count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates,
times, pointerIds, inputCodePoints, inputSize, prevWordCodePoints,
- prevWordCodePointsLength, commitPoint, givenOptions.isGesture(),
- givenOptions.useFullEditDistance(), outputCodePoints, scores,
- spaceIndices, outputTypes);
+ prevWordCodePointsLength, commitPoint, &givenSuggestOptions, outputCodePoints,
+ scores, spaceIndices, outputTypes);
} else {
count = dictionary->getBigrams(prevWordCodePoints, prevWordCodePointsLength,
inputCodePoints, inputSize, outputCodePoints, scores, outputTypes);
diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
index dfe3b09d8..08124ffc8 100644
--- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
+++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
@@ -34,12 +34,14 @@ static void latinime_initDicTraverseSession(JNIEnv *env, jclass clazz, jlong tra
void *ts = reinterpret_cast<void *>(traverseSession);
Dictionary *dict = reinterpret_cast<Dictionary *>(dictionary);
if (!previousWord) {
- DicTraverseWrapper::initDicTraverseSession(ts, dict, 0, 0);
+ DicTraverseWrapper::initDicTraverseSession(
+ ts, dict, 0 /* prevWord */, 0 /* prevWordLength*/, 0 /* suggestOptions */);
return;
}
int prevWord[previousWordLength];
env->GetIntArrayRegion(previousWord, 0, previousWordLength, prevWord);
- DicTraverseWrapper::initDicTraverseSession(ts, dict, prevWord, previousWordLength);
+ DicTraverseWrapper::initDicTraverseSession(
+ ts, dict, prevWord, previousWordLength, 0 /* suggestOptions */);
}
static void latinime_releaseDicTraverseSession(JNIEnv *env, jclass clazz, jlong traverseSession) {
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 9053e7226..ebe27994f 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -19,11 +19,12 @@
#define LOG_TAG "LatinIME: bigram_dictionary.cpp"
#include "bigram_dictionary.h"
-#include "binary_format.h"
-#include "bloom_filter.h"
-#include "char_utils.h"
+
#include "defines.h"
-#include "dictionary.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/bloom_filter.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/dictionary/dictionary.h"
namespace latinime {
@@ -51,7 +52,7 @@ void BigramDictionary::addWordBigram(int *word, int length, int probability, int
int insertAt = 0;
while (insertAt < MAX_RESULTS) {
if (probability > bigramProbability[insertAt] || (bigramProbability[insertAt] == probability
- && length < getCodePointCount(MAX_WORD_LENGTH,
+ && length < CharUtils::getCodePointCount(MAX_WORD_LENGTH,
bigramCodePoints + insertAt * MAX_WORD_LENGTH))) {
break;
}
@@ -195,9 +196,9 @@ bool BigramDictionary::checkFirstCharacter(int *word, int *inputCodePoints) cons
// what user typed.
int maxAlt = MAX_ALTERNATIVES;
- const int firstBaseLowerCodePoint = toBaseLowerCase(*word);
+ const int firstBaseLowerCodePoint = CharUtils::toBaseLowerCase(*word);
while (maxAlt > 0) {
- if (toBaseLowerCase(*inputCodePoints) == firstBaseLowerCodePoint) {
+ if (CharUtils::toBaseLowerCase(*inputCodePoints) == firstBaseLowerCodePoint) {
return true;
}
inputCodePoints++;
diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h
deleted file mode 100644
index b429f40b2..000000000
--- a/native/jni/src/char_utils.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 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_CHAR_UTILS_H
-#define LATINIME_CHAR_UTILS_H
-
-#include <cctype>
-
-#include "defines.h"
-
-namespace latinime {
-
-inline static bool isAsciiUpper(int c) {
- // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to
- // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...).
- return (c >= 'A' && c <= 'Z');
-}
-
-inline static int toAsciiLower(int c) {
- return c - 'A' + 'a';
-}
-
-inline static bool isAscii(int c) {
- return isascii(c) != 0;
-}
-
-unsigned short latin_tolower(const unsigned short c);
-
-/**
- * Table mapping most combined Latin, Greek, and Cyrillic characters
- * to their base characters. If c is in range, BASE_CHARS[c] == c
- * if c is not a combined character, or the base character if it
- * is combined.
- */
-static const int BASE_CHARS_SIZE = 0x0500;
-extern const unsigned short BASE_CHARS[BASE_CHARS_SIZE];
-
-inline static int toBaseCodePoint(int c) {
- if (c < BASE_CHARS_SIZE) {
- return static_cast<int>(BASE_CHARS[c]);
- }
- return c;
-}
-
-AK_FORCE_INLINE static int toLowerCase(const int c) {
- if (isAsciiUpper(c)) {
- return toAsciiLower(c);
- }
- if (isAscii(c)) {
- return c;
- }
- return static_cast<int>(latin_tolower(static_cast<unsigned short>(c)));
-}
-
-AK_FORCE_INLINE static int toBaseLowerCase(const int c) {
- return toLowerCase(toBaseCodePoint(c));
-}
-
-inline static bool isIntentionalOmissionCodePoint(const int codePoint) {
- // TODO: Do not hardcode here
- return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS;
-}
-
-inline static int getCodePointCount(const int arraySize, const int *const codePoints) {
- int size = 0;
- for (; size < arraySize; ++size) {
- if (codePoints[size] == '\0') {
- break;
- }
- }
- return size;
-}
-
-} // namespace latinime
-#endif // LATINIME_CHAR_UTILS_H
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 61bf3f619..3dc2f3748 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -18,11 +18,11 @@
#include <cmath>
-#include "char_utils.h"
#include "correction.h"
#include "defines.h"
-#include "proximity_info_state.h"
-#include "suggest_utils.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/proximity_info_state.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
#include "suggest/policyimpl/utils/edit_distance.h"
#include "suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h"
@@ -528,7 +528,7 @@ inline static int getQuoteCount(const int *word, const int length) {
}
inline static bool isUpperCase(unsigned short c) {
- return isAsciiUpper(toBaseCodePoint(c));
+ return CharUtils::isAsciiUpper(CharUtils::toBaseCodePoint(c));
}
//////////////////////
@@ -676,8 +676,8 @@ inline static bool isUpperCase(unsigned short c) {
if (i < adjustedProximityMatchedCount) {
multiplyIntCapped(typedLetterMultiplier, &finalFreq);
}
- const float factor =
- SuggestUtils::getLengthScalingFactor(static_cast<float>(squaredDistance));
+ const float factor = TouchPositionCorrectionUtils::getLengthScalingFactor(
+ static_cast<float>(squaredDistance));
if (factor > 0.0f) {
multiplyRate(static_cast<int>(factor * 100.0f), &finalFreq);
} else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) {
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index a9e9b48a6..3f60d48cf 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -21,7 +21,8 @@
#include "correction_state.h"
#include "defines.h"
-#include "proximity_info_state.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/proximity_info_state.h"
namespace latinime {
@@ -342,13 +343,13 @@ AK_FORCE_INLINE static void calcEditDistanceOneStep(int *editDistanceTable, cons
const int *const prevprev =
outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputSize + 1) : 0;
current[0] = outputLength;
- const int co = toBaseLowerCase(output[outputLength - 1]);
- const int prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0;
+ const int co = CharUtils::toBaseLowerCase(output[outputLength - 1]);
+ const int prevCO = outputLength >= 2 ? CharUtils::toBaseLowerCase(output[outputLength - 2]) : 0;
for (int i = 1; i <= inputSize; ++i) {
- const int ci = toBaseLowerCase(input[i - 1]);
+ const int ci = CharUtils::toBaseLowerCase(input[i - 1]);
const int cost = (ci == co) ? 0 : 1;
current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost));
- if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) {
+ if (i >= 2 && prevprev && ci == prevCO && co == CharUtils::toBaseLowerCase(input[i - 2])) {
current[i] = min(current[i], prevprev[i - 2] + 1);
}
}
diff --git a/native/jni/src/dic_traverse_wrapper.cpp b/native/jni/src/dic_traverse_wrapper.cpp
index 88ca9fa0d..ec8c62dcc 100644
--- a/native/jni/src/dic_traverse_wrapper.cpp
+++ b/native/jni/src/dic_traverse_wrapper.cpp
@@ -22,5 +22,5 @@ namespace latinime {
void *(*DicTraverseWrapper::sDicTraverseSessionFactoryMethod)(JNIEnv *, jstring) = 0;
void (*DicTraverseWrapper::sDicTraverseSessionReleaseMethod)(void *) = 0;
void (*DicTraverseWrapper::sDicTraverseSessionInitMethod)(
- void *, const Dictionary *const, const int *, const int) = 0;
+ void *, const Dictionary *const, const int *, const int, const SuggestOptions *const) = 0;
} // namespace latinime
diff --git a/native/jni/src/dic_traverse_wrapper.h b/native/jni/src/dic_traverse_wrapper.h
index 1108a45c8..43b4c9ade 100644
--- a/native/jni/src/dic_traverse_wrapper.h
+++ b/native/jni/src/dic_traverse_wrapper.h
@@ -22,6 +22,7 @@
namespace latinime {
class Dictionary;
+class SuggestOptions;
// TODO: Remove
class DicTraverseWrapper {
public:
@@ -32,9 +33,11 @@ class DicTraverseWrapper {
return 0;
}
static void initDicTraverseSession(void *traverseSession, const Dictionary *const dictionary,
- const int *prevWord, const int prevWordLength) {
+ const int *prevWord, const int prevWordLength,
+ const SuggestOptions *const suggestOptions) {
if (sDicTraverseSessionInitMethod) {
- sDicTraverseSessionInitMethod(traverseSession, dictionary, prevWord, prevWordLength);
+ sDicTraverseSessionInitMethod(
+ traverseSession, dictionary, prevWord, prevWordLength, suggestOptions);
}
}
static void releaseDicTraverseSession(void *traverseSession) {
@@ -46,7 +49,8 @@ class DicTraverseWrapper {
sDicTraverseSessionFactoryMethod = factoryMethod;
}
static void setTraverseSessionInitMethod(
- void (*initMethod)(void *, const Dictionary *const, const int *, const int)) {
+ void (*initMethod)(void *, const Dictionary *const, const int *, const int,
+ const SuggestOptions *const)) {
sDicTraverseSessionInitMethod = initMethod;
}
static void setTraverseSessionReleaseMethod(void (*releaseMethod)(void *)) {
@@ -57,7 +61,7 @@ class DicTraverseWrapper {
DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseWrapper);
static void *(*sDicTraverseSessionFactoryMethod)(JNIEnv *, jstring);
static void (*sDicTraverseSessionInitMethod)(
- void *, const Dictionary *const, const int *, const int);
+ void *, const Dictionary *const, const int *, const int, const SuggestOptions *const);
static void (*sDicTraverseSessionReleaseMethod)(void *);
};
} // namespace latinime
diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h
deleted file mode 100644
index 4cbb127e8..000000000
--- a/native/jni/src/geometry_utils.h
+++ /dev/null
@@ -1,53 +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_GEOMETRY_UTILS_H
-#define LATINIME_GEOMETRY_UTILS_H
-
-#include <cmath>
-
-#include "defines.h"
-
-#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
- ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
-
-namespace latinime {
-
-static inline float SQUARE_FLOAT(const float x) { return x * x; }
-
-static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
- const int dx = x1 - x2;
- const int dy = y1 - y2;
- if (dx == 0 && dy == 0) return 0.0f;
- return atan2f(static_cast<float>(dy), static_cast<float>(dx));
-}
-
-static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
- const float deltaA = fabsf(a1 - a2);
- const float diff = ROUND_FLOAT_10000(deltaA);
- if (diff > M_PI_F) {
- const float normalizedDiff = 2.0f * M_PI_F - diff;
- return ROUND_FLOAT_10000(normalizedDiff);
- }
- return diff;
-}
-
-static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
- const int y2) {
- return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
-}
-} // namespace latinime
-#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp
index 8c48c587b..de088c7d0 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "dic_node.h"
+#include "suggest/core/dicnode/dic_node.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 4225bb3e5..14bd2d57a 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -17,13 +17,13 @@
#ifndef LATINIME_DIC_NODE_H
#define LATINIME_DIC_NODE_H
-#include "char_utils.h"
#include "defines.h"
-#include "dic_node_state.h"
-#include "dic_node_profiler.h"
-#include "dic_node_properties.h"
-#include "dic_node_release_listener.h"
-#include "digraph_utils.h"
+#include "suggest/core/dicnode/dic_node_state.h"
+#include "suggest/core/dicnode/dic_node_profiler.h"
+#include "suggest/core/dicnode/dic_node_properties.h"
+#include "suggest/core/dicnode/dic_node_release_listener.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/dictionary/digraph_utils.h"
#if DEBUG_DICT
#define LOGI_SHOW_ADD_COST_PROP \
@@ -221,7 +221,7 @@ class DicNode {
bool isFirstCharUppercase() const {
const int c = getOutputWordBuf()[0];
- return isAsciiUpper(c);
+ return CharUtils::isAsciiUpper(c);
}
bool isFirstWord() const {
@@ -375,7 +375,7 @@ class DicNode {
// Whether the current codepoint can be an intentional omission, in which case the traversal
// algorithm will always check for a possible omission here.
bool canBeIntentionalOmission() const {
- return isIntentionalOmissionCodePoint(getNodeCodePoint());
+ return CharUtils::isIntentionalOmissionCodePoint(getNodeCodePoint());
}
// Whether the omission is so frequent that it should incur zero cost.
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
index d3f28a8bd..970e3bda4 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h
@@ -21,8 +21,8 @@
#include <vector>
#include "defines.h"
-#include "dic_node.h"
-#include "dic_node_release_listener.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_release_listener.h"
#define MAX_DIC_NODE_PRIORITY_QUEUE_CAPACITY 200
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
index 63a6b1340..d2f87c10b 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_properties.h
@@ -19,8 +19,8 @@
#include <stdint.h>
-#include "binary_format.h"
#include "defines.h"
+#include "suggest/core/dictionary/binary_format.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state.h b/native/jni/src/suggest/core/dicnode/dic_node_state.h
index 239b63c32..d35e7d79f 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_state.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state.h
@@ -18,10 +18,10 @@
#define LATINIME_DIC_NODE_STATE_H
#include "defines.h"
-#include "dic_node_state_input.h"
-#include "dic_node_state_output.h"
-#include "dic_node_state_prevword.h"
-#include "dic_node_state_scoring.h"
+#include "suggest/core/dicnode/dic_node_state_input.h"
+#include "suggest/core/dicnode/dic_node_state_output.h"
+#include "suggest/core/dicnode/dic_node_state_prevword.h"
+#include "suggest/core/dicnode/dic_node_state_scoring.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h
index e3b892bda..c3968c090 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_prevword.h
@@ -21,7 +21,7 @@
#include <stdint.h>
#include "defines.h"
-#include "dic_node_utils.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
index dca9d60da..4c884225a 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_state_scoring.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include "defines.h"
-#include "digraph_utils.h"
+#include "suggest/core/dictionary/digraph_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 5357c3773..c754a5ec2 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -17,13 +17,14 @@
#include <cstring>
#include <vector>
-#include "binary_format.h"
-#include "dic_node.h"
-#include "dic_node_utils.h"
-#include "dic_node_vector.h"
-#include "multi_bigram_map.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/dictionary/multi_bigram_map.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state.h"
namespace latinime {
@@ -62,9 +63,9 @@ namespace latinime {
DicNodeVector *childDicNodes) {
// Passing multiple chars node. No need to traverse child
const int codePoint = dicNode->getNodeTypedCodePoint();
- const int baseLowerCaseCodePoint = toBaseLowerCase(codePoint);
+ const int baseLowerCaseCodePoint = CharUtils::toBaseLowerCase(codePoint);
const bool isMatch = isMatchedNodeCodePoint(pInfoState, pointIndex, exactOnly, codePoint);
- if (isMatch || isIntentionalOmissionCodePoint(baseLowerCaseCodePoint)) {
+ if (isMatch || CharUtils::isIntentionalOmissionCodePoint(baseLowerCaseCodePoint)) {
childDicNodes->pushPassingChild(dicNode);
}
}
@@ -125,13 +126,13 @@ namespace latinime {
return false;
}
if (pInfo && (pInfo->getKeyIndexOf(nodeCodePoint) == NOT_AN_INDEX
- || isIntentionalOmissionCodePoint(nodeCodePoint))) {
+ || CharUtils::isIntentionalOmissionCodePoint(nodeCodePoint))) {
// If normalized nodeCodePoint is not on the keyboard or skippable, this child is never
// filtered.
return false;
}
- const int lowerCodePoint = toLowerCase(nodeCodePoint);
- const int baseLowerCodePoint = toBaseCodePoint(lowerCodePoint);
+ const int lowerCodePoint = CharUtils::toLowerCase(nodeCodePoint);
+ const int baseLowerCodePoint = CharUtils::toBaseCodePoint(lowerCodePoint);
// TODO: Avoid linear search
for (int i = 0; i < filterSize; ++i) {
// Checking if a normalized code point is in filter characters when pInfo is not
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
index ca07edaee..e23c411f0 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_vector.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -20,7 +20,7 @@
#include <vector>
#include "defines.h"
-#include "dic_node.h"
+#include "suggest/core/dicnode/dic_node.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp
index b9a60780b..c3d2a2e74 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.cpp
@@ -17,9 +17,9 @@
#include <list>
#include "defines.h"
-#include "dic_node_priority_queue.h"
-#include "dic_node_utils.h"
-#include "dic_nodes_cache.h"
+#include "suggest/core/dicnode/dic_node_priority_queue.h"
+#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dicnode/dic_nodes_cache.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
index a62aa422a..7f5bdbcf6 100644
--- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
+++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include "defines.h"
-#include "dic_node_priority_queue.h"
+#include "suggest/core/dicnode/dic_node_priority_queue.h"
#define INITIAL_QUEUE_ID_ACTIVE 0
#define INITIAL_QUEUE_ID_NEXT_ACTIVE 1
diff --git a/native/jni/src/binary_format.h b/native/jni/src/suggest/core/dictionary/binary_format.h
index 98241532f..ef9fd3785 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/suggest/core/dictionary/binary_format.h
@@ -21,9 +21,9 @@
#include <map>
#include <stdint.h>
-#include "bloom_filter.h"
-#include "char_utils.h"
#include "hash_map_compat.h"
+#include "suggest/core/dictionary/bloom_filter.h"
+#include "suggest/core/dictionary/char_utils.h"
namespace latinime {
@@ -473,7 +473,8 @@ AK_FORCE_INLINE int BinaryFormat::getTerminalPosition(const uint8_t *const root,
// there was no match (or we would have found it).
if (wordPos >= length) return NOT_VALID_WORD;
int charGroupCount = BinaryFormat::getGroupCountAndForwardPointer(root, &pos);
- const int wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos];
+ const int wChar = forceLowerCaseSearch
+ ? CharUtils::toLowerCase(inWord[wordPos]) : inWord[wordPos];
while (true) {
// If there are no more character groups in this node, it means we could not
// find a matching character for this depth, therefore there is no match.
diff --git a/native/jni/src/bloom_filter.h b/native/jni/src/suggest/core/dictionary/bloom_filter.h
index bcce1f7ea..bcce1f7ea 100644
--- a/native/jni/src/bloom_filter.h
+++ b/native/jni/src/suggest/core/dictionary/bloom_filter.h
diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/suggest/core/dictionary/char_utils.cpp
index e219beb62..8d40e54c9 100644
--- a/native/jni/src/char_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/char_utils.cpp
@@ -14,9 +14,10 @@
* limitations under the License.
*/
+#include "suggest/core/dictionary/char_utils.h"
+
#include <cstdlib>
-#include "char_utils.h"
#include "defines.h"
namespace latinime {
@@ -36,8 +37,7 @@ struct LatinCapitalSmallPair {
* $ apt-get install libicu-dev
*
* 3. Build the following code
- * (You need this file, char_utils.h, and defines.h)
- * $ g++ -o char_utils -DUPDATING_CHAR_UTILS char_utils.cpp -licuuc
+ * $ g++ -o char_utils -I../../.. -DUPDATING_CHAR_UTILS char_utils.cpp -licuuc
*/
#ifdef UPDATING_CHAR_UTILS
#include <stdio.h>
@@ -47,7 +47,7 @@ extern "C" int main() {
for (unsigned short c = 0; c < 0xFFFF; c++) {
if (c <= 0x7F) continue;
const unsigned short icu4cLowerC = u_tolower(c);
- const unsigned short myLowerC = latin_tolower(c);
+ const unsigned short myLowerC = CharUtils::latin_tolower(c);
if (c != icu4cLowerC) {
#ifdef CONFIRMING_CHAR_UTILS
if (icu4cLowerC != myLowerC) {
@@ -70,7 +70,8 @@ extern "C" int main() {
*
* 5. Update the SORTED_CHAR_MAP[] array below with the output above.
* Then, rebuild with -DCONFIRMING_CHAR_UTILS and confirm the program exits successfully.
- * $ g++ -o char_utils -DUPDATING_CHAR_UTILS -DCONFIRMING_CHAR_UTILS char_utils.cpp -licuuc
+ * $ g++ -o char_utils -I../../.. -DUPDATING_CHAR_UTILS -DCONFIRMING_CHAR_UTILS char_utils.cpp \
+ * -licuuc
* $ ./char_utils
* $
*/
@@ -1054,7 +1055,7 @@ static int compare_pair_capital(const void *a, const void *b) {
- static_cast<int>((static_cast<const struct LatinCapitalSmallPair *>(b))->capital);
}
-unsigned short latin_tolower(const unsigned short c) {
+/* static */ unsigned short CharUtils::latin_tolower(const unsigned short c) {
struct LatinCapitalSmallPair *p =
static_cast<struct LatinCapitalSmallPair *>(bsearch(&c, SORTED_CHAR_MAP,
NELEMS(SORTED_CHAR_MAP), sizeof(SORTED_CHAR_MAP[0]), compare_pair_capital));
@@ -1063,7 +1064,7 @@ unsigned short latin_tolower(const unsigned short c) {
/*
* Table mapping most combined Latin, Greek, and Cyrillic characters
- * to their base characters. If c is in range, BASE_CHARS[c] == c
+ * to their base characters. If c is in range, CharUtils::BASE_CHARS[c] == c
* if c is not a combined character, or the base character if it
* is combined.
*
@@ -1074,7 +1075,7 @@ unsigned short latin_tolower(const unsigned short c) {
* for ($j = $i; $j < $i + 8; $j++) { \
* printf("0x%04X, ", $base[$j] ? $base[$j] : $j)}; print "\n"; }'
*/
-const unsigned short BASE_CHARS[BASE_CHARS_SIZE] = {
+/* static */ const unsigned short CharUtils::BASE_CHARS[CharUtils::BASE_CHARS_SIZE] = {
/* U+0000 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
/* U+0008 */ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
/* U+0010 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
diff --git a/native/jni/src/suggest/core/dictionary/char_utils.h b/native/jni/src/suggest/core/dictionary/char_utils.h
new file mode 100644
index 000000000..2e735a81c
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/char_utils.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 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_CHAR_UTILS_H
+#define LATINIME_CHAR_UTILS_H
+
+#include <cctype>
+
+#include "defines.h"
+
+namespace latinime {
+
+class CharUtils {
+ public:
+ static AK_FORCE_INLINE bool isAsciiUpper(int c) {
+ // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to
+ // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...).
+ return (c >= 'A' && c <= 'Z');
+ }
+
+ static AK_FORCE_INLINE int toAsciiLower(int c) {
+ return c - 'A' + 'a';
+ }
+
+ static AK_FORCE_INLINE bool isAscii(int c) {
+ return isascii(c) != 0;
+ }
+
+ static AK_FORCE_INLINE int toLowerCase(const int c) {
+ if (isAsciiUpper(c)) {
+ return toAsciiLower(c);
+ }
+ if (isAscii(c)) {
+ return c;
+ }
+ return static_cast<int>(latin_tolower(static_cast<unsigned short>(c)));
+ }
+
+ static AK_FORCE_INLINE int toBaseLowerCase(const int c) {
+ return toLowerCase(toBaseCodePoint(c));
+ }
+
+ static AK_FORCE_INLINE bool isIntentionalOmissionCodePoint(const int codePoint) {
+ // TODO: Do not hardcode here
+ return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS;
+ }
+
+ static AK_FORCE_INLINE int getCodePointCount(const int arraySize, const int *const codePoints) {
+ int size = 0;
+ for (; size < arraySize; ++size) {
+ if (codePoints[size] == '\0') {
+ break;
+ }
+ }
+ return size;
+ }
+
+ static AK_FORCE_INLINE int toBaseCodePoint(int c) {
+ if (c < BASE_CHARS_SIZE) {
+ return static_cast<int>(BASE_CHARS[c]);
+ }
+ return c;
+ }
+
+ static unsigned short latin_tolower(const unsigned short c);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(CharUtils);
+
+ /**
+ * Table mapping most combined Latin, Greek, and Cyrillic characters
+ * to their base characters. If c is in range, BASE_CHARS[c] == c
+ * if c is not a combined character, or the base character if it
+ * is combined.
+ */
+ static const int BASE_CHARS_SIZE = 0x0500;
+ static const unsigned short BASE_CHARS[BASE_CHARS_SIZE];
+};
+} // namespace latinime
+#endif // LATINIME_CHAR_UTILS_H
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index dadb2bab2..1939c7420 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -16,16 +16,17 @@
#define LOG_TAG "LatinIME: dictionary.cpp"
-#include "dictionary.h"
+#include "suggest/core/dictionary/dictionary.h"
#include <map> // TODO: remove
#include <stdint.h>
#include "bigram_dictionary.h"
-#include "binary_format.h"
#include "defines.h"
#include "dic_traverse_wrapper.h"
+#include "suggest_options.h"
#include "suggest/core/suggest.h"
+#include "suggest/core/dictionary/binary_format.h"
#include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
#include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
#include "unigram_dictionary.h"
@@ -53,13 +54,13 @@ Dictionary::~Dictionary() {
int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession,
int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
- int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint, bool isGesture,
- bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices,
- int *outputTypes) const {
+ int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
+ const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
+ int *spaceIndices, int *outputTypes) const {
int result = 0;
- if (isGesture) {
+ if (suggestOptions->isGesture()) {
DicTraverseWrapper::initDicTraverseSession(
- traverseSession, this, prevWordCodePoints, prevWordLength);
+ traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
frequencies, spaceIndices, outputTypes);
@@ -70,7 +71,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi
} else {
if (USE_SUGGEST_INTERFACE_FOR_TYPING) {
DicTraverseWrapper::initDicTraverseSession(
- traverseSession, this, prevWordCodePoints, prevWordLength);
+ traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
outWords, frequencies, spaceIndices, outputTypes);
@@ -84,8 +85,8 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi
mBigramDictionary->fillBigramAddressToProbabilityMapAndFilter(prevWordCodePoints,
prevWordLength, &bigramMap, bigramFilter);
result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
- inputCodePoints, inputSize, &bigramMap, bigramFilter, useFullEditDistance,
- outWords, frequencies, outputTypes);
+ inputCodePoints, inputSize, &bigramMap, bigramFilter,
+ suggestOptions->useFullEditDistance(), outWords, frequencies, outputTypes);
return result;
}
}
diff --git a/native/jni/src/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index edec83fbf..e6861a3dd 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -26,6 +26,7 @@ namespace latinime {
class BigramDictionary;
class ProximityInfo;
class SuggestInterface;
+class SuggestOptions;
class UnigramDictionary;
class Dictionary {
@@ -54,9 +55,9 @@ class Dictionary {
int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates,
int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints, int inputSize,
- int *prevWordCodePoints, int prevWordLength, int commitPoint, bool isGesture,
- bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices,
- int *outputTypes) const;
+ int *prevWordCodePoints, int prevWordLength, int commitPoint,
+ const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
+ int *spaceIndices, int *outputTypes) const;
int getBigrams(const int *word, int length, int *inputCodePoints, int inputSize, int *outWords,
int *frequencies, int *outputTypes) const;
diff --git a/native/jni/src/digraph_utils.cpp b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
index 083442669..e8cdd5352 100644
--- a/native/jni/src/digraph_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "char_utils.h"
-#include "binary_format.h"
+#include "suggest/core/dictionary/digraph_utils.h"
+
#include "defines.h"
-#include "digraph_utils.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/char_utils.h"
namespace latinime {
@@ -121,7 +122,7 @@ const DigraphUtils::DigraphType DigraphUtils::USED_DIGRAPH_TYPES[] =
/* static */ const DigraphUtils::digraph_t *DigraphUtils::getDigraphForDigraphTypeAndCodePoint(
const DigraphUtils::DigraphType digraphType, const int compositeGlyphCodePoint) {
const DigraphUtils::digraph_t *digraphs = 0;
- const int compositeGlyphLowerCodePoint = toLowerCase(compositeGlyphCodePoint);
+ const int compositeGlyphLowerCodePoint = CharUtils::toLowerCase(compositeGlyphCodePoint);
const int digraphsSize =
DigraphUtils::getAllDigraphsForDictionaryAndReturnSize(digraphType, &digraphs);
for (int i = 0; i < digraphsSize; i++) {
diff --git a/native/jni/src/digraph_utils.h b/native/jni/src/suggest/core/dictionary/digraph_utils.h
index 94435228e..c1205940c 100644
--- a/native/jni/src/digraph_utils.h
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.h
@@ -17,6 +17,8 @@
#ifndef DIGRAPH_UTILS_H
#define DIGRAPH_UTILS_H
+#include "defines.h"
+
namespace latinime {
class DigraphUtils {
diff --git a/native/jni/src/multi_bigram_map.h b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
index 7e1b6301f..fcac98f35 100644
--- a/native/jni/src/multi_bigram_map.h
+++ b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
@@ -17,12 +17,11 @@
#ifndef LATINIME_MULTI_BIGRAM_MAP_H
#define LATINIME_MULTI_BIGRAM_MAP_H
-#include <cstring>
#include <stdint.h>
#include "defines.h"
-#include "binary_format.h"
#include "hash_map_compat.h"
+#include "suggest/core/dictionary/binary_format.h"
namespace latinime {
diff --git a/native/jni/src/suggest/core/dictionary/shortcut_utils.h b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
index c411408ec..601ac5f5a 100644
--- a/native/jni/src/suggest/core/dictionary/shortcut_utils.h
+++ b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
@@ -19,7 +19,7 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node_utils.h"
-#include "terminal_attributes.h"
+#include "suggest/core/dictionary/terminal_attributes.h"
namespace latinime {
diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/suggest/core/dictionary/terminal_attributes.h
index 92ef71c2c..8377c603d 100644
--- a/native/jni/src/terminal_attributes.h
+++ b/native/jni/src/suggest/core/dictionary/terminal_attributes.h
@@ -18,7 +18,8 @@
#define LATINIME_TERMINAL_ATTRIBUTES_H
#include <stdint.h>
-#include "binary_format.h"
+
+#include "suggest/core/dictionary/binary_format.h"
namespace latinime {
diff --git a/native/jni/src/additional_proximity_chars.cpp b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
index 661c50e91..34b8b37b0 100644
--- a/native/jni/src/additional_proximity_chars.cpp
+++ b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "additional_proximity_chars.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
namespace latinime {
// TODO: Stop using hardcoded additional proximity characters.
diff --git a/native/jni/src/additional_proximity_chars.h b/native/jni/src/suggest/core/layout/additional_proximity_chars.h
index a88fd6cea..a88fd6cea 100644
--- a/native/jni/src/additional_proximity_chars.h
+++ b/native/jni/src/suggest/core/layout/additional_proximity_chars.h
diff --git a/native/jni/src/suggest/core/layout/geometry_utils.h b/native/jni/src/suggest/core/layout/geometry_utils.h
new file mode 100644
index 000000000..b667df68f
--- /dev/null
+++ b/native/jni/src/suggest/core/layout/geometry_utils.h
@@ -0,0 +1,59 @@
+/*
+ * 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_GEOMETRY_UTILS_H
+#define LATINIME_GEOMETRY_UTILS_H
+
+#include <cmath>
+
+#include "defines.h"
+
+#define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \
+ ? (floorf((f) * 10000.0f) / 10000.0f) : (f)
+
+namespace latinime {
+
+class GeometryUtils {
+ public:
+ static inline float SQUARE_FLOAT(const float x) { return x * x; }
+
+ static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) {
+ const int dx = x1 - x2;
+ const int dy = y1 - y2;
+ if (dx == 0 && dy == 0) return 0.0f;
+ return atan2f(static_cast<float>(dy), static_cast<float>(dx));
+ }
+
+ static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
+ const float deltaA = fabsf(a1 - a2);
+ const float diff = ROUND_FLOAT_10000(deltaA);
+ if (diff > M_PI_F) {
+ const float normalizedDiff = 2.0f * M_PI_F - diff;
+ return ROUND_FLOAT_10000(normalizedDiff);
+ }
+ return diff;
+ }
+
+ static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
+ const int y2) {
+ return static_cast<int>(hypotf(static_cast<float>(x1 - x2), static_cast<float>(y1 - y2)));
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(GeometryUtils);
+};
+} // namespace latinime
+#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
index 88d670d61..0b5d71a43 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -14,18 +14,19 @@
* limitations under the License.
*/
+#define LOG_TAG "LatinIME: proximity_info.cpp"
+
+#include "suggest/core/layout/proximity_info.h"
+
#include <cstring>
#include <cmath>
-#define LOG_TAG "LatinIME: proximity_info.cpp"
-
-#include "additional_proximity_chars.h"
-#include "char_utils.h"
#include "defines.h"
-#include "geometry_utils.h"
#include "jni.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
namespace latinime {
@@ -58,7 +59,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr,
MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
MOST_COMMON_KEY_HEIGHT(mostCommonKeyHeight),
NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE(1.0f +
- SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
+ GeometryUtils::SQUARE_FLOAT(static_cast<float>(mostCommonKeyHeight) /
static_cast<float>(mostCommonKeyWidth))),
CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
@@ -150,7 +151,7 @@ float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
const float touchY = static_cast<float>(y);
const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
- / SQUARE_FLOAT(keyWidth);
+ / GeometryUtils::SQUARE_FLOAT(keyWidth);
}
int ProximityInfo::getCodePointOf(const int keyIndex) const {
@@ -164,7 +165,7 @@ void ProximityInfo::initializeG() {
// TODO: Optimize
for (int i = 0; i < KEY_COUNT; ++i) {
const int code = mKeyCodePoints[i];
- const int lowerCode = toLowerCase(code);
+ const int lowerCode = CharUtils::toLowerCase(code);
mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
mCodeToKeyMap[lowerCode] = i;
@@ -173,7 +174,7 @@ void ProximityInfo::initializeG() {
for (int i = 0; i < KEY_COUNT; i++) {
mKeyKeyDistancesG[i][i] = 0;
for (int j = i + 1; j < KEY_COUNT; j++) {
- mKeyKeyDistancesG[i][j] = getDistanceInt(
+ mKeyKeyDistancesG[i][j] = GeometryUtils::getDistanceInt(
mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
}
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/suggest/core/layout/proximity_info.h
index deb9ae0de..6d2ddd4bc 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/suggest/core/layout/proximity_info.h
@@ -20,7 +20,7 @@
#include "defines.h"
#include "hash_map_compat.h"
#include "jni.h"
-#include "proximity_info_utils.h"
+#include "suggest/core/layout/proximity_info_utils.h"
namespace latinime {
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
index 2675d9e70..0e887f700 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_params.cpp
@@ -15,7 +15,7 @@
*/
#include "defines.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_params.h"
namespace latinime {
const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/suggest/core/layout/proximity_info_params.h
index 4e47f7308..4e47f7308 100644
--- a/native/jni/src/proximity_info_params.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_params.h
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
index cc5b736bd..412d5508b 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -14,17 +14,19 @@
* limitations under the License.
*/
+#define LOG_TAG "LatinIME: proximity_info_state.cpp"
+
+#include "suggest/core/layout/proximity_info_state.h"
+
#include <cstring> // for memset() and memcpy()
#include <sstream> // for debug prints
#include <vector>
-#define LOG_TAG "LatinIME: proximity_info_state.cpp"
-
#include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_state.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
namespace latinime {
@@ -174,7 +176,7 @@ float ProximityInfoState::getPointToKeyLength(
const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
return min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength);
}
- if (isIntentionalOmissionCodePoint(codePoint)) {
+ if (CharUtils::isIntentionalOmissionCodePoint(codePoint)) {
return 0.0f;
}
// If the char is not a key on the keyboard then return the max length.
@@ -202,7 +204,7 @@ ProximityType ProximityInfoState::getProximityType(const int index, const int co
const bool checkProximityChars, int *proximityIndex) const {
const int *currentCodePoints = getProximityCodePointsAt(index);
const int firstCodePoint = currentCodePoints[0];
- const int baseLowerC = toBaseLowerCase(codePoint);
+ const int baseLowerC = CharUtils::toBaseLowerCase(codePoint);
// The first char in the array is what user typed. If it matches right away, that means the
// user typed that same char for this pos.
@@ -214,7 +216,7 @@ ProximityType ProximityInfoState::getProximityType(const int index, const int co
// If the non-accented, lowercased version of that first character matches c, then we have a
// non-accented version of the accented character the user typed. Treat it as a close char.
- if (toBaseLowerCase(firstCodePoint) == baseLowerC) {
+ if (CharUtils::toBaseLowerCase(firstCodePoint) == baseLowerC) {
return PROXIMITY_CHAR;
}
@@ -256,8 +258,8 @@ ProximityType ProximityInfoState::getProximityTypeG(const int index, const int c
if (!isUsed()) {
return UNRELATED_CHAR;
}
- const int lowerCodePoint = toLowerCase(codePoint);
- const int baseLowerCodePoint = toBaseCodePoint(lowerCodePoint);
+ const int lowerCodePoint = CharUtils::toLowerCase(codePoint);
+ const int baseLowerCodePoint = CharUtils::toBaseCodePoint(lowerCodePoint);
for (int i = 0; i < static_cast<int>(mSampledSearchKeyVectors[index].size()); ++i) {
if (mSampledSearchKeyVectors[index][i] == lowerCodePoint
|| mSampledSearchKeyVectors[index][i] == baseLowerCodePoint) {
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/suggest/core/layout/proximity_info_state.h
index bbe8af240..a971294e3 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.h
@@ -20,11 +20,10 @@
#include <cstring> // for memset()
#include <vector>
-#include "char_utils.h"
#include "defines.h"
#include "hash_map_compat.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_state_utils.h"
namespace latinime {
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
index 359673cd8..6f88833a2 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp
@@ -14,16 +14,17 @@
* limitations under the License.
*/
+#include "suggest/core/layout/proximity_info_state_utils.h"
+
#include <cmath>
#include <cstring> // for memset()
#include <sstream> // for debug prints
#include <vector>
#include "defines.h"
-#include "geometry_utils.h"
-#include "proximity_info.h"
-#include "proximity_info_params.h"
-#include "proximity_info_state_utils.h"
+#include "suggest/core/layout/geometry_utils.h"
+#include "suggest/core/layout/proximity_info.h"
+#include "suggest/core/layout/proximity_info_params.h"
namespace latinime {
@@ -103,12 +104,12 @@ namespace latinime {
const int time = times ? times[i] : -1;
if (i > 1) {
- const float prevAngle = getAngle(
+ const float prevAngle = GeometryUtils::getAngle(
inputXCoordinates[i - 2], inputYCoordinates[i - 2],
inputXCoordinates[i - 1], inputYCoordinates[i - 1]);
- const float currentAngle = getAngle(
+ const float currentAngle = GeometryUtils::getAngle(
inputXCoordinates[i - 1], inputYCoordinates[i - 1], x, y);
- sumAngle += getAngleDiff(prevAngle, currentAngle);
+ sumAngle += GeometryUtils::getAngleDiff(prevAngle, currentAngle);
}
if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time,
@@ -157,7 +158,8 @@ namespace latinime {
const float sweetSpotCenterY = proximityInfo->getSweetSpotCenterYAt(keyIndex);
const float inputX = static_cast<float>((*sampledInputXs)[inputIndex]);
const float inputY = static_cast<float>((*sampledInputYs)[inputIndex]);
- return SQUARE_FLOAT(inputX - sweetSpotCenterX) + SQUARE_FLOAT(inputY - sweetSpotCenterY);
+ return GeometryUtils::SQUARE_FLOAT(inputX - sweetSpotCenterX)
+ + GeometryUtils::SQUARE_FLOAT(inputY - sweetSpotCenterY);
}
/* static */ float ProximityInfoStateUtils::calculateNormalizedSquaredDistance(
@@ -174,7 +176,8 @@ namespace latinime {
}
const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(proximityInfo,
sampledInputXs, sampledInputYs, keyIndex, inputIndex);
- const float squaredRadius = SQUARE_FLOAT(proximityInfo->getSweetSpotRadiiAt(keyIndex));
+ const float squaredRadius = GeometryUtils::SQUARE_FLOAT(
+ proximityInfo->getSweetSpotRadiiAt(keyIndex));
return squaredDistance / squaredRadius;
}
@@ -285,7 +288,7 @@ namespace latinime {
if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) {
break;
}
- length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+ length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
xCoordinates[j + 1], yCoordinates[j + 1]);
duration += times[j + 1] - times[j];
}
@@ -296,7 +299,7 @@ namespace latinime {
break;
}
// TODO: use mSampledLengthCache instead?
- length += getDistanceInt(xCoordinates[j], yCoordinates[j],
+ length += GeometryUtils::getDistanceInt(xCoordinates[j], yCoordinates[j],
xCoordinates[j + 1], yCoordinates[j + 1]);
duration += times[j + 1] - times[j];
}
@@ -349,7 +352,7 @@ namespace latinime {
const int y1 = (*sampledInputYs)[index0];
const int x2 = (*sampledInputXs)[index1];
const int y2 = (*sampledInputYs)[index1];
- return getAngle(x1, y1, x2, y2);
+ return GeometryUtils::getAngle(x1, y1, x2, y2);
}
// Calculating point to key distance for all near keys and returning the distance between
@@ -411,9 +414,9 @@ namespace latinime {
}
const int baseSampleRate = mostCommonKeyWidth;
- const int distPrev = getDistanceInt(sampledInputXs->back(), sampledInputYs->back(),
- (*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2])
- * ProximityInfoParams::DISTANCE_BASE_SCALE;
+ const int distPrev = GeometryUtils::getDistanceInt(sampledInputXs->back(),
+ sampledInputYs->back(), (*sampledInputXs)[size - 2],
+ (*sampledInputYs)[size - 2]) * ProximityInfoParams::DISTANCE_BASE_SCALE;
float score = 0.0f;
// Location
@@ -425,10 +428,11 @@ namespace latinime {
score += ProximityInfoParams::LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE;
}
// Angle
- const float angle1 = getAngle(x, y, sampledInputXs->back(), sampledInputYs->back());
- const float angle2 = getAngle(sampledInputXs->back(), sampledInputYs->back(),
+ const float angle1 = GeometryUtils::getAngle(x, y, sampledInputXs->back(),
+ sampledInputYs->back());
+ const float angle2 = GeometryUtils::getAngle(sampledInputXs->back(), sampledInputYs->back(),
(*sampledInputXs)[size - 2], (*sampledInputYs)[size - 2]);
- const float angleDiff = getAngleDiff(angle1, angle2);
+ const float angleDiff = GeometryUtils::getAngleDiff(angle1, angle2);
// Save corner
if (distPrev > baseSampleRate * ProximityInfoParams::CORNER_CHECK_DISTANCE_THRESHOLD_SCALE
@@ -472,13 +476,13 @@ namespace latinime {
}
// Check if the last point should be skipped.
if (isLastPoint && size > 0) {
- if (getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
+ if (GeometryUtils::getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back())
* ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE < mostCommonKeyWidth) {
// This point is not used because it's too close to the previous point.
if (DEBUG_GEO_FULL) {
AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, "
"width = %d", size, x, y, sampledInputXs->back(),
- sampledInputYs->back(), getDistanceInt(
+ sampledInputYs->back(), GeometryUtils::getDistanceInt(
x, y, sampledInputXs->back(), sampledInputYs->back()),
mostCommonKeyWidth
/ ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE);
@@ -499,7 +503,7 @@ namespace latinime {
// Pushing point information.
if (size > 0) {
sampledLengthCache->push_back(
- sampledLengthCache->back() + getDistanceInt(
+ sampledLengthCache->back() + GeometryUtils::getDistanceInt(
x, y, sampledInputXs->back(), sampledInputYs->back()));
} else {
sampledLengthCache->push_back(0);
@@ -540,7 +544,8 @@ namespace latinime {
while (start > 0 && tempBeelineDistance < lookupRadius) {
tempTime += times[start] - times[start - 1];
--start;
- tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[start], yCoordinates[start]);
+ tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[start],
+ yCoordinates[start]);
}
// Exclusive unless this is an edge point
if (start > 0 && start < actualInputIndex) {
@@ -553,7 +558,8 @@ namespace latinime {
while (end < (inputSize - 1) && tempBeelineDistance < lookupRadius) {
tempTime += times[end + 1] - times[end];
++end;
- tempBeelineDistance = getDistanceInt(x0, y0, xCoordinates[end], yCoordinates[end]);
+ tempBeelineDistance = GeometryUtils::getDistanceInt(x0, y0, xCoordinates[end],
+ yCoordinates[end]);
}
// Exclusive unless this is an edge point
if (end > actualInputIndex && end < (inputSize - 1)) {
@@ -571,7 +577,7 @@ namespace latinime {
const int y2 = yCoordinates[start];
const int x3 = xCoordinates[end];
const int y3 = yCoordinates[end];
- const int beelineDistance = getDistanceInt(x2, y2, x3, y3);
+ const int beelineDistance = GeometryUtils::getDistanceInt(x2, y2, x3, y3);
int adjustedStartTime = times[start];
if (start == 0 && actualInputIndex == 0 && inputSize > 1) {
adjustedStartTime += ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS;
@@ -613,7 +619,7 @@ namespace latinime {
}
const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index - 1, index);
const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index, index + 1);
- const float directionDiff = getAngleDiff(previousDirection, nextDirection);
+ const float directionDiff = GeometryUtils::getAngleDiff(previousDirection, nextDirection);
return directionDiff;
}
@@ -636,7 +642,7 @@ namespace latinime {
}
const float previousDirection = getDirection(sampledInputXs, sampledInputYs, index0, index1);
const float nextDirection = getDirection(sampledInputXs, sampledInputYs, index1, index2);
- return getAngleDiff(previousDirection, nextDirection);
+ return GeometryUtils::getAngleDiff(previousDirection, nextDirection);
}
// This function basically converts from a length to an edit distance. Accordingly, it's obviously
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
index 1837c7ab6..1837c7ab6 100644
--- a/native/jni/src/proximity_info_state_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.h
diff --git a/native/jni/src/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h
index 71c97e325..3588f4df8 100644
--- a/native/jni/src/proximity_info_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h
@@ -19,11 +19,11 @@
#include <cmath>
-#include "additional_proximity_chars.h"
-#include "char_utils.h"
#include "defines.h"
-#include "geometry_utils.h"
#include "hash_map_compat.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/additional_proximity_chars.h"
+#include "suggest/core/layout/geometry_utils.h"
namespace latinime {
class ProximityInfoUtils {
@@ -37,7 +37,7 @@ class ProximityInfoUtils {
if (c == NOT_A_CODE_POINT) {
return NOT_AN_INDEX;
}
- const int lowerCode = toLowerCase(c);
+ const int lowerCode = CharUtils::toLowerCase(c);
hash_map_compat<int, int>::const_iterator mapPos = codeToKeyMap->find(lowerCode);
if (mapPos != codeToKeyMap->end()) {
return mapPos->second;
@@ -87,7 +87,7 @@ class ProximityInfoUtils {
static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2,
const float y2) {
- return SQUARE_FLOAT(x1 - x2) + SQUARE_FLOAT(y1 - y2);
+ return GeometryUtils::SQUARE_FLOAT(x1 - x2) + GeometryUtils::SQUARE_FLOAT(y1 - y2);
}
static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y,
@@ -98,7 +98,8 @@ class ProximityInfoUtils {
const float ray2y = y2 - y1;
const float dotProduct = ray1x * ray2x + ray1y * ray2y;
- const float lineLengthSqr = SQUARE_FLOAT(ray2x) + SQUARE_FLOAT(ray2y);
+ const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x)
+ + GeometryUtils::SQUARE_FLOAT(ray2y);
const float projectionLengthSqr = dotProduct / lineLengthSqr;
float projectionX;
@@ -121,12 +122,14 @@ class ProximityInfoUtils {
public:
NormalDistribution(const float u, const float sigma)
: mU(u), mSigma(sigma),
- mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))),
- mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {}
+ mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F
+ * GeometryUtils::SQUARE_FLOAT(sigma))),
+ mPreComputedExponentPart(-1.0f / (2.0f * GeometryUtils::SQUARE_FLOAT(sigma))) {}
float getProbabilityDensity(const float x) const {
const float shiftedX = x - mU;
- return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX));
+ return mPreComputedNonExpPart
+ * expf(mPreComputedExponentPart * GeometryUtils::SQUARE_FLOAT(shiftedX));
}
private:
diff --git a/native/jni/src/suggest_utils.h b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
index e053dd662..429dcae0d 100644
--- a/native/jni/src/suggest_utils.h
+++ b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef LATINIME_SUGGEST_UTILS_H
-#define LATINIME_SUGGEST_UTILS_H
+#ifndef LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
+#define LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
#include "defines.h"
-#include "proximity_info_params.h"
+#include "suggest/core/layout/proximity_info_params.h"
namespace latinime {
-class SuggestUtils {
+class TouchPositionCorrectionUtils {
public:
// TODO: (OLD) Remove
static float getLengthScalingFactor(const float normalizedSquaredDistance) {
@@ -82,7 +82,7 @@ class SuggestUtils {
}
}
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestUtils);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(TouchPositionCorrectionUtils);
};
} // namespace latinime
-#endif // LATINIME_SUGGEST_UTILS_H
+#endif // LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index d01531f07..7ad568e25 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -16,7 +16,6 @@
#include "suggest/core/policy/weighting.h"
-#include "char_utils.h"
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
#include "suggest/core/dicnode/dic_node_profiler.h"
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 6408f0163..4e634500c 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -16,12 +16,12 @@
#include "suggest/core/session/dic_traverse_session.h"
-#include "binary_format.h"
#include "defines.h"
-#include "dictionary.h"
#include "dic_traverse_wrapper.h"
#include "jni.h"
#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/dictionary.h"
namespace latinime {
@@ -34,10 +34,11 @@ static void *getSessionInstance(JNIEnv *env, jstring localeStr) {
// TODO: Pass "DicTraverseSession *traverseSession" when the source code structure settles down.
static void initSessionInstance(void *traverseSession, const Dictionary *const dictionary,
- const int *prevWord, const int prevWordLength) {
+ const int *prevWord, const int prevWordLength,
+ const SuggestOptions *const suggestOptions) {
if (traverseSession) {
DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
- tSession->init(dictionary, prevWord, prevWordLength);
+ tSession->init(dictionary, prevWord, prevWordLength, suggestOptions);
}
}
@@ -62,10 +63,11 @@ class TraverseSessionFactoryRegisterer {
static TraverseSessionFactoryRegisterer traverseSessionFactoryRegisterer;
void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
- int prevWordLength) {
+ int prevWordLength, const SuggestOptions *const suggestOptions) {
mDictionary = dictionary;
mMultiWordCostMultiplier = BinaryFormat::getMultiWordCostMultiplier(mDictionary->getDict(),
mDictionary->getDictSize());
+ mSuggestOptions = suggestOptions;
if (!prevWord) {
mPrevWordPos = NOT_VALID_WORD;
return;
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 d88be5b88..e5c7f8e0c 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -22,20 +22,21 @@
#include "defines.h"
#include "jni.h"
-#include "multi_bigram_map.h"
-#include "proximity_info_state.h"
#include "suggest/core/dicnode/dic_nodes_cache.h"
+#include "suggest/core/dictionary/multi_bigram_map.h"
+#include "suggest/core/layout/proximity_info_state.h"
namespace latinime {
class Dictionary;
class ProximityInfo;
+class SuggestOptions;
class DicTraverseSession {
public:
AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr)
: mPrevWordPos(NOT_VALID_WORD), mProximityInfo(0),
- mDictionary(0), mDicNodesCache(), mMultiBigramMap(),
+ mDictionary(0), mSuggestOptions(0), mDicNodesCache(), mMultiBigramMap(),
mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
mMultiWordCostMultiplier(1.0f) {
// NOTE: mProximityInfoStates is an array of instances.
@@ -45,7 +46,8 @@ class DicTraverseSession {
// Non virtual inline destructor -- never inherit this class
AK_FORCE_INLINE ~DicTraverseSession() {}
- void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength);
+ void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength,
+ const SuggestOptions *const suggestOptions);
// TODO: Remove and merge into init
void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
const int inputSize, const int *const inputXs, const int *const inputYs,
@@ -61,6 +63,7 @@ class DicTraverseSession {
// getters and setters
//--------------------
const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
+ const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
int getPrevWordPos() const { return mPrevWordPos; }
// TODO: REMOVE
void setPrevWordPos(int pos) { mPrevWordPos = pos; }
@@ -167,6 +170,7 @@ class DicTraverseSession {
int mPrevWordPos;
const ProximityInfo *mProximityInfo;
const Dictionary *mDictionary;
+ const SuggestOptions *mSuggestOptions;
DicNodesCache mDicNodesCache;
// Temporary cache for bigram frequencies
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index a18794850..720222363 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -16,19 +16,18 @@
#include "suggest/core/suggest.h"
-#include "char_utils.h"
-#include "dictionary.h"
-#include "digraph_utils.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/dictionary.h"
+#include "suggest/core/dictionary/digraph_utils.h"
#include "suggest/core/dictionary/shortcut_utils.h"
+#include "suggest/core/dictionary/terminal_attributes.h"
+#include "suggest/core/layout/proximity_info.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 {
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index 12110d54f..e0664185c 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -19,11 +19,11 @@
#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/dictionary/char_utils.h"
+#include "suggest/core/layout/proximity_info_state.h"
#include "suggest/core/policy/traversal.h"
#include "suggest/core/session/dic_traverse_session.h"
#include "suggest/policyimpl/typing/scoring_params.h"
@@ -64,9 +64,9 @@ class TypingTraversal : public Traversal {
}
const int point0Index = dicNode->getInputIndex(0);
const int currentBaseLowerCodePoint =
- toBaseLowerCase(childDicNode->getNodeCodePoint());
+ CharUtils::toBaseLowerCase(childDicNode->getNodeCodePoint());
const int typedBaseLowerCodePoint =
- toBaseLowerCase(traverseSession->getProximityInfoState(0)
+ CharUtils::toBaseLowerCase(traverseSession->getProximityInfoState(0)
->getPrimaryCodePointAt(point0Index));
return (currentBaseLowerCodePoint != typedBaseLowerCodePoint);
}
@@ -172,7 +172,7 @@ class TypingTraversal : public Traversal {
}
const int c = dicNode->getOutputWordBuf()[0];
const bool shortCappedWord = dicNode->getDepth()
- < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && isAsciiUpper(c);
+ < ScoringParams::THRESHOLD_SHORT_WORD_LENGTH && CharUtils::isAsciiUpper(c);
return !shortCappedWord
|| probability >= ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY_FOR_CAPPED;
}
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 3938c0ec5..9e0c0d2f7 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -18,8 +18,9 @@
#define LATINIME_TYPING_WEIGHTING_H
#include "defines.h"
-#include "suggest_utils.h"
#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/layout/touch_position_correction_utils.h"
#include "suggest/core/policy/weighting.h"
#include "suggest/core/session/dic_traverse_session.h"
#include "suggest/policyimpl/typing/scoring_params.h"
@@ -74,7 +75,7 @@ class TypingWeighting : public Weighting {
// the keyboard (like accented letters)
const float normalizedSquaredLength = traverseSession->getProximityInfoState(0)
->getPointToKeyLength(pointIndex, dicNode->getNodeCodePoint());
- const float normalizedDistance = SuggestUtils::getSweetSpotFactor(
+ const float normalizedDistance = TouchPositionCorrectionUtils::getSweetSpotFactor(
traverseSession->isTouchPositionCorrectionEnabled(), normalizedSquaredLength);
const float weightedDistance = ScoringParams::DISTANCE_WEIGHT_LENGTH * normalizedDistance;
@@ -98,9 +99,9 @@ class TypingWeighting : public Weighting {
bool isProximityDicNode(const DicTraverseSession *const traverseSession,
const DicNode *const dicNode) const {
const int pointIndex = dicNode->getInputIndex(0);
- const int primaryCodePoint = toBaseLowerCase(
+ const int primaryCodePoint = CharUtils::toBaseLowerCase(
traverseSession->getProximityInfoState(0)->getPrimaryCodePointAt(pointIndex));
- const int dicNodeChar = toBaseLowerCase(dicNode->getNodeCodePoint());
+ const int dicNodeChar = CharUtils::toBaseLowerCase(dicNode->getNodeCodePoint());
return primaryCodePoint != dicNodeChar;
}
diff --git a/native/jni/src/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h b/native/jni/src/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h
index ec1457455..09f986adf 100644
--- a/native/jni/src/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h
+++ b/native/jni/src/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h
@@ -17,7 +17,7 @@
#ifndef LATINIME_DAEMARU_LEVENSHTEIN_EDIT_DISTANCE_POLICY_H
#define LATINIME_DAEMARU_LEVENSHTEIN_EDIT_DISTANCE_POLICY_H
-#include "char_utils.h"
+#include "suggest/core/dictionary/char_utils.h"
#include "suggest/policyimpl/utils/edit_distance_policy.h"
namespace latinime {
@@ -31,8 +31,8 @@ class DamerauLevenshteinEditDistancePolicy : public EditDistancePolicy {
~DamerauLevenshteinEditDistancePolicy() {}
AK_FORCE_INLINE float getSubstitutionCost(const int index0, const int index1) const {
- const int c0 = toBaseLowerCase(mString0[index0]);
- const int c1 = toBaseLowerCase(mString1[index1]);
+ const int c0 = CharUtils::toBaseLowerCase(mString0[index0]);
+ const int c1 = CharUtils::toBaseLowerCase(mString1[index1]);
return (c0 == c1) ? 0.0f : 1.0f;
}
@@ -45,10 +45,10 @@ class DamerauLevenshteinEditDistancePolicy : public EditDistancePolicy {
}
AK_FORCE_INLINE bool allowTransposition(const int index0, const int index1) const {
- const int c0 = toBaseLowerCase(mString0[index0]);
- const int c1 = toBaseLowerCase(mString1[index1]);
- if (index0 > 0 && index1 > 0 && c0 == toBaseLowerCase(mString1[index1 - 1])
- && c1 == toBaseLowerCase(mString0[index0 - 1])) {
+ const int c0 = CharUtils::toBaseLowerCase(mString0[index0]);
+ const int c1 = CharUtils::toBaseLowerCase(mString1[index1]);
+ if (index0 > 0 && index1 > 0 && c0 == CharUtils::toBaseLowerCase(mString1[index1 - 1])
+ && c1 == CharUtils::toBaseLowerCase(mString0[index0 - 1])) {
return true;
}
return false;
diff --git a/native/jni/src/suggest_options.h b/native/jni/src/suggest_options.h
index 1bed47c93..1b21aafcf 100644
--- a/native/jni/src/suggest_options.h
+++ b/native/jni/src/suggest_options.h
@@ -23,6 +23,9 @@ namespace latinime {
class SuggestOptions{
public:
+ SuggestOptions(const int *const options, const int length)
+ : mOptions(options), mLength(length) {}
+
AK_FORCE_INLINE bool isGesture() const {
return getBoolOption(IS_GESTURE);
}
@@ -31,14 +34,20 @@ class SuggestOptions{
return getBoolOption(USE_FULL_EDIT_DISTANCE);
}
- SuggestOptions(const int *const options, const int length)
- : mOptions(options), mLength(length) {}
+ AK_FORCE_INLINE bool getAdditionalFeaturesBoolOption(const int key) const {
+ return getBoolOption(key + ADDITIONAL_FEATURES_OPTIONS);
+ }
private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestOptions);
+
// Need to update com.android.inputmethod.latin.NativeSuggestOptions when you add, remove or
// reorder options.
static const int IS_GESTURE = 0;
static const int USE_FULL_EDIT_DISTANCE = 1;
+ // Additional features options are stored after the other options and used as setting values of
+ // experimental features.
+ static const int ADDITIONAL_FEATURES_OPTIONS = 2;
const int *const mOptions;
const int mLength;
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index a672294b5..66a8b8542 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -18,13 +18,13 @@
#define LOG_TAG "LatinIME: unigram_dictionary.cpp"
-#include "binary_format.h"
-#include "char_utils.h"
#include "defines.h"
-#include "dictionary.h"
-#include "digraph_utils.h"
-#include "proximity_info.h"
-#include "terminal_attributes.h"
+#include "suggest/core/dictionary/binary_format.h"
+#include "suggest/core/dictionary/char_utils.h"
+#include "suggest/core/dictionary/dictionary.h"
+#include "suggest/core/dictionary/digraph_utils.h"
+#include "suggest/core/dictionary/terminal_attributes.h"
+#include "suggest/core/layout/proximity_info.h"
#include "unigram_dictionary.h"
#include "words_priority_queue.h"
#include "words_priority_queue_pool.h"
@@ -696,8 +696,8 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags,
const bool hasMultipleChars = (0 != (BinaryFormat::FLAG_HAS_MULTIPLE_CHARS & flags));
int pos = startPos;
int codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos);
- int baseChar = toBaseLowerCase(codePoint);
- const int wChar = toBaseLowerCase(inWord[startInputIndex]);
+ int baseChar = CharUtils::toBaseLowerCase(codePoint);
+ const int wChar = CharUtils::toBaseLowerCase(inWord[startInputIndex]);
if (baseChar != wChar) {
*outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos;
@@ -709,8 +709,9 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags,
if (hasMultipleChars) {
codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos);
while (NOT_A_CODE_POINT != codePoint) {
- baseChar = toBaseLowerCase(codePoint);
- if (inputIndex + 1 >= inputSize || toBaseLowerCase(inWord[++inputIndex]) != baseChar) {
+ baseChar = CharUtils::toBaseLowerCase(codePoint);
+ if (inputIndex + 1 >= inputSize
+ || CharUtils::toBaseLowerCase(inWord[++inputIndex]) != baseChar) {
*outPos = BinaryFormat::skipOtherCharacters(root, pos);
*outInputIndex = startInputIndex;
return false;
diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h
index a64a539bd..a50503256 100644
--- a/native/jni/src/unigram_dictionary.h
+++ b/native/jni/src/unigram_dictionary.h
@@ -19,8 +19,9 @@
#include <map>
#include <stdint.h>
+
#include "defines.h"
-#include "digraph_utils.h"
+#include "suggest/core/dictionary/digraph_utils.h"
namespace latinime {