Merge "Calculate proximity characters in the native code"

This commit is contained in:
satok 2012-03-16 01:38:07 -07:00 committed by Android (Google) Code Review
commit a50a34f8b4
4 changed files with 77 additions and 26 deletions

View file

@ -260,12 +260,19 @@ public class KeyDetector {
final int touchX = getTouchX(x); final int touchX = getTouchX(x);
final int touchY = getTouchY(y); final int touchY = getTouchY(y);
for (final Key key : mKeyboard.getNearestKeys(touchX, touchY)) { int minDistance = Integer.MAX_VALUE;
if (key.isOnKey(touchX, touchY)) { Key primaryKey = null;
return key; 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) { public static String printableCode(Key key) {

View file

@ -140,8 +140,8 @@ public class WordComposer {
keyX = x; keyX = x;
keyY = y; keyY = y;
} else { } else {
codes = keyDetector.newCodeArray(); final Key key = keyDetector.detectHitKey(x, y);
keyDetector.getNearbyCodes(x, y, codes); codes = new int[] { key != null ? key.mCode : NOT_A_CODE };
keyX = keyDetector.getTouchX(x); keyX = keyDetector.getTouchX(x);
keyY = keyDetector.getTouchY(y); keyY = keyDetector.getTouchY(y);
} }

View file

@ -55,6 +55,7 @@ ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximity
mTouchPositionCorrectionEnabled(false) { mTouchPositionCorrectionEnabled(false) {
const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
mProximityCharsArray = new int32_t[proximityGridLength]; mProximityCharsArray = new int32_t[proximityGridLength];
mInputCodes = new int32_t[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL];
if (DEBUG_PROXIMITY_INFO) { if (DEBUG_PROXIMITY_INFO) {
AKLOGI("Create proximity info array %d", proximityGridLength); AKLOGI("Create proximity info array %d", proximityGridLength);
} }
@ -96,6 +97,7 @@ void ProximityInfo::initializeCodeToKeyIndex() {
ProximityInfo::~ProximityInfo() { ProximityInfo::~ProximityInfo() {
delete[] mNormalizedSquaredDistances; delete[] mNormalizedSquaredDistances;
delete[] mProximityCharsArray; delete[] mProximityCharsArray;
delete[] mInputCodes;
} }
inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const { 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) { int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) {
const int left = mKeyXCoordinates[keyId]; const int left = mKeyXCoordinates[keyId];
const int top = mKeyYCoordinates[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 bottom = top + mKeyHeights[keyId];
const int edgeX = x < left ? left : (x > right ? right : x); const int edgeX = x < left ? left : (x > right ? right : x);
const int edgeY = y < top ? top : (y > bottom ? bottom : y); const int edgeY = y < top ? top : (y > bottom ? bottom : y);
@ -157,10 +159,10 @@ void ProximityInfo::calculateNearbyKeyCodes(
if (c < KEYCODE_SPACE || c == primaryKey) { if (c < KEYCODE_SPACE || c == primaryKey) {
continue; continue;
} }
int keyIndex = getKeyIndex(c); const int keyIndex = getKeyIndex(c);
const bool onKey = isOnKey(keyIndex, x, y); const bool onKey = isOnKey(keyIndex, x, y);
const int distance = squaredDistanceToEdge(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; inputCodes[insertPos++] = c;
if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
if (DEBUG_DICT) { 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 = const int additionalProximitySize =
AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey); AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey);
if (additionalProximitySize > 0) { 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 = const int32_t* additionalProximityChars =
AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey); AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey);
for (int j = 0; j < additionalProximitySize; ++j) { for (int j = 0; j < additionalProximitySize; ++j) {
@ -204,13 +206,46 @@ void ProximityInfo::calculateNearbyKeyCodes(
} }
} }
// Add a delimiter for the proximity characters // 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. // 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) { 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; mInputXCoordinates = xCoordinates;
mInputYCoordinates = yCoordinates; mInputYCoordinates = yCoordinates;
mTouchPositionCorrectionEnabled = 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) { for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) {
const int currentChar = proximityChars[j]; const int currentChar = proximityChars[j];
const int keyIndex = getKeyIndex(currentChar); const float squaredDistance = hasInputCoordinates()
const float squaredDistance = calculateNormalizedSquaredDistance(keyIndex, i); ? calculateNormalizedSquaredDistance(getKeyIndex(currentChar), i)
: NOT_A_DISTANCE_FLOAT;
if (squaredDistance >= 0.0f) { if (squaredDistance >= 0.0f) {
mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
(int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); (int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
@ -267,7 +303,6 @@ inline float square(const float x) { return x * x; }
float ProximityInfo::calculateNormalizedSquaredDistance( float ProximityInfo::calculateNormalizedSquaredDistance(
const int keyIndex, const int inputIndex) const { const int keyIndex, const int inputIndex) const {
static const float NOT_A_DISTANCE_FLOAT = -1.0f;
if (keyIndex == NOT_A_INDEX) { if (keyIndex == NOT_A_INDEX) {
return NOT_A_DISTANCE_FLOAT; return NOT_A_DISTANCE_FLOAT;
} }
@ -282,8 +317,12 @@ float ProximityInfo::calculateNormalizedSquaredDistance(
return squaredDistance / squaredRadius; return squaredDistance / squaredRadius;
} }
bool ProximityInfo::hasInputCoordinates() const {
return mInputXCoordinates && mInputYCoordinates;
}
int ProximityInfo::getKeyIndex(const int c) const { int ProximityInfo::getKeyIndex(const int c) const {
if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) { if (KEY_COUNT == 0) {
// We do not have the coordinate data // We do not have the coordinate data
return NOT_A_INDEX; return NOT_A_INDEX;
} }

View file

@ -53,7 +53,7 @@ class ProximityInfo {
const float *sweetSpotCenterYs, const float *sweetSpotRadii); const float *sweetSpotCenterYs, const float *sweetSpotRadii);
~ProximityInfo(); ~ProximityInfo();
bool hasSpaceProximity(const int x, const int y) const; 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 *xCoordinates, const int *yCoordinates);
const int* getProximityCharsAt(const int index) const; const int* getProximityCharsAt(const int index) const;
unsigned short getPrimaryCharAt(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; static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64;
// The upper limit of the char code in mCodeToKeyIndex // The upper limit of the char code in mCodeToKeyIndex
static const int MAX_CHAR_CODE = 127; 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; int getStartIndexFromCoordinates(const int x, const int y) const;
void initializeCodeToKeyIndex(); void initializeCodeToKeyIndex();
float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
float calculateSquaredDistanceFromSweetSpotCenter( float calculateSquaredDistanceFromSweetSpotCenter(
const int keyIndex, const int inputIndex) const; const int keyIndex, const int inputIndex) const;
bool hasInputCoordinates() const;
int getKeyIndex(const int c) const; int getKeyIndex(const int c) const;
bool hasSweetSpotData(const int keyIndex) const { bool hasSweetSpotData(const int keyIndex) const {
// When there are no calibration data for a key, // When there are no calibration data for a key,
@ -105,7 +108,9 @@ class ProximityInfo {
const int KEY_COUNT; const int KEY_COUNT;
const bool HAS_TOUCH_POSITION_CORRECTION_DATA; const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
const std::string mLocaleStr; const std::string mLocaleStr;
const int *mInputCodes; // TODO: remove this
const int *mInputCodesFromJava;
int32_t *mInputCodes;
const int *mInputXCoordinates; const int *mInputXCoordinates;
const int *mInputYCoordinates; const int *mInputYCoordinates;
bool mTouchPositionCorrectionEnabled; bool mTouchPositionCorrectionEnabled;