am bf78e137: Refactor proximity info
* commit 'bf78e1371c12d819020d60f0e585f5e6c26e6aa2': Refactor proximity infomain
commit
4e3c7cf0ef
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue