From 1caff47ecdfcf413df709371a919cf9377e26bf7 Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 14 Mar 2012 23:17:12 +0900 Subject: [PATCH] Calculate proximity characters in the native code Bug: 4343280 Change-Id: I6adaf560f7a4f1f96dcb6ec2f61f20ee3001167e --- .../inputmethod/keyboard/KeyDetector.java | 15 +++- .../inputmethod/latin/WordComposer.java | 4 +- native/src/proximity_info.cpp | 75 ++++++++++++++----- native/src/proximity_info.h | 9 ++- 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index ea3f6236a..d342c6df0 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -260,12 +260,19 @@ public class KeyDetector { final int touchX = getTouchX(x); final int touchY = getTouchY(y); - for (final Key key : mKeyboard.getNearestKeys(touchX, touchY)) { - if (key.isOnKey(touchX, touchY)) { - return key; + int minDistance = Integer.MAX_VALUE; + Key primaryKey = null; + for (final Key key: mKeyboard.getNearestKeys(touchX, touchY)) { + final boolean isOnKey = key.isOnKey(touchX, touchY); + final int distance = key.squaredDistanceToEdge(touchX, touchY); + // TODO: need to take care of hitbox overlaps + if (primaryKey == null || distance < minDistance + || (distance == minDistance && isOnKey)) { + minDistance = distance; + primaryKey = key; } } - return null; + return primaryKey; } public static String printableCode(Key key) { diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index a9609310c..251063ec4 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -140,8 +140,8 @@ public class WordComposer { keyX = x; keyY = y; } else { - codes = keyDetector.newCodeArray(); - keyDetector.getNearbyCodes(x, y, codes); + final Key key = keyDetector.detectHitKey(x, y); + codes = new int[] { key != null ? key.mCode : NOT_A_CODE }; keyX = keyDetector.getTouchX(x); keyY = keyDetector.getTouchY(y); } diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp index dd60ed62c..4d03f3274 100644 --- a/native/src/proximity_info.cpp +++ b/native/src/proximity_info.cpp @@ -55,6 +55,7 @@ ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximity mTouchPositionCorrectionEnabled(false) { const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; mProximityCharsArray = new int32_t[proximityGridLength]; + mInputCodes = new int32_t[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL]; if (DEBUG_PROXIMITY_INFO) { AKLOGI("Create proximity info array %d", proximityGridLength); } @@ -96,6 +97,7 @@ void ProximityInfo::initializeCodeToKeyIndex() { ProximityInfo::~ProximityInfo() { delete[] mNormalizedSquaredDistances; delete[] mProximityCharsArray; + delete[] mInputCodes; } inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const { @@ -138,7 +140,7 @@ bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) { int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) { const int left = mKeyXCoordinates[keyId]; const int top = mKeyYCoordinates[keyId]; - const int right = left + mKeyWidths[keyId] + 1; + const int right = left + mKeyWidths[keyId]; const int bottom = top + mKeyHeights[keyId]; const int edgeX = x < left ? left : (x > right ? right : x); const int edgeY = y < top ? top : (y > bottom ? bottom : y); @@ -157,10 +159,10 @@ void ProximityInfo::calculateNearbyKeyCodes( if (c < KEYCODE_SPACE || c == primaryKey) { continue; } - int keyIndex = getKeyIndex(c); + const int keyIndex = getKeyIndex(c); const bool onKey = isOnKey(keyIndex, x, y); const int distance = squaredDistanceToEdge(keyIndex, x, y); - if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) { + if (c >= KEYCODE_SPACE && (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE)) { inputCodes[insertPos++] = c; if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { if (DEBUG_DICT) { @@ -170,17 +172,17 @@ void ProximityInfo::calculateNearbyKeyCodes( } } } - inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; - if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { - if (DEBUG_DICT) { - assert(false); - } - return; - } - const int additionalProximitySize = AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey); if (additionalProximitySize > 0) { + inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { + if (DEBUG_DICT) { + assert(false); + } + return; + } + const int32_t* additionalProximityChars = AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey); for (int j = 0; j < additionalProximitySize; ++j) { @@ -204,13 +206,46 @@ void ProximityInfo::calculateNearbyKeyCodes( } } // Add a delimiter for the proximity characters - inputCodes[insertPos] = 0; + for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { + inputCodes[i] = NOT_A_CODE; + } } // TODO: Calculate nearby codes here. -void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, +void ProximityInfo::setInputParams(const int32_t* inputCodes, const int inputLength, const int* xCoordinates, const int* yCoordinates) { - mInputCodes = inputCodes; + memset(mInputCodes, 0, + MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE * sizeof(mInputCodes[0])); + + for (int i = 0; i < inputLength; ++i) { + const int32_t primaryKey = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE]; + const int x = xCoordinates[i]; + const int y = yCoordinates[i]; + int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE]; + calculateNearbyKeyCodes(x, y, primaryKey, proximities); + } + + if (DEBUG_PROXIMITY_CHARS) { + for (int i = 0; i < inputLength; ++i) { + AKLOGI("---"); + for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) { + int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j]; + int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j]; + icc+= 0; + icfjc += 0; + AKLOGI("--- (%d)%c,%c", i, icc, icfjc); + AKLOGI("--- A<%d>,B<%d>", icc, icfjc); + } + } + } + //Keep for debug, sorry + //for (int i = 0; i < MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE; ++i) { + //if (i < inputLength * MAX_PROXIMITY_CHARS_SIZE) { + //mInputCodes[i] = mInputCodesFromJava[i]; + //} else { + // mInputCodes[i] = 0; + // } + //} mInputXCoordinates = xCoordinates; mInputYCoordinates = yCoordinates; mTouchPositionCorrectionEnabled = @@ -246,8 +281,9 @@ void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, } for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) { const int currentChar = proximityChars[j]; - const int keyIndex = getKeyIndex(currentChar); - const float squaredDistance = calculateNormalizedSquaredDistance(keyIndex, i); + const float squaredDistance = hasInputCoordinates() + ? calculateNormalizedSquaredDistance(getKeyIndex(currentChar), i) + : NOT_A_DISTANCE_FLOAT; if (squaredDistance >= 0.0f) { mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = (int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); @@ -267,7 +303,6 @@ inline float square(const float x) { return x * x; } float ProximityInfo::calculateNormalizedSquaredDistance( const int keyIndex, const int inputIndex) const { - static const float NOT_A_DISTANCE_FLOAT = -1.0f; if (keyIndex == NOT_A_INDEX) { return NOT_A_DISTANCE_FLOAT; } @@ -282,8 +317,12 @@ float ProximityInfo::calculateNormalizedSquaredDistance( return squaredDistance / squaredRadius; } +bool ProximityInfo::hasInputCoordinates() const { + return mInputXCoordinates && mInputYCoordinates; +} + int ProximityInfo::getKeyIndex(const int c) const { - if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) { + if (KEY_COUNT == 0) { // We do not have the coordinate data return NOT_A_INDEX; } diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h index 1a47aff84..cdc5a3d43 100644 --- a/native/src/proximity_info.h +++ b/native/src/proximity_info.h @@ -53,7 +53,7 @@ class ProximityInfo { const float *sweetSpotCenterYs, const float *sweetSpotRadii); ~ProximityInfo(); bool hasSpaceProximity(const int x, const int y) const; - void setInputParams(const int *inputCodes, const int inputLength, + void setInputParams(const int32_t *inputCodes, const int inputLength, const int *xCoordinates, const int *yCoordinates); const int* getProximityCharsAt(const int index) const; unsigned short getPrimaryCharAt(const int index) const; @@ -77,12 +77,15 @@ class ProximityInfo { static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64; // The upper limit of the char code in mCodeToKeyIndex static const int MAX_CHAR_CODE = 127; + static const float NOT_A_DISTANCE_FLOAT = -1.0f; + static const int NOT_A_CODE = -1; int getStartIndexFromCoordinates(const int x, const int y) const; void initializeCodeToKeyIndex(); float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; + bool hasInputCoordinates() const; int getKeyIndex(const int c) const; bool hasSweetSpotData(const int keyIndex) const { // When there are no calibration data for a key, @@ -105,7 +108,9 @@ class ProximityInfo { const int KEY_COUNT; const bool HAS_TOUCH_POSITION_CORRECTION_DATA; const std::string mLocaleStr; - const int *mInputCodes; + // TODO: remove this + const int *mInputCodesFromJava; + int32_t *mInputCodes; const int *mInputXCoordinates; const int *mInputYCoordinates; bool mTouchPositionCorrectionEnabled;