Remove next letters frequency handling
Bug: 3428942 Change-Id: Id62f467ce4e50c60a56d59bf96770e799a4659e2main
parent
a7b2ac26ee
commit
887f11ee43
|
@ -22,6 +22,7 @@ import java.util.List;
|
|||
|
||||
public abstract class KeyDetector {
|
||||
public static final int NOT_A_KEY = -1;
|
||||
public static final int NOT_A_CODE = -1;
|
||||
|
||||
protected Keyboard mKeyboard;
|
||||
|
||||
|
@ -105,10 +106,10 @@ public abstract class KeyDetector {
|
|||
*
|
||||
* @param x The x-coordinate of a touch point
|
||||
* @param y The y-coordinate of a touch point
|
||||
* @param allKeys All nearby key indices are returned in this array
|
||||
* @param allCodes All nearby key code except functional key are returned in this array
|
||||
* @return The nearest key index
|
||||
*/
|
||||
abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys);
|
||||
abstract public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes);
|
||||
|
||||
/**
|
||||
* Compute the most common key width in order to use it as proximity key detection threshold.
|
||||
|
@ -116,14 +117,14 @@ public abstract class KeyDetector {
|
|||
* @param keyboard The keyboard to compute the most common key width
|
||||
* @return The most common key width in the keyboard
|
||||
*/
|
||||
public static int getMostCommonKeyWidth(Keyboard keyboard) {
|
||||
public static int getMostCommonKeyWidth(final Keyboard keyboard) {
|
||||
if (keyboard == null) return 0;
|
||||
final List<Key> keys = keyboard.getKeys();
|
||||
if (keys == null || keys.size() == 0) return 0;
|
||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||
int maxCount = 0;
|
||||
int mostCommonWidth = 0;
|
||||
for (Key key : keys) {
|
||||
for (final Key key : keys) {
|
||||
final Integer width = key.mWidth + key.mGap;
|
||||
Integer count = histogram.get(width);
|
||||
if (count == null)
|
||||
|
|
|
@ -288,12 +288,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
return null;
|
||||
}
|
||||
|
||||
public void setPreferredLetters(int[] frequencies) {
|
||||
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
||||
if (latinKeyboard != null)
|
||||
latinKeyboard.setPreferredLetters(frequencies);
|
||||
}
|
||||
|
||||
public void keyReleased() {
|
||||
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
||||
if (latinKeyboard != null)
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.android.inputmethod.latin.SubtypeSwitcher;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
|
@ -31,17 +32,12 @@ import android.graphics.PorterDuff;
|
|||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
// TODO: We should remove this class
|
||||
public class LatinKeyboard extends Keyboard {
|
||||
|
||||
private static final boolean DEBUG_PREFERRED_LETTER = false;
|
||||
private static final String TAG = "LatinKeyboard";
|
||||
|
||||
public static final int OPACITY_FULLY_OPAQUE = 255;
|
||||
private static final int SPACE_LED_LENGTH_PERCENT = 80;
|
||||
|
||||
|
@ -69,15 +65,7 @@ public class LatinKeyboard extends Keyboard {
|
|||
private final Drawable mEnabledShortcutIcon;
|
||||
private final Drawable mDisabledShortcutIcon;
|
||||
|
||||
private int[] mPrefLetterFrequencies;
|
||||
private int mPrefLetter;
|
||||
private int mPrefLetterX;
|
||||
private int mPrefLetterY;
|
||||
private int mPrefDistance;
|
||||
|
||||
private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
|
||||
private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f;
|
||||
private static final float OVERLAP_PERCENTAGE_HIGH_PROB = 0.85f;
|
||||
// Minimum width of space key preview (proportional to keyboard width)
|
||||
private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
|
||||
// Height in space key the language name will be drawn. (proportional to space key height)
|
||||
|
@ -265,7 +253,7 @@ public class LatinKeyboard extends Keyboard {
|
|||
final boolean allowVariableTextSize = true;
|
||||
final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
|
||||
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
|
||||
getTextSizeFromTheme(textStyle, defaultTextSize),
|
||||
getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize),
|
||||
allowVariableTextSize);
|
||||
|
||||
// Draw language text with shadow
|
||||
|
@ -334,18 +322,9 @@ public class LatinKeyboard extends Keyboard {
|
|||
return mSpaceDragLastDiff > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
public void setPreferredLetters(int[] frequencies) {
|
||||
mPrefLetterFrequencies = frequencies;
|
||||
mPrefLetter = 0;
|
||||
}
|
||||
|
||||
public void keyReleased() {
|
||||
mCurrentlyInSpace = false;
|
||||
mSpaceDragLastDiff = 0;
|
||||
mPrefLetter = 0;
|
||||
mPrefLetterX = 0;
|
||||
mPrefLetterY = 0;
|
||||
mPrefDistance = Integer.MAX_VALUE;
|
||||
if (mSpaceKey != null) {
|
||||
updateLocaleDrag(Integer.MAX_VALUE);
|
||||
}
|
||||
|
@ -381,80 +360,6 @@ public class LatinKeyboard extends Keyboard {
|
|||
return isOnSpace;
|
||||
}
|
||||
}
|
||||
} else if (mPrefLetterFrequencies != null) {
|
||||
// New coordinate? Reset
|
||||
if (mPrefLetterX != x || mPrefLetterY != y) {
|
||||
mPrefLetter = 0;
|
||||
mPrefDistance = Integer.MAX_VALUE;
|
||||
}
|
||||
// Handle preferred next letter
|
||||
final int[] pref = mPrefLetterFrequencies;
|
||||
if (mPrefLetter > 0) {
|
||||
if (DEBUG_PREFERRED_LETTER) {
|
||||
if (mPrefLetter == code && !key.isOnKey(x, y)) {
|
||||
Log.d(TAG, "CORRECTED !!!!!!");
|
||||
}
|
||||
}
|
||||
return mPrefLetter == code;
|
||||
} else {
|
||||
final boolean isOnKey = key.isOnKey(x, y);
|
||||
int[] nearby = getNearestKeys(x, y);
|
||||
List<Key> nearbyKeys = getKeys();
|
||||
if (isOnKey) {
|
||||
// If it's a preferred letter
|
||||
if (inPrefList(code, pref)) {
|
||||
// Check if its frequency is much lower than a nearby key
|
||||
mPrefLetter = code;
|
||||
mPrefLetterX = x;
|
||||
mPrefLetterY = y;
|
||||
for (int i = 0; i < nearby.length; i++) {
|
||||
Key k = nearbyKeys.get(nearby[i]);
|
||||
if (k != key && inPrefList(k.mCode, pref)) {
|
||||
final int dist = distanceFrom(k, x, y);
|
||||
if (dist < (int) (k.mWidth * OVERLAP_PERCENTAGE_LOW_PROB) &&
|
||||
(pref[k.mCode] > pref[mPrefLetter] * 3)) {
|
||||
mPrefLetter = k.mCode;
|
||||
mPrefDistance = dist;
|
||||
if (DEBUG_PREFERRED_LETTER) {
|
||||
Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mPrefLetter == code;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the surrounding keys and intersect with the preferred list
|
||||
// For all in the intersection
|
||||
// if distance from touch point is within a reasonable distance
|
||||
// make this the pref letter
|
||||
// If no pref letter
|
||||
// return inside;
|
||||
// else return thiskey == prefletter;
|
||||
|
||||
for (int i = 0; i < nearby.length; i++) {
|
||||
Key k = nearbyKeys.get(nearby[i]);
|
||||
if (inPrefList(k.mCode, pref)) {
|
||||
final int dist = distanceFrom(k, x, y);
|
||||
if (dist < (int) (k.mWidth * OVERLAP_PERCENTAGE_HIGH_PROB)
|
||||
&& dist < mPrefDistance) {
|
||||
mPrefLetter = k.mCode;
|
||||
mPrefLetterX = x;
|
||||
mPrefLetterY = y;
|
||||
mPrefDistance = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Didn't find any
|
||||
if (mPrefLetter == 0) {
|
||||
return isOnKey;
|
||||
} else {
|
||||
return mPrefLetter == code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock into the spacebar
|
||||
|
@ -463,19 +368,6 @@ public class LatinKeyboard extends Keyboard {
|
|||
return key.isOnKey(x, y);
|
||||
}
|
||||
|
||||
private boolean inPrefList(int code, int[] pref) {
|
||||
if (code < pref.length && code >= 0) return pref[code] > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private int distanceFrom(Key k, int x, int y) {
|
||||
if (y > k.mY && y < k.mY + k.mHeight) {
|
||||
return Math.abs(k.mX + k.mWidth / 2 - x);
|
||||
} else {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getNearestKeys(int x, int y) {
|
||||
if (mCurrentlyInSpace) {
|
||||
|
@ -487,8 +379,8 @@ public class LatinKeyboard extends Keyboard {
|
|||
}
|
||||
}
|
||||
|
||||
private int getTextSizeFromTheme(int style, int defValue) {
|
||||
TypedArray array = mContext.getTheme().obtainStyledAttributes(
|
||||
private static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
|
||||
TypedArray array = theme.obtainStyledAttributes(
|
||||
style, new int[] { android.R.attr.textSize });
|
||||
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
||||
return textSize;
|
||||
|
|
|
@ -35,24 +35,24 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
|
||||
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
||||
final Key[] keys = getKeys();
|
||||
final int touchX = getTouchX(x);
|
||||
final int touchY = getTouchY(y);
|
||||
|
||||
int closestKeyIndex = NOT_A_KEY;
|
||||
int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||
int nearestIndex = NOT_A_KEY;
|
||||
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||
final int keyCount = keys.length;
|
||||
for (int index = 0; index < keyCount; index++) {
|
||||
final int dist = keys[index].squaredDistanceToEdge(touchX, touchY);
|
||||
if (dist < closestKeyDist) {
|
||||
closestKeyIndex = index;
|
||||
closestKeyDist = dist;
|
||||
if (dist < nearestDist) {
|
||||
nearestIndex = index;
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (allKeys != null && closestKeyIndex != NOT_A_KEY)
|
||||
allKeys[0] = keys[closestKeyIndex].mCode;
|
||||
return closestKeyIndex;
|
||||
if (allCodes != null && nearestIndex != NOT_A_KEY)
|
||||
allCodes[0] = keys[nearestIndex].mCode;
|
||||
return nearestIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,49 +16,106 @@
|
|||
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ProximityKeyDetector extends KeyDetector {
|
||||
private static final String TAG = ProximityKeyDetector.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int MAX_NEARBY_KEYS = 12;
|
||||
|
||||
// working area
|
||||
private int[] mDistances = new int[MAX_NEARBY_KEYS];
|
||||
private final int[] mDistances = new int[MAX_NEARBY_KEYS];
|
||||
private final int[] mIndices = new int[MAX_NEARBY_KEYS];
|
||||
|
||||
@Override
|
||||
protected int getMaxNearbyKeys() {
|
||||
return MAX_NEARBY_KEYS;
|
||||
}
|
||||
|
||||
private void initializeNearbyKeys() {
|
||||
Arrays.fill(mDistances, Integer.MAX_VALUE);
|
||||
Arrays.fill(mIndices, NOT_A_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the key into nearby keys buffer and sort nearby keys by ascending order of distance.
|
||||
*
|
||||
* @param keyIndex index of the key.
|
||||
* @param distance distance between the key's edge and user touched point.
|
||||
* @return order of the key in the nearby buffer, 0 if it is the nearest key.
|
||||
*/
|
||||
private int sortNearbyKeys(int keyIndex, int distance) {
|
||||
final int[] distances = mDistances;
|
||||
final int[] indices = mIndices;
|
||||
for (int insertPos = 0; insertPos < distances.length; insertPos++) {
|
||||
if (distance < distances[insertPos]) {
|
||||
final int nextPos = insertPos + 1;
|
||||
if (nextPos < distances.length) {
|
||||
System.arraycopy(distances, insertPos, distances, nextPos,
|
||||
distances.length - nextPos);
|
||||
System.arraycopy(indices, insertPos, indices, nextPos,
|
||||
indices.length - nextPos);
|
||||
}
|
||||
distances[insertPos] = distance;
|
||||
indices[insertPos] = keyIndex;
|
||||
return insertPos;
|
||||
}
|
||||
}
|
||||
return distances.length;
|
||||
}
|
||||
|
||||
private void getNearbyKeyCodes(final int[] allCodes) {
|
||||
final Key[] keys = getKeys();
|
||||
final int[] indices = mIndices;
|
||||
|
||||
// allCodes[0] should always have the key code even if it is a non-letter key.
|
||||
if (indices[0] == NOT_A_KEY) {
|
||||
allCodes[0] = NOT_A_CODE;
|
||||
return;
|
||||
}
|
||||
|
||||
int numCodes = 0;
|
||||
for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) {
|
||||
final int index = indices[j];
|
||||
if (index == NOT_A_KEY)
|
||||
break;
|
||||
final int code = keys[index].mCode;
|
||||
// filter out a non-letter key from nearby keys
|
||||
if (code < Keyboard.CODE_SPACE)
|
||||
continue;
|
||||
allCodes[numCodes++] = code;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) {
|
||||
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
||||
final Key[] keys = getKeys();
|
||||
final int touchX = getTouchX(x);
|
||||
final int touchY = getTouchY(y);
|
||||
|
||||
initializeNearbyKeys();
|
||||
int primaryIndex = NOT_A_KEY;
|
||||
final int[] distances = mDistances;
|
||||
Arrays.fill(distances, Integer.MAX_VALUE);
|
||||
for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
|
||||
final Key key = keys[index];
|
||||
final boolean isInside = key.isInside(touchX, touchY);
|
||||
if (isInside)
|
||||
final int distance = key.squaredDistanceToEdge(touchX, touchY);
|
||||
if (isInside || (mProximityCorrectOn && distance < mProximityThresholdSquare)) {
|
||||
final int insertedPosition = sortNearbyKeys(index, distance);
|
||||
if (insertedPosition == 0 && isInside)
|
||||
primaryIndex = index;
|
||||
final int dist = key.squaredDistanceToEdge(touchX, touchY);
|
||||
if (isInside || (mProximityCorrectOn && dist < mProximityThresholdSquare)) {
|
||||
if (allKeys == null) continue;
|
||||
// Find insertion point
|
||||
for (int j = 0; j < distances.length; j++) {
|
||||
if (distances[j] > dist) {
|
||||
final int nextPos = j + 1;
|
||||
System.arraycopy(distances, j, distances, nextPos,
|
||||
distances.length - nextPos);
|
||||
System.arraycopy(allKeys, j, allKeys, nextPos,
|
||||
allKeys.length - nextPos);
|
||||
distances[j] = dist;
|
||||
allKeys[j] = key.mCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allCodes != null && allCodes.length > 0) {
|
||||
getNearbyKeyCodes(allCodes);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "x=" + x + " y=" + y
|
||||
+ " primary="
|
||||
+ (primaryIndex == NOT_A_KEY ? "none" : keys[primaryIndex].mCode)
|
||||
+ " codes=" + Arrays.toString(allCodes));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,8 +118,7 @@ public class BinaryDictionary extends Dictionary {
|
|||
private native void closeNative(int dict);
|
||||
private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
|
||||
private native int getSuggestionsNative(int dict, int[] inputCodes, int codesSize,
|
||||
char[] outputChars, int[] frequencies,
|
||||
int[] nextLettersFrequencies, int nextLettersSize);
|
||||
char[] outputChars, int[] frequencies);
|
||||
private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength,
|
||||
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] frequencies,
|
||||
int maxWordLength, int maxBigrams, int maxAlternatives);
|
||||
|
@ -133,7 +132,7 @@ public class BinaryDictionary extends Dictionary {
|
|||
|
||||
@Override
|
||||
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
||||
final WordCallback callback) {
|
||||
if (mNativeDict == 0) return;
|
||||
|
||||
char[] chars = previousWord.toString().toCharArray();
|
||||
|
@ -165,15 +164,14 @@ public class BinaryDictionary extends Dictionary {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getWords(final WordComposer codes, final WordCallback callback,
|
||||
int[] nextLettersFrequencies) {
|
||||
public void getWords(final WordComposer codes, final WordCallback callback) {
|
||||
if (mNativeDict == 0) return;
|
||||
|
||||
final int codesSize = codes.size();
|
||||
// Won't deal with really long words.
|
||||
if (codesSize > MAX_WORD_LENGTH - 1) return;
|
||||
|
||||
Arrays.fill(mInputCodes, -1);
|
||||
Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE);
|
||||
for (int i = 0; i < codesSize; i++) {
|
||||
int[] alternatives = codes.getCodesAt(i);
|
||||
System.arraycopy(alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES,
|
||||
|
@ -183,8 +181,7 @@ public class BinaryDictionary extends Dictionary {
|
|||
Arrays.fill(mFrequencies, 0);
|
||||
|
||||
int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, mOutputChars,
|
||||
mFrequencies, nextLettersFrequencies,
|
||||
nextLettersFrequencies != null ? nextLettersFrequencies.length : 0);
|
||||
mFrequencies);
|
||||
|
||||
for (int j = 0; j < count; ++j) {
|
||||
if (mFrequencies[j] < 1) break;
|
||||
|
|
|
@ -61,14 +61,9 @@ public abstract class Dictionary {
|
|||
* words are added through the callback object.
|
||||
* @param composer the key sequence to match
|
||||
* @param callback the callback object to send matched words to as possible candidates
|
||||
* @param nextLettersFrequencies array of frequencies of next letters that could follow the
|
||||
* word so far. For instance, "bracke" can be followed by "t", so array['t'] will have
|
||||
* a non-zero value on returning from this method.
|
||||
* Pass in null if you don't want the dictionary to look up next letters.
|
||||
* @see WordCallback#addWord(char[], int, int)
|
||||
*/
|
||||
abstract public void getWords(final WordComposer composer, final WordCallback callback,
|
||||
int[] nextLettersFrequencies);
|
||||
abstract public void getWords(final WordComposer composer, final WordCallback callback);
|
||||
|
||||
/**
|
||||
* Searches for pairs in the bigram dictionary that matches the previous word and all the
|
||||
|
@ -76,13 +71,9 @@ public abstract class Dictionary {
|
|||
* @param composer the key sequence to match
|
||||
* @param previousWord the word before
|
||||
* @param callback the callback object to send possible word following previous word
|
||||
* @param nextLettersFrequencies array of frequencies of next letters that could follow the
|
||||
* word so far. For instance, "bracke" can be followed by "t", so array['t'] will have
|
||||
* a non-zero value on returning from this method.
|
||||
* Pass in null if you don't want the dictionary to look up next letters.
|
||||
*/
|
||||
public void getBigrams(final WordComposer composer, final CharSequence previousWord,
|
||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
||||
final WordCallback callback) {
|
||||
// empty base implementation
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ public class ExpandableDictionary extends Dictionary {
|
|||
private int mDicTypeId;
|
||||
private int mMaxDepth;
|
||||
private int mInputLength;
|
||||
private int[] mNextLettersFrequencies;
|
||||
private StringBuilder sb = new StringBuilder(MAX_WORD_LENGTH);
|
||||
|
||||
private static final char QUOTE = '\'';
|
||||
|
@ -191,8 +190,7 @@ public class ExpandableDictionary extends Dictionary {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getWords(final WordComposer codes, final WordCallback callback,
|
||||
int[] nextLettersFrequencies) {
|
||||
public void getWords(final WordComposer codes, final WordCallback callback) {
|
||||
synchronized (mUpdatingLock) {
|
||||
// If we need to update, start off a background task
|
||||
if (mRequiresReload) startDictionaryLoadingTaskLocked();
|
||||
|
@ -201,7 +199,6 @@ public class ExpandableDictionary extends Dictionary {
|
|||
}
|
||||
|
||||
mInputLength = codes.size();
|
||||
mNextLettersFrequencies = nextLettersFrequencies;
|
||||
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
|
||||
// Cache the codes so that we don't have to lookup an array list
|
||||
for (int i = 0; i < mInputLength; i++) {
|
||||
|
@ -282,11 +279,6 @@ public class ExpandableDictionary extends Dictionary {
|
|||
DataType.UNIGRAM)) {
|
||||
return;
|
||||
}
|
||||
// Add to frequency of next letters for predictive correction
|
||||
if (mNextLettersFrequencies != null && depth >= inputIndex && skipPos < 0
|
||||
&& mNextLettersFrequencies.length > word[inputIndex]) {
|
||||
mNextLettersFrequencies[word[inputIndex]]++;
|
||||
}
|
||||
}
|
||||
if (children != null) {
|
||||
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
|
||||
|
@ -427,7 +419,7 @@ public class ExpandableDictionary extends Dictionary {
|
|||
|
||||
@Override
|
||||
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
||||
final WordCallback callback) {
|
||||
if (!reloadDictionaryIfRequired()) {
|
||||
runReverseLookUp(previousWord, callback);
|
||||
}
|
||||
|
@ -516,7 +508,7 @@ public class ExpandableDictionary extends Dictionary {
|
|||
}
|
||||
}
|
||||
|
||||
static char toLowerCase(char c) {
|
||||
private static char toLowerCase(char c) {
|
||||
char baseChar = c;
|
||||
if (c < BASE_CHARS.length) {
|
||||
baseChar = BASE_CHARS[c];
|
||||
|
@ -535,7 +527,7 @@ public class ExpandableDictionary extends Dictionary {
|
|||
* if c is not a combined character, or the base character if it
|
||||
* is combined.
|
||||
*/
|
||||
static final char BASE_CHARS[] = {
|
||||
private static final char BASE_CHARS[] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
|
|
|
@ -1500,8 +1500,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
public void updateSuggestions() {
|
||||
mKeyboardSwitcher.setPreferredLetters(null);
|
||||
|
||||
// Check if we have a suggestion engine attached.
|
||||
if ((mSuggest == null || !isSuggestionsRequested())
|
||||
&& !mVoiceConnector.isVoiceInputHighlighted()) {
|
||||
|
@ -1520,7 +1518,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
private void showCorrections(WordAlternatives alternatives) {
|
||||
mKeyboardSwitcher.setPreferredLetters(null);
|
||||
SuggestedWords.Builder builder = alternatives.getAlternatives();
|
||||
builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
|
||||
showSuggestions(builder.build(), alternatives.getOriginalWord());
|
||||
|
@ -1533,9 +1530,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
|
||||
mKeyboardSwitcher.getInputView(), word, prevWord);
|
||||
|
||||
int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
|
||||
mKeyboardSwitcher.setPreferredLetters(nextLettersFrequencies);
|
||||
|
||||
boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted
|
||||
&& mSuggest.hasAutoCorrection();
|
||||
final CharSequence typedWord = word.getTypedWord();
|
||||
|
@ -1704,7 +1698,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
saveWordInHistory(suggestion);
|
||||
mHasValidSuggestions = false;
|
||||
mCommittedLength = suggestion.length();
|
||||
switcher.setPreferredLetters(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,12 +87,6 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
private int[] mPriorities = new int[mPrefMaxSuggestions];
|
||||
private int[] mBigramPriorities = new int[PREF_MAX_BIGRAMS];
|
||||
|
||||
// Handle predictive correction for only the first 1280 characters for performance reasons
|
||||
// If we support scripts that need latin characters beyond that, we should probably use some
|
||||
// kind of a sparse array or language specific list with a mapping lookup table.
|
||||
// 1280 is the size of the BASE_CHARS array in ExpandableDictionary, which is a basic set of
|
||||
// latin characters.
|
||||
private int[] mNextLettersFrequencies = new int[1280];
|
||||
private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
|
||||
ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
|
||||
private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
|
||||
|
@ -216,7 +210,6 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
mIsAllUpperCase = wordComposer.isAllUpperCase();
|
||||
collectGarbage(mSuggestions, mPrefMaxSuggestions);
|
||||
Arrays.fill(mPriorities, 0);
|
||||
Arrays.fill(mNextLettersFrequencies, 0);
|
||||
|
||||
// Save a lowercase version of the original word
|
||||
CharSequence typedWord = wordComposer.getTypedWord();
|
||||
|
@ -244,16 +237,13 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
prevWordForBigram = lowerPrevWord;
|
||||
}
|
||||
if (mUserBigramDictionary != null) {
|
||||
mUserBigramDictionary.getBigrams(wordComposer, prevWordForBigram, this,
|
||||
mNextLettersFrequencies);
|
||||
mUserBigramDictionary.getBigrams(wordComposer, prevWordForBigram, this);
|
||||
}
|
||||
if (mContactsDictionary != null) {
|
||||
mContactsDictionary.getBigrams(wordComposer, prevWordForBigram, this,
|
||||
mNextLettersFrequencies);
|
||||
mContactsDictionary.getBigrams(wordComposer, prevWordForBigram, this);
|
||||
}
|
||||
if (mMainDict != null) {
|
||||
mMainDict.getBigrams(wordComposer, prevWordForBigram, this,
|
||||
mNextLettersFrequencies);
|
||||
mMainDict.getBigrams(wordComposer, prevWordForBigram, this);
|
||||
}
|
||||
char currentChar = wordComposer.getTypedWord().charAt(0);
|
||||
char currentCharUpper = Character.toUpperCase(currentChar);
|
||||
|
@ -278,10 +268,10 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
// At second character typed, search the unigrams (scores being affected by bigrams)
|
||||
if (mUserDictionary != null || mContactsDictionary != null) {
|
||||
if (mUserDictionary != null) {
|
||||
mUserDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
|
||||
mUserDictionary.getWords(wordComposer, this);
|
||||
}
|
||||
if (mContactsDictionary != null) {
|
||||
mContactsDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
|
||||
mContactsDictionary.getWords(wordComposer, this);
|
||||
}
|
||||
|
||||
if (mSuggestions.size() > 0 && isValidWord(typedWord)
|
||||
|
@ -293,7 +283,7 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
mHasAutoCorrection = true;
|
||||
}
|
||||
}
|
||||
if (mMainDict != null) mMainDict.getWords(wordComposer, this, mNextLettersFrequencies);
|
||||
if (mMainDict != null) mMainDict.getWords(wordComposer, this);
|
||||
if ((mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM)
|
||||
&& mSuggestions.size() > 0 && mPriorities.length > 0) {
|
||||
// TODO: when the normalized score of the first suggestion is nearly equals to
|
||||
|
@ -388,10 +378,6 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
}
|
||||
}
|
||||
|
||||
public int[] getNextLettersFrequencies() {
|
||||
return mNextLettersFrequencies;
|
||||
}
|
||||
|
||||
private void removeDupes() {
|
||||
final ArrayList<CharSequence> suggestions = mSuggestions;
|
||||
if (suggestions.size() < 2) return;
|
||||
|
|
|
@ -126,9 +126,8 @@ public class UserDictionary extends ExpandableDictionary {
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized void getWords(final WordComposer codes, final WordCallback callback,
|
||||
int[] nextLettersFrequencies) {
|
||||
super.getWords(codes, callback, nextLettersFrequencies);
|
||||
public synchronized void getWords(final WordComposer codes, final WordCallback callback) {
|
||||
super.getWords(codes, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,12 +16,16 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.keyboard.KeyDetector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A place to store the currently composing word with information such as adjacent key codes as well
|
||||
*/
|
||||
public class WordComposer {
|
||||
public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
|
||||
|
||||
/**
|
||||
* The list of unicode values for each keystroke (including surrounding keys)
|
||||
*/
|
||||
|
|
|
@ -123,26 +123,20 @@ static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
|
|||
}
|
||||
|
||||
static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jint dict,
|
||||
jintArray inputArray, jint arraySize, jcharArray outputArray, jintArray frequencyArray,
|
||||
jintArray nextLettersArray, jint nextLettersSize) {
|
||||
jintArray inputArray, jint arraySize, jcharArray outputArray, jintArray frequencyArray) {
|
||||
Dictionary *dictionary = (Dictionary*)dict;
|
||||
if (!dictionary) return 0;
|
||||
|
||||
int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
|
||||
int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
|
||||
jchar *outputChars = env->GetCharArrayElements(outputArray, NULL);
|
||||
int *nextLetters = nextLettersArray != NULL ? env->GetIntArrayElements(nextLettersArray, NULL)
|
||||
: NULL;
|
||||
|
||||
int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars,
|
||||
frequencies, nextLetters, nextLettersSize);
|
||||
frequencies);
|
||||
|
||||
env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
|
||||
env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
|
||||
env->ReleaseCharArrayElements(outputArray, outputChars, 0);
|
||||
if (nextLetters) {
|
||||
env->ReleaseIntArrayElements(nextLettersArray, nextLetters, 0);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -209,7 +203,7 @@ static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jint di
|
|||
static JNINativeMethod gMethods[] = {
|
||||
{"openNative", "(Ljava/lang/String;JJIIIII)I", (void*)latinime_BinaryDictionary_open},
|
||||
{"closeNative", "(I)V", (void*)latinime_BinaryDictionary_close},
|
||||
{"getSuggestionsNative", "(I[II[C[I[II)I", (void*)latinime_BinaryDictionary_getSuggestions},
|
||||
{"getSuggestionsNative", "(I[II[C[I)I", (void*)latinime_BinaryDictionary_getSuggestions},
|
||||
{"isValidWordNative", "(I[CI)Z", (void*)latinime_BinaryDictionary_isValidWord},
|
||||
{"getBigramsNative", "(I[CI[II[C[IIII)I", (void*)latinime_BinaryDictionary_getBigrams}
|
||||
};
|
||||
|
|
|
@ -151,6 +151,9 @@ static void prof_out(void) {
|
|||
#define MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION 3
|
||||
#define MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION 3
|
||||
|
||||
// The size of next letters frequency array. Zero will disable the feature.
|
||||
#define NEXT_LETTERS_SIZE 0
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
#endif // LATINIME_DEFINES_H
|
||||
|
|
|
@ -27,10 +27,8 @@ class Dictionary {
|
|||
public:
|
||||
Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler,
|
||||
int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives);
|
||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
|
||||
int *nextLetters, int nextLettersSize) {
|
||||
return mUnigramDictionary->getSuggestions(codes, codesSize, outWords, frequencies,
|
||||
nextLetters, nextLettersSize);
|
||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies) {
|
||||
return mUnigramDictionary->getSuggestions(codes, codesSize, outWords, frequencies);
|
||||
}
|
||||
|
||||
// TODO: Call mBigramDictionary instead of mUnigramDictionary
|
||||
|
|
|
@ -42,7 +42,7 @@ UnigramDictionary::UnigramDictionary(const unsigned char *dict, int typedLetterM
|
|||
UnigramDictionary::~UnigramDictionary() {}
|
||||
|
||||
int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWords,
|
||||
int *frequencies, int *nextLetters, int nextLettersSize) {
|
||||
int *frequencies) {
|
||||
PROF_OPEN;
|
||||
PROF_START(0);
|
||||
initSuggestions(codes, codesSize, outWords, frequencies);
|
||||
|
@ -52,7 +52,7 @@ int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short
|
|||
PROF_END(0);
|
||||
|
||||
PROF_START(1);
|
||||
getSuggestionCandidates(-1, -1, -1, nextLetters, nextLettersSize, MAX_DEPTH);
|
||||
getSuggestionCandidates(-1, -1, -1, mNextLettersFrequency, NEXT_LETTERS_SIZE, MAX_DEPTH);
|
||||
PROF_END(1);
|
||||
|
||||
PROF_START(2);
|
||||
|
@ -108,9 +108,9 @@ int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short
|
|||
if (DEBUG_DICT) {
|
||||
LOGI("Returning %d words", suggestedWordsCount);
|
||||
LOGI("Next letters: ");
|
||||
for (int k = 0; k < nextLettersSize; k++) {
|
||||
if (nextLetters[k] > 0) {
|
||||
LOGI("%c = %d,", k, nextLetters[k]);
|
||||
for (int k = 0; k < NEXT_LETTERS_SIZE; k++) {
|
||||
if (mNextLettersFrequency[k] > 0) {
|
||||
LOGI("%c = %d,", k, mNextLettersFrequency[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@ class UnigramDictionary {
|
|||
public:
|
||||
UnigramDictionary(const unsigned char *dict, int typedLetterMultipler, int fullWordMultiplier,
|
||||
int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion);
|
||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
|
||||
int *nextLetters, int nextLettersSize);
|
||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies);
|
||||
~UnigramDictionary();
|
||||
|
||||
private:
|
||||
|
@ -109,6 +108,7 @@ private:
|
|||
int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];
|
||||
int mStackDiffs[MAX_WORD_LENGTH_INTERNAL];
|
||||
int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];
|
||||
int mNextLettersFrequency[NEXT_LETTERS_SIZE];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -61,7 +61,7 @@ public class UserBigramSuggestHelper extends SuggestHelper {
|
|||
mSuggest.getSuggestions(null, firstChar, previous);
|
||||
boolean reloading = mUserBigram.reloadDictionaryIfRequired();
|
||||
if (reloading) mUserBigram.waitForDictionaryLoading();
|
||||
mUserBigram.getBigrams(firstChar, previous, mSuggest, null);
|
||||
mUserBigram.getBigrams(firstChar, previous, mSuggest);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mSuggest.mBigramSuggestions.size(); i++) {
|
||||
|
|
Loading…
Reference in New Issue