diff options
author | 2012-01-31 17:15:43 +0900 | |
---|---|---|
committer | 2012-02-02 16:07:16 +0900 | |
commit | e05b3f4b3a57dcf99ade35bfbc1e1cdc3c3e476c (patch) | |
tree | f84b7084220c6f08f6b825655d1c51832b436755 /java/src | |
parent | 8ca325f437a4dd6484e14ac66415b792195dbd40 (diff) | |
download | latinime-e05b3f4b3a57dcf99ade35bfbc1e1cdc3c3e476c.tar.gz latinime-e05b3f4b3a57dcf99ade35bfbc1e1cdc3c3e476c.tar.xz latinime-e05b3f4b3a57dcf99ade35bfbc1e1cdc3c3e476c.zip |
Support additional proximity characters
Change-Id: Ifbe0d7e4eafea1926bbce968eae4724dd5769689
Diffstat (limited to 'java/src')
4 files changed, 115 insertions, 16 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 0d271625b..bff491ffd 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -19,12 +19,14 @@ package com.android.inputmethod.keyboard; import android.util.Log; import java.util.Arrays; +import java.util.List; public class KeyDetector { private static final String TAG = KeyDetector.class.getSimpleName(); private static final boolean DEBUG = false; public static final int NOT_A_CODE = -1; + private static final int ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE = 2; private final int mKeyHysteresisDistanceSquared; @@ -154,8 +156,9 @@ public class KeyDetector { return distances.length; } - private void getNearbyKeyCodes(final int[] allCodes) { + private void getNearbyKeyCodes(final int primaryCode, final int[] allCodes) { final Key[] neighborKeys = mNeighborKeys; + final int maxCodesSize = allCodes.length; // allCodes[0] should always have the key code even if it is a non-letter key. if (neighborKeys[0] == null) { @@ -164,7 +167,7 @@ public class KeyDetector { } int numCodes = 0; - for (int j = 0; j < neighborKeys.length && numCodes < allCodes.length; j++) { + for (int j = 0; j < neighborKeys.length && numCodes < maxCodesSize; j++) { final Key key = neighborKeys[j]; if (key == null) break; @@ -174,6 +177,38 @@ public class KeyDetector { continue; allCodes[numCodes++] = code; } + if (maxCodesSize <= numCodes) { + return; + } + if (primaryCode != NOT_A_CODE) { + final List<Integer> additionalChars = + mKeyboard.getAdditionalProximityChars().get(primaryCode); + if (additionalChars == null || additionalChars.size() == 0) { + return; + } + int currentCodesSize = numCodes; + allCodes[numCodes++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (maxCodesSize <= numCodes) { + return; + } + // TODO: This is O(N^2). Assuming additionalChars.size() is up to 4 or 5. + for (int i = 0; i < additionalChars.size(); ++i) { + final int additionalChar = additionalChars.get(i); + boolean contains = false; + for (int j = 0; j < currentCodesSize; ++j) { + if (additionalChar == allCodes[j]) { + contains = true; + break; + } + } + if (!contains) { + allCodes[numCodes++] = additionalChar; + if (maxCodesSize <= numCodes) { + return; + } + } + } + } } /** @@ -205,7 +240,7 @@ public class KeyDetector { } if (allCodes != null && allCodes.length > 0) { - getNearbyKeyCodes(allCodes); + getNearbyKeyCodes(primaryKey != null ? primaryKey.mCode : NOT_A_CODE, allCodes); if (DEBUG) { Log.d(TAG, "x=" + x + " y=" + y + " primary=" + printableCode(primaryKey) diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 6653dec4b..10e0a5b01 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; @@ -38,10 +39,12 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -130,6 +133,8 @@ public class Keyboard { private final ProximityInfo mProximityInfo; + public final Map<Integer, List<Integer>> mAdditionalProximityChars; + public Keyboard(Params params) { mId = params.mId; mThemeId = params.mThemeId; @@ -146,10 +151,12 @@ public class Keyboard { mKeys = Collections.unmodifiableSet(params.mKeys); mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys); mIconsSet = params.mIconsSet; + mAdditionalProximityChars = params.mAdditionalProximityChars; mProximityInfo = new ProximityInfo( params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, - mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection); + mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection, + params.mAdditionalProximityChars); } public ProximityInfo getProximityInfo() { @@ -227,6 +234,9 @@ public class Keyboard { public final Set<Key> mKeys = new HashSet<Key>(); public final Set<Key> mShiftKeys = new HashSet<Key>(); public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); + // TODO: Should be in Key instead of Keyboard.Params? + public final Map<Integer, List<Integer>> mAdditionalProximityChars = + new HashMap<Integer, List<Integer>>(); public KeyboardSet.KeysCache mKeysCache; @@ -358,6 +368,10 @@ public class Keyboard { return mProximityInfo.getNearestKeys(adjustedX, adjustedY); } + public Map<Integer, List<Integer>> getAdditionalProximityChars() { + return mAdditionalProximityChars; + } + public static String printableCode(int code) { switch (code) { case CODE_SHIFT: return "shift"; @@ -614,6 +628,7 @@ public class Keyboard { mParams = params; setTouchPositionCorrectionData(context, params); + setAdditionalProximityChars(context, params); params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); @@ -636,6 +651,25 @@ public class Keyboard { params.mTouchPositionCorrection.load(data); } + private static void setAdditionalProximityChars(Context context, Params params) { + final String[] additionalChars = + context.getResources().getStringArray(R.array.additional_proximitychars); + int currentPrimaryIndex = 0; + for (int i = 0; i < additionalChars.length; ++i) { + final String additionalChar = additionalChars[i]; + if (TextUtils.isEmpty(additionalChar)) { + currentPrimaryIndex = 0; + } else if (currentPrimaryIndex == 0) { + currentPrimaryIndex = additionalChar.charAt(0); + params.mAdditionalProximityChars.put( + currentPrimaryIndex, new ArrayList<Integer>()); + } else if (currentPrimaryIndex != 0) { + final int c = additionalChar.charAt(0); + params.mAdditionalProximityChars.get(currentPrimaryIndex).add(c); + } + } + } + public void setAutoGenerate(KeyboardSet.KeysCache keysCache) { mParams.mKeysCache = keysCache; } diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index c1dae0601..2d1a0083d 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -24,6 +24,9 @@ import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Set; public class ProximityInfo { @@ -44,7 +47,8 @@ public class ProximityInfo { private final Key[][] mGridNeighbors; ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, - int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection) { + int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection, + Map<Integer, List<Integer>> additionalProximityChars) { mGridWidth = gridWidth; mGridHeight = gridHeight; mGridSize = mGridWidth * mGridHeight; @@ -58,20 +62,20 @@ public class ProximityInfo { // No proximity required. Keyboard might be mini keyboard. return; } - computeNearestNeighbors(keyWidth, keys, touchPositionCorrection); + computeNearestNeighbors(keyWidth, keys, touchPositionCorrection, additionalProximityChars); } public static ProximityInfo createDummyProximityInfo() { - return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptySet(), null); + return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key> emptySet(), + null, Collections.<Integer, List<Integer>> emptyMap()); } public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) { final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo(); spellCheckerProximityInfo.mNativeProximityInfo = spellCheckerProximityInfo.setProximityInfoNative( - SpellCheckerProximityInfo.ROW_SIZE, - 480, 300, 11, 3, proximity, - 0, null, null, null, null, null, null, null, null); + SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, proximity, 0, + null, null, null, null, null, null, null, null); return spellCheckerProximityInfo; } @@ -79,11 +83,13 @@ public class ProximityInfo { static { Utils.loadNativeLibrary(); } + private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth, int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray, int keyCount, int[] keyXCoordinates, int[] keyYCoordinates, int[] keyWidths, int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii); + private native void releaseProximityInfoNative(long nativeProximityInfo); private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth, @@ -138,7 +144,7 @@ public class ProximityInfo { final float radius = touchPositionCorrection.mRadii[row]; sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth; sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight; - sweetSpotRadii[i] = radius * (float)Math.sqrt( + sweetSpotRadii[i] = radius * (float) Math.sqrt( hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); } } @@ -168,7 +174,12 @@ public class ProximityInfo { } private void computeNearestNeighbors(int defaultWidth, Set<Key> keys, - TouchPositionCorrection touchPositionCorrection) { + TouchPositionCorrection touchPositionCorrection, + Map<Integer, List<Integer>> additionalProximityChars) { + final Map<Integer, Key> keyCodeMap = new HashMap<Integer, Key>(); + for (final Key key : keys) { + keyCodeMap.put(key.mCode, key); + } final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE); final int threshold = thresholdBase * thresholdBase; // Round-up so we don't have any pixels outside the grid @@ -186,6 +197,27 @@ public class ProximityInfo { neighborKeys[count++] = key; } } + int currentCodesSize = count; + for (int i = 0; i < currentCodesSize; ++i) { + final int c = neighborKeys[i].mCode; + final List<Integer> additionalChars = additionalProximityChars.get(c); + if (additionalChars == null || additionalChars.size() == 0) { + continue; + } + for (int j = 0; j < additionalChars.size(); ++j) { + final int additionalChar = additionalChars.get(j); + boolean contains = false; + for (int k = 0; k < count; ++k) { + if(additionalChar == neighborKeys[k].mCode) { + contains = true; + break; + } + } + if (!contains) { + neighborKeys[count++] = keyCodeMap.get(additionalChar); + } + } + } mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = Arrays.copyOfRange(neighborKeys, 0, count); } @@ -199,7 +231,7 @@ public class ProximityInfo { return EMPTY_KEY_ARRAY; } if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) { - int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth); + int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth); if (index < mGridSize) { return mGridNeighbors[index]; } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 230c2916b..bd244b913 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -16,8 +16,6 @@ package com.android.inputmethod.latin; -import android.text.TextUtils; - import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; @@ -33,7 +31,7 @@ public class WordComposer { public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE; public static final int NOT_A_COORDINATE = -1; - final int N = BinaryDictionary.MAX_WORD_LENGTH; + final static int N = BinaryDictionary.MAX_WORD_LENGTH; private ArrayList<int[]> mCodes; private int[] mXCoordinates; |