Refactor proximity info

Change-Id: I96a4eb5cbdb3b2a402e286ac2aff36c3a52482ff
main
Satoshi Kataoka 2013-01-17 19:46:12 +09:00
parent 5a6b4f953e
commit bf78e1371c
6 changed files with 223 additions and 146 deletions

View File

@ -45,7 +45,7 @@ class AdditionalProximityChars {
} }
public: public:
static int getAdditionalCharsSize(const char *localeStr, const int c) { static int getAdditionalCharsSize(const char *const localeStr, const int c) {
if (!isEnLocale(localeStr)) { if (!isEnLocale(localeStr)) {
return 0; return 0;
} }
@ -65,7 +65,7 @@ class AdditionalProximityChars {
} }
} }
static const int *getAdditionalChars(const char *localeStr, const int c) { static const int *getAdditionalChars(const char *const localeStr, const int c) {
if (!isEnLocale(localeStr)) { if (!isEnLocale(localeStr)) {
return 0; return 0;
} }

View File

@ -94,11 +94,6 @@ ProximityInfo::~ProximityInfo() {
delete[] mProximityCharsArray; delete[] mProximityCharsArray;
} }
inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
return ((y / CELL_HEIGHT) * GRID_WIDTH + (x / CELL_WIDTH))
* MAX_PROXIMITY_CHARS_SIZE;
}
bool ProximityInfo::hasSpaceProximity(const int x, const int y) const { bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
if (x < 0 || y < 0) { if (x < 0 || y < 0) {
if (DEBUG_DICT) { if (DEBUG_DICT) {
@ -109,7 +104,8 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
return false; return false;
} }
const int startIndex = getStartIndexFromCoordinates(x, y); const int startIndex = ProximityInfoUtils::getStartIndexFromCoordinates(
MAX_PROXIMITY_CHARS_SIZE, x, y, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH);
if (DEBUG_PROXIMITY_INFO) { if (DEBUG_PROXIMITY_INFO) {
AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y); AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
} }
@ -147,100 +143,6 @@ float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
return getSquaredDistanceFloat(centerX, centerY, touchX, touchY) / SQUARE_FLOAT(keyWidth); return getSquaredDistanceFloat(centerX, centerY, touchX, touchY) / SQUARE_FLOAT(keyWidth);
} }
int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) const {
if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
const int left = mKeyXCoordinates[keyId];
const int top = mKeyYCoordinates[keyId];
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);
const int dx = x - edgeX;
const int dy = y - edgeY;
return dx * dx + dy * dy;
}
void ProximityInfo::calculateNearbyKeyCodes(
const int x, const int y, const int primaryKey, int *inputCodes) const {
int *proximityCharsArray = mProximityCharsArray;
int insertPos = 0;
inputCodes[insertPos++] = primaryKey;
const int startIndex = getStartIndexFromCoordinates(x, y);
if (startIndex >= 0) {
for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
const int c = proximityCharsArray[startIndex + i];
if (c < KEYCODE_SPACE || c == primaryKey) {
continue;
}
const int keyIndex = getKeyIndexOf(c);
const bool onKey = isOnKey(keyIndex, x, y);
const int distance = squaredDistanceToEdge(keyIndex, x, y);
if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) {
inputCodes[insertPos++] = c;
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 int *additionalProximityChars =
AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey);
for (int j = 0; j < additionalProximitySize; ++j) {
const int ac = additionalProximityChars[j];
int k = 0;
for (; k < insertPos; ++k) {
if (ac == inputCodes[k]) {
break;
}
}
if (k < insertPos) {
continue;
}
inputCodes[insertPos++] = ac;
if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
if (DEBUG_DICT) {
ASSERT(false);
}
return;
}
}
}
}
// Add a delimiter for the proximity characters
for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
inputCodes[i] = NOT_A_CODE_POINT;
}
}
int ProximityInfo::getKeyIndexOf(const int c) const {
if (KEY_COUNT == 0) {
// We do not have the coordinate data
return NOT_AN_INDEX;
}
if (c == NOT_A_CODE_POINT) {
return NOT_AN_INDEX;
}
const int lowerCode = toLowerCase(c);
hash_map_compat<int, int>::const_iterator mapPos = mCodeToKeyMap.find(lowerCode);
if (mapPos != mCodeToKeyMap.end()) {
return mapPos->second;
}
return NOT_AN_INDEX;
}
int ProximityInfo::getCodePointOf(const int keyIndex) const { int ProximityInfo::getCodePointOf(const int keyIndex) const {
if (keyIndex < 0 || keyIndex >= KEY_COUNT) { if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
return NOT_A_CODE_POINT; return NOT_A_CODE_POINT;
@ -269,11 +171,13 @@ void ProximityInfo::initializeG() {
} }
int ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const { int ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const {
return getKeyCenterXOfKeyIdG(getKeyIndexOf(charCode)); return getKeyCenterXOfKeyIdG(
ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
} }
int ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const { int ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const {
return getKeyCenterYOfKeyIdG(getKeyIndexOf(charCode)); return getKeyCenterYOfKeyIdG(
ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
} }
int ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const { int ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const {

View File

@ -20,6 +20,7 @@
#include "defines.h" #include "defines.h"
#include "hash_map_compat.h" #include "hash_map_compat.h"
#include "jni.h" #include "jni.h"
#include "proximity_info_utils.h"
namespace latinime { namespace latinime {
@ -40,7 +41,6 @@ class ProximityInfo {
float getNormalizedSquaredDistanceFromCenterFloatG( float getNormalizedSquaredDistanceFromCenterFloatG(
const int keyId, const int x, const int y) const; const int keyId, const int x, const int y) const;
bool sameAsTyped(const unsigned short *word, int length) const; bool sameAsTyped(const unsigned short *word, int length) const;
int getKeyIndexOf(const int c) const;
int getCodePointOf(const int keyIndex) const; int getCodePointOf(const int keyIndex) 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,
@ -109,23 +109,26 @@ class ProximityInfo {
int getKeyCenterYOfKeyIdG(int keyId) const; int getKeyCenterYOfKeyIdG(int keyId) const;
int getKeyKeyDistanceG(int keyId0, int keyId1) const; int getKeyKeyDistanceG(int keyId0, int keyId1) const;
void initializeProximities(const int *const inputCodes, const int *const inputXCoordinates,
const int *const inputYCoordinates, const int inputSize, int *allInputCodes) const {
ProximityInfoUtils::initializeProximities(inputCodes, inputXCoordinates, inputYCoordinates,
inputSize, mKeyXCoordinates, mKeyYCoordinates, mKeyWidths, mKeyHeights,
mProximityCharsArray, MAX_PROXIMITY_CHARS_SIZE, CELL_HEIGHT, CELL_WIDTH,
GRID_WIDTH, MOST_COMMON_KEY_WIDTH, KEY_COUNT, mLocaleStr, &mCodeToKeyMap,
allInputCodes);
}
int getKeyIndexOf(const int c) const {
return ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, c, &mCodeToKeyMap);
}
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo); DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo);
static const float NOT_A_DISTANCE_FLOAT; static const float NOT_A_DISTANCE_FLOAT;
int getStartIndexFromCoordinates(const int x, const int y) const;
void initializeG(); void initializeG();
float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
bool hasInputCoordinates() const; bool hasInputCoordinates() const;
int squaredDistanceToEdge(const int keyId, const int x, const int y) const;
bool isOnKey(const int keyId, const int x, const int y) const {
if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
const int left = mKeyXCoordinates[keyId];
const int top = mKeyYCoordinates[keyId];
const int right = left + mKeyWidths[keyId] + 1;
const int bottom = top + mKeyHeights[keyId];
return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
}
const int MAX_PROXIMITY_CHARS_SIZE; const int MAX_PROXIMITY_CHARS_SIZE;
const int GRID_WIDTH; const int GRID_WIDTH;

View File

@ -53,33 +53,11 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mGridHeight = proximityInfo->getGridWidth(); mGridHeight = proximityInfo->getGridWidth();
mGridWidth = proximityInfo->getGridHeight(); mGridWidth = proximityInfo->getGridHeight();
memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mInputProximities, 0, sizeof(mInputProximities));
if (!isGeometric && pointerId == 0) { if (!isGeometric && pointerId == 0) {
// Initialize mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates,
// - mInputCodes inputSize, mInputProximities);
// - mNormalizedSquaredDistances
// TODO: Merge
for (int i = 0; i < inputSize; ++i) {
const int primaryKey = inputCodes[i];
const int x = xCoordinates[i];
const int y = yCoordinates[i];
int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL];
mProximityInfo->calculateNearbyKeyCodes(x, y, primaryKey, proximities);
}
if (DEBUG_PROXIMITY_CHARS) {
for (int i = 0; i < inputSize; ++i) {
AKLOGI("---");
for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) {
int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
icc += 0;
icfjc += 0;
AKLOGI("--- (%d)%c,%c", i, icc, icfjc); AKLOGI("--- A<%d>,B<%d>", icc, icfjc);
}
}
}
} }
/////////////////////// ///////////////////////

View File

@ -61,7 +61,7 @@ class ProximityInfoState {
mInputIndice(), mLengthCache(), mBeelineSpeedPercentiles(), mDistanceCache_G(), mInputIndice(), mLengthCache(), mBeelineSpeedPercentiles(), mDistanceCache_G(),
mSpeedRates(), mDirections(), mCharProbabilities(), mNearKeysVector(), mSpeedRates(), mDirections(), mCharProbabilities(), mNearKeysVector(),
mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) { mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) {
memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mInputProximities, 0, sizeof(mInputProximities));
memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
} }
@ -117,12 +117,12 @@ class ProximityInfoState {
if (length != mSampledInputSize) { if (length != mSampledInputSize) {
return false; return false;
} }
const int *inputCodes = mInputCodes; const int *inputProximities = mInputProximities;
while (length--) { while (length--) {
if (*inputCodes != *word) { if (*inputProximities != *word) {
return false; return false;
} }
inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL; inputProximities += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
word++; word++;
} }
return true; return true;
@ -229,7 +229,7 @@ class ProximityInfoState {
} }
inline const int *getProximityCodePointsAt(const int index) const { inline const int *getProximityCodePointsAt(const int index) const {
return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL); return mInputProximities + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
} }
float updateNearKeysDistances(const int x, const int y, float updateNearKeysDistances(const int x, const int y,
@ -289,7 +289,7 @@ class ProximityInfoState {
// inputs including the current input point. // inputs including the current input point.
std::vector<NearKeycodesSet> mSearchKeysVector; std::vector<NearKeycodesSet> mSearchKeysVector;
bool mTouchPositionCorrectionEnabled; bool mTouchPositionCorrectionEnabled;
int mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH]; int mInputProximities[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH];
int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH]; int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH];
int mSampledInputSize; int mSampledInputSize;
int mPrimaryInputWord[MAX_WORD_LENGTH]; int mPrimaryInputWord[MAX_WORD_LENGTH];

View File

@ -0,0 +1,192 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LATINIME_PROXIMITY_INFO_UTILS_H
#define LATINIME_PROXIMITY_INFO_UTILS_H
#include "additional_proximity_chars.h"
#include "char_utils.h"
#include "defines.h"
#include "hash_map_compat.h"
namespace latinime {
class ProximityInfoUtils {
public:
static int getKeyIndexOf(const int keyCount, const int c,
const hash_map_compat<int, int> *const codeToKeyMap) {
if (keyCount == 0) {
// We do not have the coordinate data
return NOT_AN_INDEX;
}
if (c == NOT_A_CODE_POINT) {
return NOT_AN_INDEX;
}
const int lowerCode = toLowerCase(c);
hash_map_compat<int, int>::const_iterator mapPos = codeToKeyMap->find(lowerCode);
if (mapPos != codeToKeyMap->end()) {
return mapPos->second;
}
return NOT_AN_INDEX;
}
static void initializeProximities(const int *const inputCodes,
const int *const inputXCoordinates, const int *const inputYCoordinates,
const int inputSize, const int *const keyXCoordinates,
const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
const int *const proximityCharsArray, const int maxProximityCharsSize,
const int cellHeight, const int cellWidth, const int gridWidth,
const int mostCommonKeyWidth, const int keyCount, const char *const localeStr,
const hash_map_compat<int, int> *const codeToKeyMap, int *inputProximities) {
// Initialize
// - mInputCodes
// - mNormalizedSquaredDistances
// TODO: Merge
for (int i = 0; i < inputSize; ++i) {
const int primaryKey = inputCodes[i];
const int x = inputXCoordinates[i];
const int y = inputYCoordinates[i];
int *proximities = &inputProximities[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL];
calculateProximities(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights,
proximityCharsArray, maxProximityCharsSize, cellHeight, cellWidth, gridWidth,
mostCommonKeyWidth, keyCount, x, y, primaryKey, localeStr, codeToKeyMap,
proximities);
}
if (DEBUG_PROXIMITY_CHARS) {
for (int i = 0; i < inputSize; ++i) {
AKLOGI("---");
for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) {
int proximityChar =
inputProximities[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
proximityChar += 0;
AKLOGI("--- (%d)%c", i, proximityChar);
}
}
}
}
AK_FORCE_INLINE static int getStartIndexFromCoordinates(const int maxProximityCharsSize,
const int x, const int y, const int cellHeight, const int cellWidth,
const int gridWidth) {
return ((y / cellHeight) * gridWidth + (x / cellWidth)) * maxProximityCharsSize;
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoUtils);
static bool isOnKey(const int *const keyXCoordinates, const int *const keyYCoordinates,
const int *const keyWidths, const int *keyHeights, const int keyId, const int x,
const int y) {
if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
const int left = keyXCoordinates[keyId];
const int top = keyYCoordinates[keyId];
const int right = left + keyWidths[keyId] + 1;
const int bottom = top + keyHeights[keyId];
return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
}
static void calculateProximities(
const int *const keyXCoordinates, const int *const keyYCoordinates,
const int *const keyWidths, const int *keyHeights,
const int *const proximityCharsArray,
const int maxProximityCharsSize, const int cellHeight, const int cellWidth,
const int gridWidth, const int mostCommonKeyWidth, const int keyCount,
const int x, const int y, const int primaryKey, const char *const localeStr,
const hash_map_compat<int, int> *const codeToKeyMap, int *proximities) {
const int mostCommonKeyWidthSquare = mostCommonKeyWidth * mostCommonKeyWidth;
int insertPos = 0;
proximities[insertPos++] = primaryKey;
const int startIndex = getStartIndexFromCoordinates(
maxProximityCharsSize, x, y, cellHeight, cellWidth, gridWidth);
if (startIndex >= 0) {
for (int i = 0; i < maxProximityCharsSize; ++i) {
const int c = proximityCharsArray[startIndex + i];
if (c < KEYCODE_SPACE || c == primaryKey) {
continue;
}
const int keyIndex = getKeyIndexOf(keyCount, c, codeToKeyMap);
const bool onKey = isOnKey(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights,
keyIndex, x, y);
const int distance = squaredLengthToEdge(keyXCoordinates, keyYCoordinates,
keyWidths, keyHeights, keyIndex, x, y);
if (onKey || distance < mostCommonKeyWidthSquare) {
proximities[insertPos++] = c;
if (insertPos >= maxProximityCharsSize) {
if (DEBUG_DICT) {
ASSERT(false);
}
return;
}
}
}
const int additionalProximitySize =
AdditionalProximityChars::getAdditionalCharsSize(localeStr, primaryKey);
if (additionalProximitySize > 0) {
proximities[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
if (insertPos >= maxProximityCharsSize) {
if (DEBUG_DICT) {
ASSERT(false);
}
return;
}
const int *additionalProximityChars =
AdditionalProximityChars::getAdditionalChars(localeStr, primaryKey);
for (int j = 0; j < additionalProximitySize; ++j) {
const int ac = additionalProximityChars[j];
int k = 0;
for (; k < insertPos; ++k) {
if (ac == proximities[k]) {
break;
}
}
if (k < insertPos) {
continue;
}
proximities[insertPos++] = ac;
if (insertPos >= maxProximityCharsSize) {
if (DEBUG_DICT) {
ASSERT(false);
}
return;
}
}
}
}
// Add a delimiter for the proximity characters
for (int i = insertPos; i < maxProximityCharsSize; ++i) {
proximities[i] = NOT_A_CODE_POINT;
}
}
static int squaredLengthToEdge(const int *const keyXCoordinates,
const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
const int keyId, const int x, const int y) {
// NOT_A_ID is -1, but return whenever < 0 just in case
if (keyId < 0) return MAX_POINT_TO_KEY_LENGTH;
const int left = keyXCoordinates[keyId];
const int top = keyYCoordinates[keyId];
const int right = left + keyWidths[keyId];
const int bottom = top + keyHeights[keyId];
const int edgeX = x < left ? left : (x > right ? right : x);
const int edgeY = y < top ? top : (y > bottom ? bottom : y);
const int dx = x - edgeX;
const int dy = y - edgeY;
return dx * dx + dy * dy;
}
};
} // namespace latinime
#endif // LATINIME_PROXIMITY_INFO_UTILS_H