aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java8
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java29
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java11
-rw-r--r--java/src/com/android/inputmethod/research/BootBroadcastReceiver.java5
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java34
-rw-r--r--java/src/com/android/inputmethod/research/UploaderService.java46
-rw-r--r--native/jni/src/proximity_info.cpp4
-rw-r--r--native/jni/src/proximity_info.h3
-rw-r--r--native/jni/src/proximity_info_params.cpp3
-rw-r--r--native/jni/src/proximity_info_params.h1
-rw-r--r--native/jni/src/proximity_info_state.cpp16
-rw-r--r--native/jni/src/proximity_info_state_utils.cpp31
-rw-r--r--native/jni/src/proximity_info_state_utils.h8
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h7
-rw-r--r--native/jni/src/suggest/core/suggest.cpp1
-rw-r--r--native/jni/src/suggest/core/suggest.h9
-rw-r--r--tests/src/com/android/inputmethod/latin/InputTestsBase.java4
-rw-r--r--tests/src/com/android/inputmethod/latin/StringUtilsTests.java46
18 files changed, 183 insertions, 83 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 0fc26a80e..56b1c786e 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -72,6 +72,7 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.MainKeyboardView;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.Utils.Stats;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
@@ -1905,7 +1906,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private boolean handleSeparator(final int primaryCode, final int x, final int y,
final int spaceState) {
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.recordTimeForLogUnitSplit();
ResearchLogger.latinIME_handleSeparator(primaryCode, mWordComposer.isComposingWord());
}
boolean didAutoCorrect = false;
@@ -2174,8 +2174,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
// interface
@Override
- public void pickSuggestionManually(final int index, final String suggestion) {
+ public void pickSuggestionManually(final int index, final SuggestedWordInfo suggestionInfo) {
final SuggestedWords suggestedWords = mSuggestedWords;
+ final String suggestion = suggestionInfo.mWord;
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
if (suggestion.length() == 1 && isShowingPunctuationList()) {
// Word separators are suggested before the user inputs something.
@@ -2241,7 +2242,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// AND it's in none of our current dictionaries (main, user or otherwise).
// Please note that if mSuggest is null, it means that everything is off: suggestion
// and correction, so we shouldn't try to show the hint
- final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null
+ final boolean showingAddToDictionaryHint =
+ SuggestedWordInfo.KIND_TYPED == suggestionInfo.mKind && mSuggest != null
// If the suggestion is not in the dictionary, the hint should be shown.
&& !AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), suggestion, true);
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index dcb514a5e..59ad28fc9 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -115,11 +115,12 @@ public final class StringUtils {
// - This does not work for Greek, because it returns upper case instead of title case.
// - It does not work for Serbian, because it fails to account for the "lj" character,
// which should be "Lj" in title case and "LJ" in upper case.
- // - It does not work for Dutch, because it fails to account for the "ij" digraph, which
- // are two different characters but both should be capitalized as "IJ" as if they were
- // a single letter.
- // - It also does not work with unicode surrogate code points.
- return s.toUpperCase(locale).charAt(0) + s.substring(1);
+ // - It does not work for Dutch, because it fails to account for the "ij" digraph when it's
+ // written as two separate code points. They are two different characters but both should
+ // be capitalized as "IJ" as if they were a single letter in most words (not all). If the
+ // unicode char for the ligature is used however, it works.
+ final int cutoff = s.offsetByCodePoints(0, 1);
+ return s.substring(0, cutoff).toUpperCase(locale) + s.substring(cutoff).toLowerCase(locale);
}
private static final int[] EMPTY_CODEPOINTS = {};
@@ -176,17 +177,27 @@ public final class StringUtils {
return list.toArray(new String[list.size()]);
}
- // This method assumes the text is not empty or null.
+ // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
public static int getCapitalizationType(final String text) {
// If the first char is not uppercase, then the word is either all lower case or
// camel case, and in either case we return CAPITALIZE_NONE.
- if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
final int len = text.length();
+ int index = 0;
+ for (; index < len; index = text.offsetByCodePoints(index, 1)) {
+ if (Character.isLetter(text.codePointAt(index))) {
+ break;
+ }
+ }
+ if (index == len) return CAPITALIZE_NONE;
+ if (!Character.isUpperCase(text.codePointAt(index))) {
+ return CAPITALIZE_NONE;
+ }
int capsCount = 1;
int letterCount = 1;
- for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
+ for (index = text.offsetByCodePoints(index, 1); index < len;
+ index = text.offsetByCodePoints(index, 1)) {
if (1 != capsCount && letterCount != capsCount) break;
- final int codePoint = text.codePointAt(i);
+ final int codePoint = text.codePointAt(index);
if (Character.isUpperCase(codePoint)) {
++capsCount;
++letterCount;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 8c3d3b08c..eeaf828a7 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -62,6 +62,7 @@ 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.research.ResearchLogger;
@@ -72,7 +73,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
OnLongClickListener {
public interface Listener {
public void addWordToUserDictionary(String word);
- public void pickSuggestionManually(int index, String word);
+ public void pickSuggestionManually(int index, SuggestedWordInfo word);
}
// The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}.
@@ -656,8 +657,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
@Override
public boolean onCustomRequest(final int requestCode) {
final int index = requestCode;
- final String word = mSuggestedWords.getWord(index);
- mListener.pickSuggestionManually(index, word);
+ final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
+ mListener.pickSuggestionManually(index, wordInfo);
dismissMoreSuggestions();
return true;
}
@@ -807,8 +808,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
if (index >= mSuggestedWords.size())
return;
- final String word = mSuggestedWords.getWord(index);
- mListener.pickSuggestionManually(index, word);
+ final SuggestedWordInfo wordInfo = mSuggestedWords.getInfo(index);
+ mListener.pickSuggestionManually(index, wordInfo);
}
@Override
diff --git a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java b/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
index c5f095919..4f86526a7 100644
--- a/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/research/BootBroadcastReceiver.java
@@ -25,9 +25,10 @@ import android.content.Intent;
*/
public final class BootBroadcastReceiver extends BroadcastReceiver {
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
- ResearchLogger.scheduleUploadingService(context);
+ UploaderService.cancelAndRescheduleUploadingService(context,
+ true /* needsRescheduling */);
}
}
}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index fbfa9c977..e0bd37c1e 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -20,16 +20,13 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
@@ -74,22 +71,16 @@ import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.research.MotionEventReader.ReplayData;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
-import java.util.Locale;
import java.util.Random;
-import java.util.UUID;
/**
* Logs the use of the LatinIME keyboard.
@@ -254,7 +245,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- scheduleUploadingService(mLatinIME);
+ UploaderService.cancelAndRescheduleUploadingService(mLatinIME,
+ true /* needsRescheduling */);
}
mReplayer.setKeyboardSwitcher(keyboardSwitcher);
}
@@ -268,25 +260,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
ResearchSettings.writeResearchLastDirCleanupTime(mPrefs, now);
}
- /**
- * Arrange for the UploaderService to be run on a regular basis.
- *
- * Any existing scheduled invocation of UploaderService is removed and rescheduled. This may
- * cause problems if this method is called often and frequent updates are required, but since
- * the user will likely be sleeping at some point, if the interval is less that the expected
- * sleep duration and this method is not called during that time, the service should be invoked
- * at some point.
- */
- public static void scheduleUploadingService(Context context) {
- final Intent intent = new Intent(context, UploaderService.class);
- final PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
- final AlarmManager manager =
- (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- manager.cancel(pendingIntent);
- manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- UploaderService.RUN_INTERVAL, UploaderService.RUN_INTERVAL, pendingIntent);
- }
-
public void mainKeyboardView_onAttachedToWindow(final MainKeyboardView mainKeyboardView) {
mMainKeyboardView = mainKeyboardView;
maybeShowSplashScreen();
@@ -790,8 +763,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
private boolean isAllowedToLog() {
- return !mIsPasswordView && !mIsLoggingSuspended && sIsLogging && !mInFeedbackDialog
- && !isReplaying();
+ return !mIsPasswordView && !mIsLoggingSuspended && sIsLogging && !mInFeedbackDialog;
}
public void requestIndicatorRedraw() {
diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java
index 6a9f5c1f4..6a9717b7c 100644
--- a/java/src/com/android/inputmethod/research/UploaderService.java
+++ b/java/src/com/android/inputmethod/research/UploaderService.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.research;
import android.app.AlarmManager;
import android.app.IntentService;
+import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -43,11 +45,17 @@ public final class UploaderService extends IntentService {
@Override
protected void onHandleIntent(final Intent intent) {
+ // We may reach this point either because the alarm fired, or because the system explicitly
+ // requested that an Upload occur. In the latter case, we want to cancel the alarm in case
+ // it's about to fire.
+ cancelAndRescheduleUploadingService(this, false /* needsRescheduling */);
+
final Uploader uploader = new Uploader(this);
if (!uploader.isPossibleToUpload()) return;
if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) {
uploader.doUpload();
}
+ cancelAndRescheduleUploadingService(this, true /* needsRescheduling */);
}
private boolean isUploadingUnconditionally(final Bundle bundle) {
@@ -57,4 +65,42 @@ public final class UploaderService extends IntentService {
}
return false;
}
+
+ /**
+ * Arrange for the UploaderService to be run on a regular basis.
+ *
+ * Any existing scheduled invocation of UploaderService is removed and optionally rescheduled.
+ * This may cause problems if this method is called so often that no scheduled invocation is
+ * ever run. But if the delay is short enough that it will go off when the user is sleeping,
+ * then there should be no starvation.
+ *
+ * @param context {@link Context} object
+ * @param needsRescheduling whether to schedule a future intent to be delivered to this service
+ */
+ public static void cancelAndRescheduleUploadingService(final Context context,
+ final boolean needsRescheduling) {
+ final PendingIntent pendingIntent = getPendingIntentForService(context);
+ final AlarmManager alarmManager = (AlarmManager) context.getSystemService(
+ Context.ALARM_SERVICE);
+ cancelAnyScheduledServiceAlarm(alarmManager, pendingIntent);
+ if (needsRescheduling) {
+ scheduleServiceAlarm(alarmManager, pendingIntent);
+ }
+ }
+
+ private static PendingIntent getPendingIntentForService(final Context context) {
+ final Intent intent = new Intent(context, UploaderService.class);
+ return PendingIntent.getService(context, 0, intent, 0);
+ }
+
+ private static void cancelAnyScheduledServiceAlarm(final AlarmManager alarmManager,
+ final PendingIntent pendingIntent) {
+ alarmManager.cancel(pendingIntent);
+ }
+
+ private static void scheduleServiceAlarm(final AlarmManager alarmManager,
+ final PendingIntent pendingIntent) {
+ alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, UploaderService.RUN_INTERVAL,
+ pendingIntent);
+ }
}
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 74b5e0131..50f38e82e 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -129,7 +129,7 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
}
float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
- const int keyId, const int x, const int y) const {
+ const int keyId, const int x, const int y, const float verticalScale) const {
const bool correctTouchPosition = hasTouchPositionCorrectionData();
const float centerX = static_cast<float>(correctTouchPosition ? getSweetSpotCenterXAt(keyId)
: getKeyCenterXOfKeyIdG(keyId));
@@ -138,7 +138,7 @@ float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
if (correctTouchPosition) {
const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
const float gapY = sweetSpotCenterY - visualKeyCenterY;
- centerY = visualKeyCenterY + gapY * ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G;
+ centerY = visualKeyCenterY + gapY * verticalScale;
} else {
centerY = visualKeyCenterY;
}
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index 57a175d2c..e21262fdb 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -39,7 +39,8 @@ class ProximityInfo {
bool hasSpaceProximity(const int x, const int y) const;
int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
float getNormalizedSquaredDistanceFromCenterFloatG(
- const int keyId, const int x, const int y) const;
+ const int keyId, const int x, const int y,
+ const float verticalScale) const;
bool sameAsTyped(const unsigned short *word, int length) const;
int getCodePointOf(const int keyIndex) const;
bool hasSweetSpotData(const int keyIndex) const {
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/proximity_info_params.cpp
index f9a4352ee..2675d9e70 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/proximity_info_params.cpp
@@ -20,7 +20,8 @@
namespace latinime {
const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
const int ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5;
-const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G = 1.1f;
+const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE = 1.0f;
+const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G = 0.5f;
/* Per method constants */
// Used by ProximityInfoStateUtils::initGeometricDistanceInfos()
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/proximity_info_params.h
index e7aec0976..4e47f7308 100644
--- a/native/jni/src/proximity_info_params.h
+++ b/native/jni/src/proximity_info_params.h
@@ -25,6 +25,7 @@ class ProximityInfoParams {
public:
static const float NOT_A_DISTANCE_FLOAT;
static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE;
+ static const float VERTICAL_SWEET_SPOT_SCALE;
static const float VERTICAL_SWEET_SPOT_SCALE_G;
// Used by ProximityInfoStateUtils::initGeometricDistanceInfos()
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 861ba9971..a10b260e1 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -28,6 +28,7 @@
namespace latinime {
+// TODO: Remove the dependency of "isGeometric"
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
const int *const xCoordinates, const int *const yCoordinates, const int *const times,
@@ -94,12 +95,17 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
pushTouchPointStartIndex, lastSavedInputSize);
}
+ // TODO: Remove the dependency of "isGeometric"
+ const float verticalSweetSpotScale = isGeometric
+ ? ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G
+ : ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE;
+
if (xCoordinates && yCoordinates) {
mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(mProximityInfo,
mMaxPointToKeyLength, mInputProximities, xCoordinates, yCoordinates, times,
- pointerIds, inputSize, isGeometric, pointerId, pushTouchPointStartIndex,
- &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
- &mSampledInputIndice);
+ pointerIds, verticalSweetSpotScale, inputSize, isGeometric, pointerId,
+ pushTouchPointStartIndex, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
+ &mSampledLengthCache, &mSampledInputIndice);
}
if (mSampledInputSize > 0 && isGeometric) {
@@ -115,8 +121,8 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
if (mSampledInputSize > 0) {
ProximityInfoStateUtils::initGeometricDistanceInfos(mProximityInfo, mSampledInputSize,
- lastSavedInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledNearKeySets,
- &mSampledDistanceCache_G);
+ lastSavedInputSize, verticalSweetSpotScale, &mSampledInputXs, &mSampledInputYs,
+ &mSampledNearKeySets, &mSampledDistanceCache_G);
if (isGeometric) {
// updates probabilities of skipping or mapping each key for all points.
ProximityInfoStateUtils::updateAlignPointProbabilities(
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index 760508076..df70cffdf 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -42,8 +42,8 @@ namespace latinime {
const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
const int *const inputProximities, const int *const inputXCoordinates,
const int *const inputYCoordinates, const int *const times, const int *const pointerIds,
- const int inputSize, const bool isGeometric, const int pointerId,
- const int pushTouchPointStartIndex, std::vector<int> *sampledInputXs,
+ const float verticalSweetSpotScale, const int inputSize, const bool isGeometric,
+ const int pointerId, const int pushTouchPointStartIndex, std::vector<int> *sampledInputXs,
std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) {
if (DEBUG_SAMPLING_POINTS) {
@@ -112,10 +112,10 @@ namespace latinime {
}
if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time,
- isGeometric /* doSampling */, i == lastInputIndex, sumAngle,
- currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances,
- sampledInputXs, sampledInputYs, sampledInputTimes, sampledLengthCache,
- sampledInputIndice)) {
+ verticalSweetSpotScale, isGeometric /* doSampling */, i == lastInputIndex,
+ sumAngle, currentNearKeysDistances, prevNearKeysDistances,
+ prevPrevNearKeysDistances, sampledInputXs, sampledInputYs, sampledInputTimes,
+ sampledLengthCache, sampledInputIndice)) {
// Previous point information was popped.
NearKeysDistanceMap *tmp = prevNearKeysDistances;
prevNearKeysDistances = currentNearKeysDistances;
@@ -222,7 +222,8 @@ namespace latinime {
/* static */ void ProximityInfoStateUtils::initGeometricDistanceInfos(
const ProximityInfo *const proximityInfo, const int sampledInputSize,
- const int lastSavedInputSize, const std::vector<int> *const sampledInputXs,
+ const int lastSavedInputSize, const float verticalSweetSpotScale,
+ const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
std::vector<NearKeycodesSet> *SampledNearKeySets,
std::vector<float> *SampledDistanceCache_G) {
@@ -236,7 +237,8 @@ namespace latinime {
const int x = (*sampledInputXs)[i];
const int y = (*sampledInputYs)[i];
const float normalizedSquaredDistance =
- proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
+ proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(
+ k, x, y, verticalSweetSpotScale);
(*SampledDistanceCache_G)[index] = normalizedSquaredDistance;
if (normalizedSquaredDistance
< ProximityInfoParams::NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) {
@@ -354,12 +356,14 @@ namespace latinime {
// the given point and the nearest key position.
/* static */ float ProximityInfoStateUtils::updateNearKeysDistances(
const ProximityInfo *const proximityInfo, const float maxPointToKeyLength, const int x,
- const int y, NearKeysDistanceMap *const currentNearKeysDistances) {
+ const int y, const float verticalSweetspotScale,
+ NearKeysDistanceMap *const currentNearKeysDistances) {
currentNearKeysDistances->clear();
const int keyCount = proximityInfo->getKeyCount();
float nearestKeyDistance = maxPointToKeyLength;
for (int k = 0; k < keyCount; ++k) {
- const float dist = proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
+ const float dist = proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y,
+ verticalSweetspotScale);
if (dist < ProximityInfoParams::NEAR_KEY_THRESHOLD_FOR_DISTANCE) {
currentNearKeysDistances->insert(std::pair<int, float>(k, dist));
}
@@ -439,7 +443,8 @@ namespace latinime {
// Returning if previous point is popped or not.
/* static */ bool ProximityInfoStateUtils::pushTouchPoint(const ProximityInfo *const proximityInfo,
const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x, int y,
- const int time, const bool doSampling, const bool isLastPoint, const float sumAngle,
+ const int time, const float verticalSweetSpotScale, const bool doSampling,
+ const bool isLastPoint, const float sumAngle,
NearKeysDistanceMap *const currentNearKeysDistances,
const NearKeysDistanceMap *const prevNearKeysDistances,
const NearKeysDistanceMap *const prevPrevNearKeysDistances,
@@ -451,8 +456,8 @@ namespace latinime {
size_t size = sampledInputXs->size();
bool popped = false;
if (nodeCodePoint < 0 && doSampling) {
- const float nearest = updateNearKeysDistances(
- proximityInfo, maxPointToKeyLength, x, y, currentNearKeysDistances);
+ const float nearest = updateNearKeysDistances(proximityInfo, maxPointToKeyLength, x, y,
+ verticalSweetSpotScale, currentNearKeysDistances);
const float score = getPointScore(mostCommonKeyWidth, x, y, time, isLastPoint, nearest,
sumAngle, currentNearKeysDistances, prevNearKeysDistances,
prevPrevNearKeysDistances, sampledInputXs, sampledInputYs);
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/proximity_info_state_utils.h
index 3ceb25d8b..c9feb59a3 100644
--- a/native/jni/src/proximity_info_state_utils.h
+++ b/native/jni/src/proximity_info_state_utils.h
@@ -38,7 +38,8 @@ class ProximityInfoStateUtils {
static int updateTouchPoints(const ProximityInfo *const proximityInfo,
const int maxPointToKeyLength, const int *const inputProximities,
const int *const inputXCoordinates, const int *const inputYCoordinates,
- const int *const times, const int *const pointerIds, const int inputSize,
+ const int *const times, const int *const pointerIds,
+ const float verticalSweetSpotScale, const int inputSize,
const bool isGeometric, const int pointerId, const int pushTouchPointStartIndex,
std::vector<int> *sampledInputXs, std::vector<int> *sampledInputYs,
std::vector<int> *sampledInputTimes, std::vector<int> *sampledLengthCache,
@@ -84,6 +85,7 @@ class ProximityInfoStateUtils {
const int inputIndex, const int keyId);
static void initGeometricDistanceInfos(const ProximityInfo *const proximityInfo,
const int sampledInputSize, const int lastSavedInputSize,
+ const float verticalSweetSpotScale,
const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
std::vector<NearKeycodesSet> *SampledNearKeySets,
@@ -118,6 +120,7 @@ class ProximityInfoStateUtils {
static float updateNearKeysDistances(const ProximityInfo *const proximityInfo,
const float maxPointToKeyLength, const int x, const int y,
+ const float verticalSweetSpotScale,
NearKeysDistanceMap *const currentNearKeysDistances);
static bool isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
const NearKeysDistanceMap *const prevNearKeysDistances,
@@ -130,7 +133,8 @@ class ProximityInfoStateUtils {
std::vector<int> *sampledInputXs, std::vector<int> *sampledInputYs);
static bool pushTouchPoint(const ProximityInfo *const proximityInfo,
const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x,
- int y, const int time, const bool doSampling, const bool isLastPoint,
+ int y, const int time, const float verticalSweetSpotScale,
+ const bool doSampling, const bool isLastPoint,
const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances,
const NearKeysDistanceMap *const prevNearKeysDistances,
const NearKeysDistanceMap *const prevPrevNearKeysDistances,
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 7bfa459a2..cde7b99a7 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -48,13 +48,6 @@
namespace latinime {
-// Naming convention
-// - Distance: "Weighted" edit distance -- used both for spatial and language.
-// - Compound Distance: Spatial Distance + Language Distance -- used for pruning and scoring
-// - Cost: delta/diff for Distance -- used both for spatial and language
-// - Length: "Non-weighted" -- used only for spatial
-// - Probability: "Non-weighted" -- used only for language
-
// This struct is purely a bucket to return values. No instances of this struct should be kept.
struct DicNode_InputStateG {
bool mNeedsToUpdateInputStateG;
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index 1e97a9176..764c37240 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -426,7 +426,6 @@ void Suggest::processDicNodeAsOmission(
weightChildNode(traverseSession, childDicNode);
if (!TRAVERSAL->isPossibleOmissionChildNode(traverseSession, dicNode, childDicNode)) {
- DicNode::managedDelete(childDicNode);
continue;
}
processExpandedDicNode(traverseSession, childDicNode);
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
index a1e7e7a94..6c09b9467 100644
--- a/native/jni/src/suggest/core/suggest.h
+++ b/native/jni/src/suggest/core/suggest.h
@@ -23,6 +23,15 @@
namespace latinime {
+// Naming convention
+// - Distance: "Weighted" edit distance -- used both for spatial and language.
+// - Compound Distance: Spatial Distance + Language Distance -- used for pruning and scoring
+// - Cost: delta/diff for Distance -- used both for spatial and language
+// - Length: "Non-weighted" -- used only for spatial
+// - Probability: "Non-weighted" -- used only for language
+// - Score: Final calibrated score based on the compound distance, which is sent to java as the
+// priority of a suggested word
+
class DicNode;
class DicTraverseSession;
class ProximityInfo;
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 04e1f932a..4583eab2f 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -36,6 +36,7 @@ import android.widget.TextView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.util.Locale;
@@ -255,7 +256,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIME> {
}
protected void pickSuggestionManually(final int index, final String suggestion) {
- mLatinIME.pickSuggestionManually(index, suggestion);
+ mLatinIME.pickSuggestionManually(index, new SuggestedWordInfo(suggestion, 1,
+ SuggestedWordInfo.KIND_CORRECTION, "main"));
}
// Helper to avoid writing the try{}catch block each time
diff --git a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
index 923ab2ecc..966919ed3 100644
--- a/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/StringUtilsTests.java
@@ -19,6 +19,8 @@ package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Locale;
+
@SmallTest
public class StringUtilsTests extends AndroidTestCase {
public void testContainsInArray() {
@@ -90,4 +92,48 @@ public class StringUtilsTests extends AndroidTestCase {
assertEquals("in 5 elements at position 2,4", "key1,key3,key5",
StringUtils.removeFromCsvIfExists("key", "key1,key,key3,key,key5"));
}
+
+ public void testToTitleCase() {
+ assertEquals("SSaa",
+ StringUtils.toTitleCase("ßaa", Locale.GERMAN));
+ assertEquals("Aßa",
+ StringUtils.toTitleCase("aßa", Locale.GERMAN));
+ assertEquals("Iab",
+ StringUtils.toTitleCase("iab", Locale.ENGLISH));
+ assertEquals("Camelcase",
+ StringUtils.toTitleCase("cAmElCaSe", Locale.ENGLISH));
+ assertEquals("İab",
+ StringUtils.toTitleCase("iab", new Locale("tr")));
+ assertEquals("Aib",
+ StringUtils.toTitleCase("AİB", new Locale("tr")));
+ // For one character, toTitleCase returns the string as is. Not sure what the motivation
+ // is, but that's how it works now.
+ assertEquals("a",
+ StringUtils.toTitleCase("a", Locale.ENGLISH));
+ assertEquals("A",
+ StringUtils.toTitleCase("A", Locale.ENGLISH));
+ }
+
+ public void testGetCapitalizationType() {
+ assertEquals(StringUtils.CAPITALIZE_NONE,
+ StringUtils.getCapitalizationType("capitalize"));
+ assertEquals(StringUtils.CAPITALIZE_NONE,
+ StringUtils.getCapitalizationType("cApITalize"));
+ assertEquals(StringUtils.CAPITALIZE_NONE,
+ StringUtils.getCapitalizationType("capitalizE"));
+ assertEquals(StringUtils.CAPITALIZE_NONE,
+ StringUtils.getCapitalizationType("__c a piu$@tali56ze"));
+ assertEquals(StringUtils.CAPITALIZE_FIRST,
+ StringUtils.getCapitalizationType("A__c a piu$@tali56ze"));
+ assertEquals(StringUtils.CAPITALIZE_FIRST,
+ StringUtils.getCapitalizationType("Capitalize"));
+ assertEquals(StringUtils.CAPITALIZE_FIRST,
+ StringUtils.getCapitalizationType(" Capitalize"));
+ assertEquals(StringUtils.CAPITALIZE_ALL,
+ StringUtils.getCapitalizationType("CAPITALIZE"));
+ assertEquals(StringUtils.CAPITALIZE_ALL,
+ StringUtils.getCapitalizationType(" PI26LIE"));
+ assertEquals(StringUtils.CAPITALIZE_NONE,
+ StringUtils.getCapitalizationType(""));
+ }
}