diff options
23 files changed, 192 insertions, 150 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 97d88af4a..c0e6aa8d7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -59,6 +59,9 @@ public class KeyDetector { } public Keyboard getKeyboard() { + if (mKeyboard == null) { + throw new IllegalStateException("keyboard isn't set"); + } return mKeyboard; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 0e6de7032..fcf97b99c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -108,14 +108,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private int mDelayAfterPreview; private final PreviewPlacerView mPreviewPlacerView; - /** True if {@link KeyboardView} should handle gesture events. */ - protected boolean mShouldHandleGesture; - // Drawing /** True if the entire keyboard needs to be dimmed. */ private boolean mNeedsToDimEntireKeyboard; - /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/ - private boolean mBufferNeedsUpdate; /** True if all keys should be drawn */ private boolean mInvalidateAllKeys; /** The keys that should be drawn */ @@ -438,9 +433,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { return mShowKeyPreviewPopup; } - public void setGestureHandlingMode(boolean shouldHandleGesture, - boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) { - mShouldHandleGesture = shouldHandleGesture; + public void setGesturePreviewMode(boolean drawsGesturePreviewTrail, + boolean drawsGestureFloatingPreviewText) { mPreviewPlacerView.setGesturePreviewMode( drawsGesturePreviewTrail, drawsGestureFloatingPreviewText); } @@ -463,8 +457,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { onDrawKeyboard(canvas); return; } - if (mBufferNeedsUpdate || mOffscreenBuffer == null) { - mBufferNeedsUpdate = false; + + final boolean bufferNeedsUpdates = mInvalidateAllKeys || !mInvalidatedKeys.isEmpty(); + if (bufferNeedsUpdates || mOffscreenBuffer == null) { if (maybeAllocateOffscreenBuffer()) { mInvalidateAllKeys = true; // TODO: Stop using the offscreen canvas even when in software rendering @@ -528,13 +523,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } if (!isHardwareAccelerated) { canvas.clipRegion(mClipRegion, Region.Op.REPLACE); - } - - // Draw keyboard background. - canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); - final Drawable background = getBackground(); - if (background != null) { - background.draw(canvas); + // Draw keyboard background. + canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); + final Drawable background = getBackground(); + if (background != null) { + background.draw(canvas); + } } // TODO: Confirm if it's really required to draw all keys when hardware acceleration is on. @@ -1052,7 +1046,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public void invalidateAllKeys() { mInvalidatedKeys.clear(); mInvalidateAllKeys = true; - mBufferNeedsUpdate = true; invalidate(); } @@ -1070,9 +1063,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mInvalidatedKeys.add(key); final int x = key.mX + getPaddingLeft(); final int y = key.mY + getPaddingTop(); - mWorkingRect.set(x, y, x + key.mWidth, y + key.mHeight); - mBufferNeedsUpdate = true; - invalidate(mWorkingRect); + invalidate(x, y, x + key.mWidth, y + key.mHeight); } public void closing() { diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index fe9cb9415..4088f3e93 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -482,7 +482,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection); - PointerTracker.setKeyDetector(mKeyDetector, mShouldHandleGesture); + PointerTracker.setKeyDetector(mKeyDetector); mTouchScreenRegulator.setKeyboard(keyboard); mMoreKeysPanelCache.clear(); @@ -500,12 +500,13 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard); } - @Override - public void setGestureHandlingMode(final boolean shouldHandleGesture, - boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) { - super.setGestureHandlingMode(shouldHandleGesture, drawsGesturePreviewTrail, - drawsGestureFloatingPreviewText); - PointerTracker.setKeyDetector(mKeyDetector, shouldHandleGesture); + // Note that this method is called from a non-UI thread. + public void setMainDictionaryAvailability(boolean mainDictionaryAvailable) { + PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable); + } + + public void setGestureHandlingEnabledByUser(boolean gestureHandlingEnabledByUser) { + PointerTracker.setGestureHandlingEnabledByUser(gestureHandlingEnabledByUser); } /** diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java index a183546dd..cd4e3001e 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java @@ -39,11 +39,7 @@ public class MoreKeysDetector extends KeyDetector { Key nearestKey = null; int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; - final Keyboard keyboard = getKeyboard(); - if (keyboard == null) { - throw new NullPointerException("Keyboard isn't set"); - } - for (final Key key : keyboard.mKeys) { + for (final Key key : getKeyboard().mKeys) { final int dist = key.squaredDistanceToEdge(touchX, touchY); if (dist < nearestDist) { nearestKey = key; diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 2b90a3cb9..85360c410 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -29,6 +29,7 @@ import com.android.inputmethod.keyboard.internal.GestureStroke; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.ResearchLogger; @@ -43,6 +44,9 @@ public class PointerTracker implements PointerTrackerQueue.Element { /** True if {@link PointerTracker}s should handle gesture events. */ private static boolean sShouldHandleGesture = false; + private static boolean sMainDictionaryAvailable = false; + private static boolean sGestureHandlingEnabledByInputField = false; + private static boolean sGestureHandlingEnabledByUser = false; private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec @@ -198,7 +202,6 @@ public class PointerTracker implements PointerTrackerQueue.Element { sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack; setParameters(MainKeyboardView.PointerTrackerParams.DEFAULT); - updateGestureHandlingMode(null, false /* shouldHandleGesture */); } public static void setParameters(MainKeyboardView.PointerTrackerParams params) { @@ -207,14 +210,22 @@ public class PointerTracker implements PointerTrackerQueue.Element { params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance); } - private static void updateGestureHandlingMode(Keyboard keyboard, boolean shouldHandleGesture) { - if (!shouldHandleGesture - || AccessibilityUtils.getInstance().isTouchExplorationEnabled() - || (keyboard != null && keyboard.mId.passwordInput())) { - sShouldHandleGesture = false; - } else { - sShouldHandleGesture = true; - } + private static void updateGestureHandlingMode() { + sShouldHandleGesture = sMainDictionaryAvailable + && sGestureHandlingEnabledByInputField + && sGestureHandlingEnabledByUser + && !AccessibilityUtils.getInstance().isTouchExplorationEnabled(); + } + + // Note that this method is called from a non-UI thread. + public static void setMainDictionaryAvailability(boolean mainDictionaryAvailable) { + sMainDictionaryAvailable = mainDictionaryAvailable; + updateGestureHandlingMode(); + } + + public static void setGestureHandlingEnabledByUser(boolean gestureHandlingEnabledByUser) { + sGestureHandlingEnabledByUser = gestureHandlingEnabledByUser; + updateGestureHandlingMode(); } public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { @@ -241,7 +252,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { } } - public static void setKeyDetector(KeyDetector keyDetector, boolean shouldHandleGesture) { + public static void setKeyDetector(KeyDetector keyDetector) { final int trackersSize = sTrackers.size(); for (int i = 0; i < trackersSize; ++i) { final PointerTracker tracker = sTrackers.get(i); @@ -250,7 +261,8 @@ public class PointerTracker implements PointerTrackerQueue.Element { tracker.mKeyboardLayoutHasBeenChanged = true; } final Keyboard keyboard = keyDetector.getKeyboard(); - updateGestureHandlingMode(keyboard, shouldHandleGesture); + sGestureHandlingEnabledByInputField = !keyboard.mId.passwordInput(); + updateGestureHandlingMode(); } public static void dismissAllKeyPreviews() { diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 7e6c53e2f..e0adc9a71 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -90,9 +90,9 @@ public class BinaryDictionary extends Dictionary { private native void closeNative(long dict); private native int getFrequencyNative(long dict, int[] word, int wordLength); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); - private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, - int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize, - int commitPoint, boolean isGesture, + private native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession, + int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, + int[] inputCodes, int codesSize, int commitPoint, boolean isGesture, int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, int[] outputScores, int[] outputIndices, int[] outputTypes); private static native float calcNormalizedScoreNative( @@ -129,7 +129,8 @@ public class BinaryDictionary extends Dictionary { final int codesSize = isGesture ? ips.getPointerSize() : composerSize; // proximityInfo and/or prevWordForBigrams may not be null. final int tmpCount = getSuggestionsNative(mNativeDict, - proximityInfo.getNativeProximityInfo(), ips.getXCoordinates(), + proximityInfo.getNativeProximityInfo(), + mDicTraverseSession.getSession(), ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(), mInputCodes, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray, mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes); diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java index d0c70f3ad..437876e05 100644 --- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java +++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java @@ -22,16 +22,30 @@ public class DicTraverseSession { static { JniUtils.loadNativeLibrary(); } + private native long setDicTraverseSessionNative(String locale); + private native void initDicTraverseSessionNative( + long nativeDicTraverseSession, int[] previousWord, int previwousWordLength); + private native void releaseDicTraverseSessionNative(long nativeDicTraverseSession); private long mNativeDicTraverseSession; public DicTraverseSession(Locale locale) { mNativeDicTraverseSession = createNativeDicTraverseSession( locale != null ? locale.toString() : ""); + initSession(); } - private native long setDicTraverseSessionNative(String locale); - private native void releaseDicTraverseSessionNative(long nativeDicTraverseSession); + public long getSession() { + return mNativeDicTraverseSession; + } + + public void initSession() { + initSession(null, 0); + } + + public void initSession(int[] previousWord, int previousWordLength) { + initDicTraverseSessionNative(mNativeDicTraverseSession, previousWord, previousWordLength); + } private final long createNativeDicTraverseSession(String locale) { return setDicTraverseSessionNative(locale); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 43901bab4..e0dbb8e6e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -433,10 +433,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } + // Note that this method is called from a non-UI thread. @Override public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable) { mIsMainDictionaryAvailable = isMainDictionaryAvailable; - updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability(); + final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); + if (mainKeyboardView != null) { + mainKeyboardView.setMainDictionaryAvailability(isMainDictionaryAvailable); + } } private void initSuggest() { @@ -701,7 +705,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } switcher.loadKeyboard(editorInfo, mCurrentSettings); - updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability(); } setSuggestionStripShownInternal( isSuggestionsStripVisible(), /* needsInputViewShown */ false); @@ -719,8 +722,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.cancelUpdateSuggestionStrip(); mHandler.cancelDoubleSpacesTimer(); + mainKeyboardView.setMainDictionaryAvailability(mIsMainDictionaryAvailable); mainKeyboardView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn, mCurrentSettings.mKeyPreviewPopupDismissDelay); + mainKeyboardView.setGestureHandlingEnabledByUser(mCurrentSettings.mGestureInputEnabled); + mainKeyboardView.setGesturePreviewMode(mCurrentSettings.mGesturePreviewTrailEnabled, + mCurrentSettings.mGestureFloatingPreviewTextEnabled); if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } @@ -2103,7 +2110,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mKeyboardSwitcher.getMainKeyboardView() != null) { // Reload keyboard because the current language has been changed. mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings); - updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability(); } // Since we just changed languages, we should re-evaluate suggestions with whatever word // we are currently composing. If we are not composing anything, we may want to display @@ -2111,17 +2117,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.postUpdateSuggestionStrip(); } - private void updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability() { - final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); - if (mainKeyboardView != null) { - final boolean shouldHandleGesture = mCurrentSettings.mGestureInputEnabled - && mIsMainDictionaryAvailable; - mainKeyboardView.setGestureHandlingMode(shouldHandleGesture, - mCurrentSettings.mGesturePreviewTrailEnabled, - mCurrentSettings.mGestureFloatingPreviewTextEnabled); - } - } - // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to // {@link KeyboardSwitcher}. Called from KeyboardSwitcher public void hapticAndAudioFeedback(final int primaryCode) { diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp index a01ac3780..f9b23f06d 100644 --- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp +++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp @@ -29,18 +29,15 @@ static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object, jint keyCount, jintArray keyXCoordinates, jintArray keyYCoordinates, jintArray keyWidths, jintArray keyHeights, jintArray keyCharCodes, jfloatArray sweetSpotCenterXs, jfloatArray sweetSpotCenterYs, jfloatArray sweetSpotRadii) { - const char *localeCStr = env->GetStringUTFChars(localeJStr, 0); - ProximityInfo *proximityInfo = new ProximityInfo(env, localeCStr, maxProximityCharsSize, + ProximityInfo *proximityInfo = new ProximityInfo(env, localeJStr, maxProximityCharsSize, displayWidth, displayHeight, gridWidth, gridHeight, mostCommonkeyWidth, proximityChars, keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); - env->ReleaseStringUTFChars(localeJStr, localeCStr); return reinterpret_cast<jlong>(proximityInfo); } static void latinime_Keyboard_release(JNIEnv *env, jobject object, jlong proximityInfo) { ProximityInfo *pi = reinterpret_cast<ProximityInfo*>(proximityInfo); - if (!pi) return; delete pi; } diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 776f5f78f..6e2efbec1 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -36,7 +36,7 @@ namespace latinime { class ProximityInfo; -void releaseDictBuf(void *dictBuf, const size_t length, int fd); +static void releaseDictBuf(void *dictBuf, const size_t length, int fd); static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, jstring sourceDir, jlong dictOffset, jlong dictSize, @@ -44,11 +44,14 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, jint maxPredictions) { PROF_OPEN; PROF_START(66); - const char *sourceDirChars = env->GetStringUTFChars(sourceDir, 0); - if (sourceDirChars == 0) { + const jsize sourceDirUtf8Length = env->GetStringUTFLength(sourceDir); + if (sourceDirUtf8Length <= 0) { AKLOGE("DICT: Can't get sourceDir string"); return 0; } + char sourceDirChars[sourceDirUtf8Length + 1]; + env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars); + sourceDirChars[sourceDirUtf8Length] = '\0'; int fd = 0; void *dictBuf = 0; int adjust = 0; @@ -98,8 +101,6 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, return 0; } #endif // USE_MMAP_FOR_DICTIONARY - env->ReleaseStringUTFChars(sourceDir, sourceDirChars); - if (!dictBuf) { AKLOGE("DICT: dictBuf is null"); return 0; @@ -122,14 +123,15 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, } static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, - jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, - jintArray timesArray, jintArray pointerIdArray, jintArray inputArray, jint arraySize, - jint commitPoint, jboolean isGesture, + jlong proximityInfo, jlong dicTraverseSession, jintArray xCoordinatesArray, + jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdArray, + jintArray inputArray, jint arraySize, jint commitPoint, jboolean isGesture, jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray, jintArray frequencyArray, jintArray spaceIndexArray, jintArray outputTypesArray) { - Dictionary *dictionary = (Dictionary*) dict; + Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict); if (!dictionary) return 0; - ProximityInfo *pInfo = (ProximityInfo*)proximityInfo; + ProximityInfo *pInfo = reinterpret_cast<ProximityInfo*>(proximityInfo); + void *traverseSession = reinterpret_cast<void*>(dicTraverseSession); int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0); int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0); int *times = env->GetIntArrayElements(timesArray, 0); @@ -145,10 +147,10 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, int count; if (isGesture || arraySize > 1) { - count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, times, pointerIds, - inputCodes, arraySize, prevWordChars, prevWordLength, commitPoint, isGesture, - useFullEditDistance, (unsigned short*) outputChars, frequencies, spaceIndices, - outputTypes); + count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates, + times, pointerIds, inputCodes, arraySize, prevWordChars, prevWordLength, + commitPoint, isGesture, useFullEditDistance, (unsigned short*) outputChars, + frequencies, spaceIndices, outputTypes); } else { count = dictionary->getBigrams(prevWordChars, prevWordLength, inputCodes, arraySize, (unsigned short*) outputChars, frequencies, outputTypes); @@ -229,7 +231,7 @@ static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jlong d delete dictionary; } -void releaseDictBuf(void *dictBuf, const size_t length, int fd) { +static void releaseDictBuf(void *dictBuf, const size_t length, int fd) { #ifdef USE_MMAP_FOR_DICTIONARY int ret = munmap(dictBuf, length); if (ret != 0) { @@ -247,7 +249,7 @@ void releaseDictBuf(void *dictBuf, const size_t length, int fd) { static JNINativeMethod sMethods[] = { {"openNative", "(Ljava/lang/String;JJIIIII)J", (void*)latinime_BinaryDictionary_open}, {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close}, - {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", + {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", (void*) latinime_BinaryDictionary_getSuggestions}, {"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency}, {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram}, diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp index 8ee0450e4..0f5c39642 100644 --- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp +++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp @@ -23,21 +23,30 @@ namespace latinime { void *(*DicTraverseWrapper::sDicTraverseSessionFactoryMethod)() = 0; void (*DicTraverseWrapper::sDicTraverseSessionReleaseMethod)(void *) = 0; +void (*DicTraverseWrapper::sDicTraverseSessionInitMethod)( + JNIEnv *, void *, const jintArray, const jint) = 0; static jlong latinime_setDicTraverseSession(JNIEnv *env, jobject object, jstring localejStr) { - void *session = DicTraverseWrapper::getDicTraverseSession(); - return reinterpret_cast<jlong>(session); + void *traverseSession = DicTraverseWrapper::getDicTraverseSession(); + return reinterpret_cast<jlong>(traverseSession); } -static void latinime_DicTraverseSession_release(JNIEnv *env, jobject object, jlong session) { - void *pi = reinterpret_cast<void*>(session); - if (!pi) return; - DicTraverseWrapper::releaseDicTraverseSession(pi); +static void latinime_initDicTraverseSession(JNIEnv *env, jlong traverseSession, + jintArray previousWord, jint previousWordLength) { + void *ts = reinterpret_cast<void*>(traverseSession); + DicTraverseWrapper::initDicTraverseSession(env, ts, previousWord, previousWordLength); +} + +static void latinime_DicTraverseSession_release( + JNIEnv *env, jobject object, jlong traverseSession) { + void *ts = reinterpret_cast<void*>(traverseSession); + DicTraverseWrapper::releaseDicTraverseSession(ts); } static JNINativeMethod sMethods[] = { {"setDicTraverseSessionNative", "(Ljava/lang/String;)J", (void*)latinime_setDicTraverseSession}, + {"initDicTraverseSessionNative", "(J[II)V", (void*)latinime_initDicTraverseSession}, {"releaseDicTraverseSessionNative", "(J)V", (void*)latinime_DicTraverseSession_release} }; diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.h b/native/jni/com_android_inputmethod_latin_DicTraverseSession.h index 5238fd0af..a76815d7f 100644 --- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.h +++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.h @@ -31,14 +31,21 @@ class DicTraverseWrapper { } return 0; } - static void releaseDicTraverseSession(void *session) { + static void initDicTraverseSession(JNIEnv *env, void *traverseSession, + const jintArray prevWord, const jint prevWordLength) { + if (sDicTraverseSessionInitMethod) { + sDicTraverseSessionInitMethod(env, traverseSession, prevWord, prevWordLength); + } + } + static void releaseDicTraverseSession(void *traverseSession) { if (sDicTraverseSessionReleaseMethod) { - sDicTraverseSessionReleaseMethod(session); + sDicTraverseSessionReleaseMethod(traverseSession); } } private: DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseWrapper); static void *(*sDicTraverseSessionFactoryMethod)(); + static void (*sDicTraverseSessionInitMethod)(JNIEnv *, void *, const jintArray, const jint); static void (*sDicTraverseSessionReleaseMethod)(void *); }; int register_DicTraverseSession(JNIEnv *env); diff --git a/native/jni/src/additional_proximity_chars.cpp b/native/jni/src/additional_proximity_chars.cpp index de8764678..f59492741 100644 --- a/native/jni/src/additional_proximity_chars.cpp +++ b/native/jni/src/additional_proximity_chars.cpp @@ -17,7 +17,9 @@ #include "additional_proximity_chars.h" namespace latinime { -const std::string AdditionalProximityChars::LOCALE_EN_US("en"); +// TODO: Stop using hardcoded additional proximity characters. +// TODO: Have proximity character informations in each language's binary dictionary. +const char *AdditionalProximityChars::LOCALE_EN_US = "en"; const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = { 'e', 'i', 'o', 'u' diff --git a/native/jni/src/additional_proximity_chars.h b/native/jni/src/additional_proximity_chars.h index ba76cfced..1fe996d0d 100644 --- a/native/jni/src/additional_proximity_chars.h +++ b/native/jni/src/additional_proximity_chars.h @@ -17,8 +17,8 @@ #ifndef LATINIME_ADDITIONAL_PROXIMITY_CHARS_H #define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H +#include <cstring> #include <stdint.h> -#include <string> #include "defines.h" @@ -27,7 +27,7 @@ namespace latinime { class AdditionalProximityChars { private: DISALLOW_IMPLICIT_CONSTRUCTORS(AdditionalProximityChars); - static const std::string LOCALE_EN_US; + static const char *LOCALE_EN_US; static const int EN_US_ADDITIONAL_A_SIZE = 4; static const int32_t EN_US_ADDITIONAL_A[]; static const int EN_US_ADDITIONAL_E_SIZE = 4; @@ -39,14 +39,15 @@ class AdditionalProximityChars { static const int EN_US_ADDITIONAL_U_SIZE = 4; static const int32_t EN_US_ADDITIONAL_U[]; - static bool isEnLocale(const std::string *locale_str) { - return locale_str && locale_str->size() >= LOCALE_EN_US.size() - && LOCALE_EN_US.compare(0, LOCALE_EN_US.size(), *locale_str); + static bool isEnLocale(const char *localeStr) { + const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US); + return localeStr && strlen(localeStr) >= LOCALE_EN_US_SIZE + && strncmp(localeStr, LOCALE_EN_US, LOCALE_EN_US_SIZE) == 0; } public: - static int getAdditionalCharsSize(const std::string *locale_str, const int32_t c) { - if (!isEnLocale(locale_str)) { + static int getAdditionalCharsSize(const char *localeStr, const int32_t c) { + if (!isEnLocale(localeStr)) { return 0; } switch(c) { @@ -65,8 +66,8 @@ class AdditionalProximityChars { } } - static const int32_t *getAdditionalChars(const std::string *locale_str, const int32_t c) { - if (!isEnLocale(locale_str)) { + static const int32_t *getAdditionalChars(const char *localeStr, const int32_t c) { + if (!isEnLocale(localeStr)) { return 0; } switch(c) { @@ -84,10 +85,6 @@ class AdditionalProximityChars { return 0; } } - - static bool hasAdditionalChars(const std::string *locale_str, const int32_t c) { - return getAdditionalCharsSize(locale_str, c) > 0; - } }; } // namespace latinime #endif // LATINIME_ADDITIONAL_PROXIMITY_CHARS_H diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 31dd61e30..484fc6bde 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -265,6 +265,9 @@ static inline void prof_out(void) { // This must be equal to ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE in KeyDetector.java #define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2 +// Assuming locale strings such as en_US, sr-Latn etc. +#define MAX_LOCALE_STRING_LENGTH 10 + // Word limit for sub queues used in WordsPriorityQueuePool. Sub queues are temporary queues used // for better performance. // Holds up to 1 candidate for each word diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp index ee55cfa60..8c785a263 100644 --- a/native/jni/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -56,16 +56,17 @@ Dictionary::~Dictionary() { delete mGestureDecoder; } -int Dictionary::getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, - int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, +int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, + int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, + int *codes, int codesSize, int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, bool useFullEditDistance, unsigned short *outWords, int *frequencies, int *spaceIndices, int *outputTypes) { int result = 0; if (isGesture) { mGestureDecoder->setPrevWord(prevWordChars, prevWordLength); - result = mGestureDecoder->getSuggestions(proximityInfo, xcoordinates, ycoordinates, - times, pointerIds, codes, codesSize, commitPoint, + result = mGestureDecoder->getSuggestions(proximityInfo, traverseSession, + xcoordinates, ycoordinates, times, pointerIds, codes, codesSize, commitPoint, outWords, frequencies, spaceIndices, outputTypes); if (DEBUG_DICT) { DUMP_RESULT(outWords, frequencies, 18 /* MAX_WORDS */, MAX_WORD_LENGTH_INTERNAL); diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index ab238c824..2c79527be 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -44,9 +44,9 @@ class Dictionary { Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler, int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions); - int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, - int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, - int prevWordLength, int commitPoint, bool isGesture, + int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates, + int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, + int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, bool useFullEditDistance, unsigned short *outWords, int *frequencies, int *spaceIndices, int *outputTypes); diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h index 03c84b5fd..b70c8e0a3 100644 --- a/native/jni/src/gesture/gesture_decoder_wrapper.h +++ b/native/jni/src/gesture/gesture_decoder_wrapper.h @@ -37,15 +37,15 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface { delete mIncrementalDecoderInterface; } - int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times, - int *pointerIds, int *codes, int inputSize, int commitPoint, + int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) { if (!mIncrementalDecoderInterface) { return 0; } return mIncrementalDecoderInterface->getSuggestions( - pInfo, inputXs, inputYs, times, pointerIds, codes, inputSize, commitPoint, - outWords, frequencies, outputIndices, outputTypes); + pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, + inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); } void reset() { diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h index 6d2e273da..e8d3a5333 100644 --- a/native/jni/src/gesture/incremental_decoder_interface.h +++ b/native/jni/src/gesture/incremental_decoder_interface.h @@ -28,9 +28,10 @@ class ProximityInfo; class IncrementalDecoderInterface { public: - virtual int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times, - int *pointerIds, int *codes, int inputSize, int commitPoint, - unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) = 0; + virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession, + int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes, + int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, + int *outputIndices, int *outputTypes) = 0; virtual void reset() = 0; virtual void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram, const uint8_t *dictRoot, int rootPos) = 0; diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.h b/native/jni/src/gesture/incremental_decoder_wrapper.h index 698061548..8d66b4ec1 100644 --- a/native/jni/src/gesture/incremental_decoder_wrapper.h +++ b/native/jni/src/gesture/incremental_decoder_wrapper.h @@ -37,15 +37,15 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface { delete mIncrementalDecoderInterface; } - int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times, - int *pointerIds, int *codes, int inputSize, int commitPoint, + int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) { if (!mIncrementalDecoderInterface) { return 0; } return mIncrementalDecoderInterface->getSuggestions( - pInfo, inputXs, inputYs, times, pointerIds, codes, inputSize, commitPoint, - outWords, frequencies, outputIndices, outputTypes); + pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, + inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); } void reset() { diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index 7bae41362..2564c8a67 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -17,7 +17,6 @@ #include <cassert> #include <cmath> #include <cstring> -#include <string> #define LOG_TAG "LatinIME: proximity_info.cpp" @@ -47,7 +46,7 @@ static inline void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jA } } -ProximityInfo::ProximityInfo(JNIEnv *env, const char *localeCStr, const int maxProximityCharsSize, +ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize, const int keyboardWidth, const int keyboardHeight, const int gridWidth, const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars, const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates, @@ -62,12 +61,18 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const char *localeCStr, const int maxP KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs - && sweetSpotCenterYs && sweetSpotRadii), - mLocaleStr(localeCStr) { + && sweetSpotCenterYs && sweetSpotRadii) { const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; if (DEBUG_PROXIMITY_INFO) { AKLOGI("Create proximity info array %d", proximityGridLength); } + const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr); + if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) { + AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length); + assert(false); + } + memset(mLocaleStr, 0, sizeof(mLocaleStr)); + env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr); mProximityCharsArray = new int32_t[proximityGridLength]; safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityGridLength, mProximityCharsArray); safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates); @@ -166,7 +171,7 @@ void ProximityInfo::calculateNearbyKeyCodes( } } const int additionalProximitySize = - AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey); + AdditionalProximityChars::getAdditionalCharsSize(mLocaleStr, primaryKey); if (additionalProximitySize > 0) { inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { @@ -177,7 +182,7 @@ void ProximityInfo::calculateNearbyKeyCodes( } const int32_t *additionalProximityChars = - AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey); + AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey); for (int j = 0; j < additionalProximitySize; ++j) { const int32_t ac = additionalProximityChars[j]; int k = 0; diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h index 5dd378d21..d7e24c5f5 100644 --- a/native/jni/src/proximity_info.h +++ b/native/jni/src/proximity_info.h @@ -18,7 +18,6 @@ #define LATINIME_PROXIMITY_INFO_H #include <stdint.h> -#include <string> #include "defines.h" #include "jni.h" @@ -29,7 +28,7 @@ class Correction; class ProximityInfo { public: - ProximityInfo(JNIEnv *env, const char *localeCStr, const int maxProximityCharsSize, + ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize, const int keyboardWidth, const int keyboardHeight, const int gridWidth, const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars, const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates, @@ -75,7 +74,7 @@ class ProximityInfo { return MOST_COMMON_KEY_WIDTH_SQUARE; } - std::string getLocaleStr() const { + const char *getLocaleStr() const { return mLocaleStr; } @@ -129,7 +128,7 @@ class ProximityInfo { const int CELL_HEIGHT; const int KEY_COUNT; const bool HAS_TOUCH_POSITION_CORRECTION_DATA; - const std::string mLocaleStr; + char mLocaleStr[MAX_LOCALE_STRING_LENGTH]; int32_t *mProximityCharsArray; int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java index a76ec50e0..3cb0a12c4 100644 --- a/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java +++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java @@ -46,46 +46,52 @@ public class Compress { static public class Compressor extends Dicttool.Command { public static final String COMMAND = "compress"; - private static final String SUFFIX = ".compressed"; + public static final String STDIN_OR_STDOUT = "-"; public Compressor() { } public String getHelp() { - return "compress <filename>: Compresses a file using gzip compression"; + return COMMAND + " <src_filename> <dst_filename>: " + + "Compresses a file using gzip compression"; } public void run() throws IOException { - if (mArgs.length < 1) { - throw new RuntimeException("Not enough arguments for command " + COMMAND); + if (mArgs.length > 2) { + throw new RuntimeException("Too many arguments for command " + COMMAND); } - final String inFilename = mArgs[0]; - final String outFilename = inFilename + SUFFIX; - final FileInputStream input = new FileInputStream(new File(inFilename)); - final FileOutputStream output = new FileOutputStream(new File(outFilename)); + final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT; + final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT; + final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in + : new FileInputStream(new File(inFilename)); + final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out + : new FileOutputStream(new File(outFilename)); copy(input, new GZIPOutputStream(output)); } } static public class Uncompressor extends Dicttool.Command { public static final String COMMAND = "uncompress"; - private static final String SUFFIX = ".uncompressed"; + public static final String STDIN_OR_STDOUT = "-"; public Uncompressor() { } public String getHelp() { - return "uncompress <filename>: Uncompresses a file compressed with gzip compression"; + return COMMAND + " <src_filename> <dst_filename>: " + + "Uncompresses a file compressed with gzip compression"; } public void run() throws IOException { - if (mArgs.length < 1) { - throw new RuntimeException("Not enough arguments for command " + COMMAND); + if (mArgs.length > 2) { + throw new RuntimeException("Too many arguments for command " + COMMAND); } - final String inFilename = mArgs[0]; - final String outFilename = inFilename + SUFFIX; - final FileInputStream input = new FileInputStream(new File(inFilename)); - final FileOutputStream output = new FileOutputStream(new File(outFilename)); + final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT; + final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT; + final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in + : new FileInputStream(new File(inFilename)); + final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out + : new FileOutputStream(new File(outFilename)); copy(new GZIPInputStream(input), output); } } |