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 abstract class KeyDetector {
|
||||||
public static final int NOT_A_KEY = -1;
|
public static final int NOT_A_KEY = -1;
|
||||||
|
public static final int NOT_A_CODE = -1;
|
||||||
|
|
||||||
protected Keyboard mKeyboard;
|
protected Keyboard mKeyboard;
|
||||||
|
|
||||||
|
@ -105,10 +106,10 @@ public abstract class KeyDetector {
|
||||||
*
|
*
|
||||||
* @param x The x-coordinate of a touch point
|
* @param x The x-coordinate of a touch point
|
||||||
* @param y The y-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
|
* @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.
|
* 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
|
* @param keyboard The keyboard to compute the most common key width
|
||||||
* @return The most common key width in the keyboard
|
* @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;
|
if (keyboard == null) return 0;
|
||||||
final List<Key> keys = keyboard.getKeys();
|
final List<Key> keys = keyboard.getKeys();
|
||||||
if (keys == null || keys.size() == 0) return 0;
|
if (keys == null || keys.size() == 0) return 0;
|
||||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||||
int maxCount = 0;
|
int maxCount = 0;
|
||||||
int mostCommonWidth = 0;
|
int mostCommonWidth = 0;
|
||||||
for (Key key : keys) {
|
for (final Key key : keys) {
|
||||||
final Integer width = key.mWidth + key.mGap;
|
final Integer width = key.mWidth + key.mGap;
|
||||||
Integer count = histogram.get(width);
|
Integer count = histogram.get(width);
|
||||||
if (count == null)
|
if (count == null)
|
||||||
|
|
|
@ -288,12 +288,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPreferredLetters(int[] frequencies) {
|
|
||||||
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
|
||||||
if (latinKeyboard != null)
|
|
||||||
latinKeyboard.setPreferredLetters(frequencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void keyReleased() {
|
public void keyReleased() {
|
||||||
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
LatinKeyboard latinKeyboard = getLatinKeyboard();
|
||||||
if (latinKeyboard != null)
|
if (latinKeyboard != null)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.Resources.Theme;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
@ -31,17 +32,12 @@ import android.graphics.PorterDuff;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
// TODO: We should remove this class
|
// TODO: We should remove this class
|
||||||
public class LatinKeyboard extends Keyboard {
|
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;
|
public static final int OPACITY_FULLY_OPAQUE = 255;
|
||||||
private static final int SPACE_LED_LENGTH_PERCENT = 80;
|
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 mEnabledShortcutIcon;
|
||||||
private final Drawable mDisabledShortcutIcon;
|
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 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)
|
// Minimum width of space key preview (proportional to keyboard width)
|
||||||
private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
|
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)
|
// 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 boolean allowVariableTextSize = true;
|
||||||
final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
|
final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
|
||||||
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
|
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
|
||||||
getTextSizeFromTheme(textStyle, defaultTextSize),
|
getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize),
|
||||||
allowVariableTextSize);
|
allowVariableTextSize);
|
||||||
|
|
||||||
// Draw language text with shadow
|
// Draw language text with shadow
|
||||||
|
@ -334,18 +322,9 @@ public class LatinKeyboard extends Keyboard {
|
||||||
return mSpaceDragLastDiff > 0 ? 1 : -1;
|
return mSpaceDragLastDiff > 0 ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPreferredLetters(int[] frequencies) {
|
|
||||||
mPrefLetterFrequencies = frequencies;
|
|
||||||
mPrefLetter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void keyReleased() {
|
public void keyReleased() {
|
||||||
mCurrentlyInSpace = false;
|
mCurrentlyInSpace = false;
|
||||||
mSpaceDragLastDiff = 0;
|
mSpaceDragLastDiff = 0;
|
||||||
mPrefLetter = 0;
|
|
||||||
mPrefLetterX = 0;
|
|
||||||
mPrefLetterY = 0;
|
|
||||||
mPrefDistance = Integer.MAX_VALUE;
|
|
||||||
if (mSpaceKey != null) {
|
if (mSpaceKey != null) {
|
||||||
updateLocaleDrag(Integer.MAX_VALUE);
|
updateLocaleDrag(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
@ -381,80 +360,6 @@ public class LatinKeyboard extends Keyboard {
|
||||||
return isOnSpace;
|
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
|
// Lock into the spacebar
|
||||||
|
@ -463,19 +368,6 @@ public class LatinKeyboard extends Keyboard {
|
||||||
return key.isOnKey(x, y);
|
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
|
@Override
|
||||||
public int[] getNearestKeys(int x, int y) {
|
public int[] getNearestKeys(int x, int y) {
|
||||||
if (mCurrentlyInSpace) {
|
if (mCurrentlyInSpace) {
|
||||||
|
@ -487,8 +379,8 @@ public class LatinKeyboard extends Keyboard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTextSizeFromTheme(int style, int defValue) {
|
private static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
|
||||||
TypedArray array = mContext.getTheme().obtainStyledAttributes(
|
TypedArray array = theme.obtainStyledAttributes(
|
||||||
style, new int[] { android.R.attr.textSize });
|
style, new int[] { android.R.attr.textSize });
|
||||||
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
||||||
return textSize;
|
return textSize;
|
||||||
|
|
|
@ -35,24 +35,24 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 Key[] keys = getKeys();
|
||||||
final int touchX = getTouchX(x);
|
final int touchX = getTouchX(x);
|
||||||
final int touchY = getTouchY(y);
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
int closestKeyIndex = NOT_A_KEY;
|
int nearestIndex = NOT_A_KEY;
|
||||||
int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||||
final int keyCount = keys.length;
|
final int keyCount = keys.length;
|
||||||
for (int index = 0; index < keyCount; index++) {
|
for (int index = 0; index < keyCount; index++) {
|
||||||
final int dist = keys[index].squaredDistanceToEdge(touchX, touchY);
|
final int dist = keys[index].squaredDistanceToEdge(touchX, touchY);
|
||||||
if (dist < closestKeyDist) {
|
if (dist < nearestDist) {
|
||||||
closestKeyIndex = index;
|
nearestIndex = index;
|
||||||
closestKeyDist = dist;
|
nearestDist = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allKeys != null && closestKeyIndex != NOT_A_KEY)
|
if (allCodes != null && nearestIndex != NOT_A_KEY)
|
||||||
allKeys[0] = keys[closestKeyIndex].mCode;
|
allCodes[0] = keys[nearestIndex].mCode;
|
||||||
return closestKeyIndex;
|
return nearestIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,49 +16,106 @@
|
||||||
|
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class ProximityKeyDetector extends KeyDetector {
|
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;
|
private static final int MAX_NEARBY_KEYS = 12;
|
||||||
|
|
||||||
// working area
|
// 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
|
@Override
|
||||||
protected int getMaxNearbyKeys() {
|
protected int getMaxNearbyKeys() {
|
||||||
return MAX_NEARBY_KEYS;
|
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
|
@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 Key[] keys = getKeys();
|
||||||
final int touchX = getTouchX(x);
|
final int touchX = getTouchX(x);
|
||||||
final int touchY = getTouchY(y);
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
|
initializeNearbyKeys();
|
||||||
int primaryIndex = NOT_A_KEY;
|
int primaryIndex = NOT_A_KEY;
|
||||||
final int[] distances = mDistances;
|
|
||||||
Arrays.fill(distances, Integer.MAX_VALUE);
|
|
||||||
for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
|
for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
|
||||||
final Key key = keys[index];
|
final Key key = keys[index];
|
||||||
final boolean isInside = key.isInside(touchX, touchY);
|
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;
|
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 void closeNative(int dict);
|
||||||
private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
|
private native boolean isValidWordNative(int nativeData, char[] word, int wordLength);
|
||||||
private native int getSuggestionsNative(int dict, int[] inputCodes, int codesSize,
|
private native int getSuggestionsNative(int dict, int[] inputCodes, int codesSize,
|
||||||
char[] outputChars, int[] frequencies,
|
char[] outputChars, int[] frequencies);
|
||||||
int[] nextLettersFrequencies, int nextLettersSize);
|
|
||||||
private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength,
|
private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength,
|
||||||
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] frequencies,
|
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] frequencies,
|
||||||
int maxWordLength, int maxBigrams, int maxAlternatives);
|
int maxWordLength, int maxBigrams, int maxAlternatives);
|
||||||
|
@ -133,7 +132,7 @@ public class BinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
||||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
final WordCallback callback) {
|
||||||
if (mNativeDict == 0) return;
|
if (mNativeDict == 0) return;
|
||||||
|
|
||||||
char[] chars = previousWord.toString().toCharArray();
|
char[] chars = previousWord.toString().toCharArray();
|
||||||
|
@ -165,15 +164,14 @@ public class BinaryDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getWords(final WordComposer codes, final WordCallback callback,
|
public void getWords(final WordComposer codes, final WordCallback callback) {
|
||||||
int[] nextLettersFrequencies) {
|
|
||||||
if (mNativeDict == 0) return;
|
if (mNativeDict == 0) return;
|
||||||
|
|
||||||
final int codesSize = codes.size();
|
final int codesSize = codes.size();
|
||||||
// Won't deal with really long words.
|
// Won't deal with really long words.
|
||||||
if (codesSize > MAX_WORD_LENGTH - 1) return;
|
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++) {
|
for (int i = 0; i < codesSize; i++) {
|
||||||
int[] alternatives = codes.getCodesAt(i);
|
int[] alternatives = codes.getCodesAt(i);
|
||||||
System.arraycopy(alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES,
|
System.arraycopy(alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES,
|
||||||
|
@ -183,8 +181,7 @@ public class BinaryDictionary extends Dictionary {
|
||||||
Arrays.fill(mFrequencies, 0);
|
Arrays.fill(mFrequencies, 0);
|
||||||
|
|
||||||
int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, mOutputChars,
|
int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, mOutputChars,
|
||||||
mFrequencies, nextLettersFrequencies,
|
mFrequencies);
|
||||||
nextLettersFrequencies != null ? nextLettersFrequencies.length : 0);
|
|
||||||
|
|
||||||
for (int j = 0; j < count; ++j) {
|
for (int j = 0; j < count; ++j) {
|
||||||
if (mFrequencies[j] < 1) break;
|
if (mFrequencies[j] < 1) break;
|
||||||
|
|
|
@ -61,14 +61,9 @@ public abstract class Dictionary {
|
||||||
* words are added through the callback object.
|
* words are added through the callback object.
|
||||||
* @param composer the key sequence to match
|
* @param composer the key sequence to match
|
||||||
* @param callback the callback object to send matched words to as possible candidates
|
* @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)
|
* @see WordCallback#addWord(char[], int, int)
|
||||||
*/
|
*/
|
||||||
abstract public void getWords(final WordComposer composer, final WordCallback callback,
|
abstract public void getWords(final WordComposer composer, final WordCallback callback);
|
||||||
int[] nextLettersFrequencies);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for pairs in the bigram dictionary that matches the previous word and all the
|
* 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 composer the key sequence to match
|
||||||
* @param previousWord the word before
|
* @param previousWord the word before
|
||||||
* @param callback the callback object to send possible word following previous word
|
* @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,
|
public void getBigrams(final WordComposer composer, final CharSequence previousWord,
|
||||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
final WordCallback callback) {
|
||||||
// empty base implementation
|
// empty base implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class ExpandableDictionary extends Dictionary {
|
||||||
private int mDicTypeId;
|
private int mDicTypeId;
|
||||||
private int mMaxDepth;
|
private int mMaxDepth;
|
||||||
private int mInputLength;
|
private int mInputLength;
|
||||||
private int[] mNextLettersFrequencies;
|
|
||||||
private StringBuilder sb = new StringBuilder(MAX_WORD_LENGTH);
|
private StringBuilder sb = new StringBuilder(MAX_WORD_LENGTH);
|
||||||
|
|
||||||
private static final char QUOTE = '\'';
|
private static final char QUOTE = '\'';
|
||||||
|
@ -191,8 +190,7 @@ public class ExpandableDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getWords(final WordComposer codes, final WordCallback callback,
|
public void getWords(final WordComposer codes, final WordCallback callback) {
|
||||||
int[] nextLettersFrequencies) {
|
|
||||||
synchronized (mUpdatingLock) {
|
synchronized (mUpdatingLock) {
|
||||||
// If we need to update, start off a background task
|
// If we need to update, start off a background task
|
||||||
if (mRequiresReload) startDictionaryLoadingTaskLocked();
|
if (mRequiresReload) startDictionaryLoadingTaskLocked();
|
||||||
|
@ -201,7 +199,6 @@ public class ExpandableDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
mInputLength = codes.size();
|
mInputLength = codes.size();
|
||||||
mNextLettersFrequencies = nextLettersFrequencies;
|
|
||||||
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
|
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
|
||||||
// Cache the codes so that we don't have to lookup an array list
|
// Cache the codes so that we don't have to lookup an array list
|
||||||
for (int i = 0; i < mInputLength; i++) {
|
for (int i = 0; i < mInputLength; i++) {
|
||||||
|
@ -282,11 +279,6 @@ public class ExpandableDictionary extends Dictionary {
|
||||||
DataType.UNIGRAM)) {
|
DataType.UNIGRAM)) {
|
||||||
return;
|
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) {
|
if (children != null) {
|
||||||
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
|
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
|
||||||
|
@ -427,7 +419,7 @@ public class ExpandableDictionary extends Dictionary {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
public void getBigrams(final WordComposer codes, final CharSequence previousWord,
|
||||||
final WordCallback callback, int[] nextLettersFrequencies) {
|
final WordCallback callback) {
|
||||||
if (!reloadDictionaryIfRequired()) {
|
if (!reloadDictionaryIfRequired()) {
|
||||||
runReverseLookUp(previousWord, callback);
|
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;
|
char baseChar = c;
|
||||||
if (c < BASE_CHARS.length) {
|
if (c < BASE_CHARS.length) {
|
||||||
baseChar = BASE_CHARS[c];
|
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
|
* if c is not a combined character, or the base character if it
|
||||||
* is combined.
|
* is combined.
|
||||||
*/
|
*/
|
||||||
static final char BASE_CHARS[] = {
|
private static final char BASE_CHARS[] = {
|
||||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||||
|
|
|
@ -1500,8 +1500,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSuggestions() {
|
public void updateSuggestions() {
|
||||||
mKeyboardSwitcher.setPreferredLetters(null);
|
|
||||||
|
|
||||||
// Check if we have a suggestion engine attached.
|
// Check if we have a suggestion engine attached.
|
||||||
if ((mSuggest == null || !isSuggestionsRequested())
|
if ((mSuggest == null || !isSuggestionsRequested())
|
||||||
&& !mVoiceConnector.isVoiceInputHighlighted()) {
|
&& !mVoiceConnector.isVoiceInputHighlighted()) {
|
||||||
|
@ -1520,7 +1518,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showCorrections(WordAlternatives alternatives) {
|
private void showCorrections(WordAlternatives alternatives) {
|
||||||
mKeyboardSwitcher.setPreferredLetters(null);
|
|
||||||
SuggestedWords.Builder builder = alternatives.getAlternatives();
|
SuggestedWords.Builder builder = alternatives.getAlternatives();
|
||||||
builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
|
builder.setTypedWordValid(false).setHasMinimalSuggestion(false);
|
||||||
showSuggestions(builder.build(), alternatives.getOriginalWord());
|
showSuggestions(builder.build(), alternatives.getOriginalWord());
|
||||||
|
@ -1533,9 +1530,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
|
SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
|
||||||
mKeyboardSwitcher.getInputView(), word, prevWord);
|
mKeyboardSwitcher.getInputView(), word, prevWord);
|
||||||
|
|
||||||
int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
|
|
||||||
mKeyboardSwitcher.setPreferredLetters(nextLettersFrequencies);
|
|
||||||
|
|
||||||
boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted
|
boolean correctionAvailable = !mInputTypeNoAutoCorrect && !mJustReverted
|
||||||
&& mSuggest.hasAutoCorrection();
|
&& mSuggest.hasAutoCorrection();
|
||||||
final CharSequence typedWord = word.getTypedWord();
|
final CharSequence typedWord = word.getTypedWord();
|
||||||
|
@ -1704,7 +1698,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
saveWordInHistory(suggestion);
|
saveWordInHistory(suggestion);
|
||||||
mHasValidSuggestions = false;
|
mHasValidSuggestions = false;
|
||||||
mCommittedLength = suggestion.length();
|
mCommittedLength = suggestion.length();
|
||||||
switcher.setPreferredLetters(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -87,12 +87,6 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
private int[] mPriorities = new int[mPrefMaxSuggestions];
|
private int[] mPriorities = new int[mPrefMaxSuggestions];
|
||||||
private int[] mBigramPriorities = new int[PREF_MAX_BIGRAMS];
|
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>();
|
private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
|
||||||
ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
|
ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>();
|
||||||
private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
|
private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
|
||||||
|
@ -216,7 +210,6 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
mIsAllUpperCase = wordComposer.isAllUpperCase();
|
mIsAllUpperCase = wordComposer.isAllUpperCase();
|
||||||
collectGarbage(mSuggestions, mPrefMaxSuggestions);
|
collectGarbage(mSuggestions, mPrefMaxSuggestions);
|
||||||
Arrays.fill(mPriorities, 0);
|
Arrays.fill(mPriorities, 0);
|
||||||
Arrays.fill(mNextLettersFrequencies, 0);
|
|
||||||
|
|
||||||
// Save a lowercase version of the original word
|
// Save a lowercase version of the original word
|
||||||
CharSequence typedWord = wordComposer.getTypedWord();
|
CharSequence typedWord = wordComposer.getTypedWord();
|
||||||
|
@ -244,16 +237,13 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
prevWordForBigram = lowerPrevWord;
|
prevWordForBigram = lowerPrevWord;
|
||||||
}
|
}
|
||||||
if (mUserBigramDictionary != null) {
|
if (mUserBigramDictionary != null) {
|
||||||
mUserBigramDictionary.getBigrams(wordComposer, prevWordForBigram, this,
|
mUserBigramDictionary.getBigrams(wordComposer, prevWordForBigram, this);
|
||||||
mNextLettersFrequencies);
|
|
||||||
}
|
}
|
||||||
if (mContactsDictionary != null) {
|
if (mContactsDictionary != null) {
|
||||||
mContactsDictionary.getBigrams(wordComposer, prevWordForBigram, this,
|
mContactsDictionary.getBigrams(wordComposer, prevWordForBigram, this);
|
||||||
mNextLettersFrequencies);
|
|
||||||
}
|
}
|
||||||
if (mMainDict != null) {
|
if (mMainDict != null) {
|
||||||
mMainDict.getBigrams(wordComposer, prevWordForBigram, this,
|
mMainDict.getBigrams(wordComposer, prevWordForBigram, this);
|
||||||
mNextLettersFrequencies);
|
|
||||||
}
|
}
|
||||||
char currentChar = wordComposer.getTypedWord().charAt(0);
|
char currentChar = wordComposer.getTypedWord().charAt(0);
|
||||||
char currentCharUpper = Character.toUpperCase(currentChar);
|
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)
|
// At second character typed, search the unigrams (scores being affected by bigrams)
|
||||||
if (mUserDictionary != null || mContactsDictionary != null) {
|
if (mUserDictionary != null || mContactsDictionary != null) {
|
||||||
if (mUserDictionary != null) {
|
if (mUserDictionary != null) {
|
||||||
mUserDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
|
mUserDictionary.getWords(wordComposer, this);
|
||||||
}
|
}
|
||||||
if (mContactsDictionary != null) {
|
if (mContactsDictionary != null) {
|
||||||
mContactsDictionary.getWords(wordComposer, this, mNextLettersFrequencies);
|
mContactsDictionary.getWords(wordComposer, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSuggestions.size() > 0 && isValidWord(typedWord)
|
if (mSuggestions.size() > 0 && isValidWord(typedWord)
|
||||||
|
@ -293,7 +283,7 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
mHasAutoCorrection = true;
|
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)
|
if ((mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM)
|
||||||
&& mSuggestions.size() > 0 && mPriorities.length > 0) {
|
&& mSuggestions.size() > 0 && mPriorities.length > 0) {
|
||||||
// TODO: when the normalized score of the first suggestion is nearly equals to
|
// 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() {
|
private void removeDupes() {
|
||||||
final ArrayList<CharSequence> suggestions = mSuggestions;
|
final ArrayList<CharSequence> suggestions = mSuggestions;
|
||||||
if (suggestions.size() < 2) return;
|
if (suggestions.size() < 2) return;
|
||||||
|
|
|
@ -126,9 +126,8 @@ public class UserDictionary extends ExpandableDictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void getWords(final WordComposer codes, final WordCallback callback,
|
public synchronized void getWords(final WordComposer codes, final WordCallback callback) {
|
||||||
int[] nextLettersFrequencies) {
|
super.getWords(codes, callback);
|
||||||
super.getWords(codes, callback, nextLettersFrequencies);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,12 +16,16 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.KeyDetector;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A place to store the currently composing word with information such as adjacent key codes as well
|
* A place to store the currently composing word with information such as adjacent key codes as well
|
||||||
*/
|
*/
|
||||||
public class WordComposer {
|
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)
|
* 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,
|
static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jint dict,
|
||||||
jintArray inputArray, jint arraySize, jcharArray outputArray, jintArray frequencyArray,
|
jintArray inputArray, jint arraySize, jcharArray outputArray, jintArray frequencyArray) {
|
||||||
jintArray nextLettersArray, jint nextLettersSize) {
|
|
||||||
Dictionary *dictionary = (Dictionary*)dict;
|
Dictionary *dictionary = (Dictionary*)dict;
|
||||||
if (!dictionary) return 0;
|
if (!dictionary) return 0;
|
||||||
|
|
||||||
int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
|
int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
|
||||||
int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
|
int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
|
||||||
jchar *outputChars = env->GetCharArrayElements(outputArray, 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,
|
int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars,
|
||||||
frequencies, nextLetters, nextLettersSize);
|
frequencies);
|
||||||
|
|
||||||
env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
|
env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
|
||||||
env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
|
env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
|
||||||
env->ReleaseCharArrayElements(outputArray, outputChars, 0);
|
env->ReleaseCharArrayElements(outputArray, outputChars, 0);
|
||||||
if (nextLetters) {
|
|
||||||
env->ReleaseIntArrayElements(nextLettersArray, nextLetters, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +203,7 @@ static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jint di
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
{"openNative", "(Ljava/lang/String;JJIIIII)I", (void*)latinime_BinaryDictionary_open},
|
{"openNative", "(Ljava/lang/String;JJIIIII)I", (void*)latinime_BinaryDictionary_open},
|
||||||
{"closeNative", "(I)V", (void*)latinime_BinaryDictionary_close},
|
{"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},
|
{"isValidWordNative", "(I[CI)Z", (void*)latinime_BinaryDictionary_isValidWord},
|
||||||
{"getBigramsNative", "(I[CI[II[C[IIII)I", (void*)latinime_BinaryDictionary_getBigrams}
|
{"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_MISSING_SPACE_SUGGESTION 3
|
||||||
#define MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_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))
|
#define min(a,b) ((a)<(b)?(a):(b))
|
||||||
|
|
||||||
#endif // LATINIME_DEFINES_H
|
#endif // LATINIME_DEFINES_H
|
||||||
|
|
|
@ -27,10 +27,8 @@ class Dictionary {
|
||||||
public:
|
public:
|
||||||
Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler,
|
Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler,
|
||||||
int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives);
|
int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives);
|
||||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
|
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies) {
|
||||||
int *nextLetters, int nextLettersSize) {
|
return mUnigramDictionary->getSuggestions(codes, codesSize, outWords, frequencies);
|
||||||
return mUnigramDictionary->getSuggestions(codes, codesSize, outWords, frequencies,
|
|
||||||
nextLetters, nextLettersSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Call mBigramDictionary instead of mUnigramDictionary
|
// TODO: Call mBigramDictionary instead of mUnigramDictionary
|
||||||
|
|
|
@ -42,7 +42,7 @@ UnigramDictionary::UnigramDictionary(const unsigned char *dict, int typedLetterM
|
||||||
UnigramDictionary::~UnigramDictionary() {}
|
UnigramDictionary::~UnigramDictionary() {}
|
||||||
|
|
||||||
int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWords,
|
int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWords,
|
||||||
int *frequencies, int *nextLetters, int nextLettersSize) {
|
int *frequencies) {
|
||||||
PROF_OPEN;
|
PROF_OPEN;
|
||||||
PROF_START(0);
|
PROF_START(0);
|
||||||
initSuggestions(codes, codesSize, outWords, frequencies);
|
initSuggestions(codes, codesSize, outWords, frequencies);
|
||||||
|
@ -52,7 +52,7 @@ int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short
|
||||||
PROF_END(0);
|
PROF_END(0);
|
||||||
|
|
||||||
PROF_START(1);
|
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_END(1);
|
||||||
|
|
||||||
PROF_START(2);
|
PROF_START(2);
|
||||||
|
@ -108,9 +108,9 @@ int UnigramDictionary::getSuggestions(int *codes, int codesSize, unsigned short
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("Returning %d words", suggestedWordsCount);
|
LOGI("Returning %d words", suggestedWordsCount);
|
||||||
LOGI("Next letters: ");
|
LOGI("Next letters: ");
|
||||||
for (int k = 0; k < nextLettersSize; k++) {
|
for (int k = 0; k < NEXT_LETTERS_SIZE; k++) {
|
||||||
if (nextLetters[k] > 0) {
|
if (mNextLettersFrequency[k] > 0) {
|
||||||
LOGI("%c = %d,", k, nextLetters[k]);
|
LOGI("%c = %d,", k, mNextLettersFrequency[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,7 @@ class UnigramDictionary {
|
||||||
public:
|
public:
|
||||||
UnigramDictionary(const unsigned char *dict, int typedLetterMultipler, int fullWordMultiplier,
|
UnigramDictionary(const unsigned char *dict, int typedLetterMultipler, int fullWordMultiplier,
|
||||||
int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion);
|
int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion);
|
||||||
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
|
int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies);
|
||||||
int *nextLetters, int nextLettersSize);
|
|
||||||
~UnigramDictionary();
|
~UnigramDictionary();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -109,6 +108,7 @@ private:
|
||||||
int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];
|
int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackDiffs[MAX_WORD_LENGTH_INTERNAL];
|
int mStackDiffs[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackSiblingPos[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);
|
mSuggest.getSuggestions(null, firstChar, previous);
|
||||||
boolean reloading = mUserBigram.reloadDictionaryIfRequired();
|
boolean reloading = mUserBigram.reloadDictionaryIfRequired();
|
||||||
if (reloading) mUserBigram.waitForDictionaryLoading();
|
if (reloading) mUserBigram.waitForDictionaryLoading();
|
||||||
mUserBigram.getBigrams(firstChar, previous, mSuggest, null);
|
mUserBigram.getBigrams(firstChar, previous, mSuggest);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mSuggest.mBigramSuggestions.size(); i++) {
|
for (int i = 0; i < mSuggest.mBigramSuggestions.size(); i++) {
|
||||||
|
|
Loading…
Reference in New Issue