Loading java/src/com/android/inputmethod/keyboard/KeyDetector.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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) Loading java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +0 −6 Original line number Diff line number Diff line Loading @@ -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) Loading java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +4 −112 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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 Loading @@ -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) { Loading @@ -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; Loading java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java +9 −9 Original line number Diff line number Diff line Loading @@ -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; } } java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java +79 −22 Original line number Diff line number Diff line Loading @@ -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)); } } Loading Loading
java/src/com/android/inputmethod/keyboard/KeyDetector.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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) Loading
java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +0 −6 Original line number Diff line number Diff line Loading @@ -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) Loading
java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +4 −112 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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 Loading @@ -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) { Loading @@ -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; Loading
java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java +9 −9 Original line number Diff line number Diff line Loading @@ -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; } }
java/src/com/android/inputmethod/keyboard/ProximityKeyDetector.java +79 −22 Original line number Diff line number Diff line Loading @@ -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)); } } Loading