Promote touches in hit box according to the distance from sweet spot
Change-Id: Ice0fd0514304a79aed67627c2ea3439bd5177de4main
parent
a62a022ea7
commit
e4ba822cc6
|
@ -118,9 +118,8 @@ bool Correction::initProcessState(const int outputIndex) {
|
||||||
mInputIndex = mCorrectionStates[outputIndex].mInputIndex;
|
mInputIndex = mCorrectionStates[outputIndex].mInputIndex;
|
||||||
mNeedsToTraverseAllNodes = mCorrectionStates[outputIndex].mNeedsToTraverseAllNodes;
|
mNeedsToTraverseAllNodes = mCorrectionStates[outputIndex].mNeedsToTraverseAllNodes;
|
||||||
|
|
||||||
mEquivalentCharStrongCount = mCorrectionStates[outputIndex].mEquivalentCharStrongCount;
|
mSumOfDistance = mCorrectionStates[outputIndex].mSumOfDistance;
|
||||||
mEquivalentCharNormalCount = mCorrectionStates[outputIndex].mEquivalentCharNormalCount;
|
mEquivalentCharCount = mCorrectionStates[outputIndex].mEquivalentCharCount;
|
||||||
mEquivalentCharWeakCount = mCorrectionStates[outputIndex].mEquivalentCharWeakCount;
|
|
||||||
mProximityCount = mCorrectionStates[outputIndex].mProximityCount;
|
mProximityCount = mCorrectionStates[outputIndex].mProximityCount;
|
||||||
mTransposedCount = mCorrectionStates[outputIndex].mTransposedCount;
|
mTransposedCount = mCorrectionStates[outputIndex].mTransposedCount;
|
||||||
mExcessiveCount = mCorrectionStates[outputIndex].mExcessiveCount;
|
mExcessiveCount = mCorrectionStates[outputIndex].mExcessiveCount;
|
||||||
|
@ -175,9 +174,8 @@ void Correction::incrementOutputIndex() {
|
||||||
mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex;
|
mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex;
|
||||||
mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes;
|
mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes;
|
||||||
|
|
||||||
mCorrectionStates[mOutputIndex].mEquivalentCharStrongCount = mEquivalentCharStrongCount;
|
mCorrectionStates[mOutputIndex].mSumOfDistance = mSumOfDistance;
|
||||||
mCorrectionStates[mOutputIndex].mEquivalentCharNormalCount = mEquivalentCharNormalCount;
|
mCorrectionStates[mOutputIndex].mEquivalentCharCount = mEquivalentCharCount;
|
||||||
mCorrectionStates[mOutputIndex].mEquivalentCharWeakCount = mEquivalentCharWeakCount;
|
|
||||||
mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount;
|
mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount;
|
||||||
mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount;
|
mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount;
|
||||||
mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount;
|
mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount;
|
||||||
|
@ -220,9 +218,7 @@ Correction::CorrectionType Correction::processSkipChar(
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isEquivalentChar(ProximityInfo::ProximityType type) {
|
inline bool isEquivalentChar(ProximityInfo::ProximityType type) {
|
||||||
// 'type ProximityInfo::EQUIVALENT_CHAR_WEAK' means that
|
return type == ProximityInfo::EQUIVALENT_CHAR;
|
||||||
// type == ..._WEAK or type == ..._NORMAL or type == ..._STRONG.
|
|
||||||
return type <= ProximityInfo::EQUIVALENT_CHAR_WEAK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Correction::CorrectionType Correction::processCharAndCalcState(
|
Correction::CorrectionType Correction::processCharAndCalcState(
|
||||||
|
@ -304,7 +300,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
|
||||||
// TODO: Change the limit if we'll allow two or more proximity chars with corrections
|
// TODO: Change the limit if we'll allow two or more proximity chars with corrections
|
||||||
const bool checkProximityChars = noCorrectionsHappenedSoFar || mProximityCount == 0;
|
const bool checkProximityChars = noCorrectionsHappenedSoFar || mProximityCount == 0;
|
||||||
const ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
|
const ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
|
||||||
? ProximityInfo::EQUIVALENT_CHAR_NORMAL
|
? ProximityInfo::EQUIVALENT_CHAR
|
||||||
: mProximityInfo->getMatchedProximityId(mInputIndex, c, checkProximityChars);
|
: mProximityInfo->getMatchedProximityId(mInputIndex, c, checkProximityChars);
|
||||||
|
|
||||||
if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
|
if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
|
||||||
|
@ -384,18 +380,14 @@ Correction::CorrectionType Correction::processCharAndCalcState(
|
||||||
mMatching = true;
|
mMatching = true;
|
||||||
} else if (isEquivalentChar(matchedProximityCharId)) {
|
} else if (isEquivalentChar(matchedProximityCharId)) {
|
||||||
mMatching = true;
|
mMatching = true;
|
||||||
switch (matchedProximityCharId) {
|
++mEquivalentCharCount;
|
||||||
case ProximityInfo::EQUIVALENT_CHAR_STRONG:
|
if (mSumOfDistance != NOT_A_DISTANCE) {
|
||||||
++mEquivalentCharStrongCount;
|
const int distance = mProximityInfo->getNormalizedSquaredDistance(mInputIndex);
|
||||||
break;
|
if (distance != NOT_A_DISTANCE) {
|
||||||
case ProximityInfo::EQUIVALENT_CHAR_NORMAL:
|
mSumOfDistance += distance;
|
||||||
++mEquivalentCharNormalCount;
|
} else {
|
||||||
break;
|
mSumOfDistance = NOT_A_DISTANCE;
|
||||||
case ProximityInfo::EQUIVALENT_CHAR_WEAK:
|
}
|
||||||
++mEquivalentCharWeakCount;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
} else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
|
} else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
|
||||||
mProximityMatching = true;
|
mProximityMatching = true;
|
||||||
|
@ -568,8 +560,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
|
||||||
const int transposedCount = correction->mTransposedCount / 2;
|
const int transposedCount = correction->mTransposedCount / 2;
|
||||||
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
|
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
|
||||||
const int proximityMatchedCount = correction->mProximityCount;
|
const int proximityMatchedCount = correction->mProximityCount;
|
||||||
const int equivalentCharStrongCount = correction->mEquivalentCharStrongCount;
|
const int mSumOfDistance = correction->mSumOfDistance;
|
||||||
const int equivalentCharWeakCount = correction->mEquivalentCharWeakCount;
|
const int mEquivalentCharCount = correction->mEquivalentCharCount;
|
||||||
const bool lastCharExceeded = correction->mLastCharExceeded;
|
const bool lastCharExceeded = correction->mLastCharExceeded;
|
||||||
const bool useFullEditDistance = correction->mUseFullEditDistance;
|
const bool useFullEditDistance = correction->mUseFullEditDistance;
|
||||||
const int outputLength = outputIndex + 1;
|
const int outputLength = outputIndex + 1;
|
||||||
|
@ -679,18 +671,37 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
|
||||||
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
|
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < equivalentCharStrongCount; ++i) {
|
if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES
|
||||||
if (DEBUG_DICT_FULL) {
|
&& mEquivalentCharCount > 0 && mSumOfDistance != NOT_A_DISTANCE) {
|
||||||
LOGI("equivalent char strong");
|
// Let (x, y) be the coordinate of a user's touch, and let c be a key.
|
||||||
}
|
// Assuming users' touch distribution is gauss distribution, the conditional probability of
|
||||||
multiplyRate(WORDS_WITH_EQUIVALENT_CHAR_STRONG_PROMOTION_RATE, &finalFreq);
|
// the user touching (x, y) given he or she intends to hit c is:
|
||||||
}
|
// p(x, y | c) = exp(-(x - m_x) / (2 * s^2)) / (sqrt(2 * pi) * s)
|
||||||
|
// * exp(-(y - m_y) / (2 * s^2)) / (sqrt(2 * pi) * s)
|
||||||
for (int i = 0; i < equivalentCharWeakCount; ++i) {
|
// where (m_x, m_y) is a mean of touches of c, and s is a variance of touches of c.
|
||||||
if (DEBUG_DICT_FULL) {
|
// If user touches c1, c2, .., cn, the joint distribution is
|
||||||
LOGI("equivalent char weak");
|
// p(x1, y1 | c1) * p(x2, y2 | c2) * ... * p(xn, yn | cn)
|
||||||
}
|
// We consider the logarithm of this value, that is
|
||||||
multiplyRate(WORDS_WITH_EQUIVALENT_CHAR_WEAK_DEMOTION_RATE, &finalFreq);
|
// sum_i log p(x_i, y_i | c_i) + const
|
||||||
|
// = sum_i ((x_i - m_x)^2 + (y_i - m_y)^2) / (2 * s^2) + const
|
||||||
|
// Thus, we use the sum of squared distance as a score of the word.
|
||||||
|
static const int UPPER = WORDS_WITH_EQUIVALENT_CHAR_STRONGEST_PROMOTION_RATE;
|
||||||
|
static const int LOWER = WORDS_WITH_EQUIVALENT_CHAR_WEAKEST_DEMOTION_RATE;
|
||||||
|
static const int MIDDLE = 100;
|
||||||
|
static const int SHIFT = ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||||
|
const int expected = mEquivalentCharCount << SHIFT;
|
||||||
|
// factor is a function as described below:
|
||||||
|
// U\ .
|
||||||
|
// \ .
|
||||||
|
// M \ .
|
||||||
|
// \ .
|
||||||
|
// L \------- .
|
||||||
|
// 0 e
|
||||||
|
// (x-axis is mSumOfDistance, y-axis is rate,
|
||||||
|
// and e, U, M, L are expected, UPPER, MIDDLE, LOWER respectively.
|
||||||
|
const int factor =
|
||||||
|
max((UPPER * expected - (UPPER - MIDDLE) * mSumOfDistance) / expected, LOWER);
|
||||||
|
multiplyRate(factor, &finalFreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int errorCount = adjustedProximityMatchedCount > 0
|
const int errorCount = adjustedProximityMatchedCount > 0
|
||||||
|
|
|
@ -127,9 +127,8 @@ private:
|
||||||
int mOutputIndex;
|
int mOutputIndex;
|
||||||
int mInputIndex;
|
int mInputIndex;
|
||||||
|
|
||||||
int mEquivalentCharStrongCount;
|
int mEquivalentCharCount;
|
||||||
int mEquivalentCharNormalCount;
|
int mSumOfDistance;
|
||||||
int mEquivalentCharWeakCount;
|
|
||||||
int mProximityCount;
|
int mProximityCount;
|
||||||
int mExcessiveCount;
|
int mExcessiveCount;
|
||||||
int mTransposedCount;
|
int mTransposedCount;
|
||||||
|
|
|
@ -29,9 +29,8 @@ struct CorrectionState {
|
||||||
uint16_t mChildCount;
|
uint16_t mChildCount;
|
||||||
uint8_t mInputIndex;
|
uint8_t mInputIndex;
|
||||||
|
|
||||||
uint8_t mEquivalentCharStrongCount;
|
int32_t mSumOfDistance;
|
||||||
uint8_t mEquivalentCharNormalCount;
|
uint8_t mEquivalentCharCount;
|
||||||
uint8_t mEquivalentCharWeakCount;
|
|
||||||
uint8_t mProximityCount;
|
uint8_t mProximityCount;
|
||||||
uint8_t mTransposedCount;
|
uint8_t mTransposedCount;
|
||||||
uint8_t mExcessiveCount;
|
uint8_t mExcessiveCount;
|
||||||
|
@ -66,9 +65,8 @@ inline static void initCorrectionState(CorrectionState *state, const int rootPos
|
||||||
state->mExcessivePos = -1;
|
state->mExcessivePos = -1;
|
||||||
state->mSkipPos = -1;
|
state->mSkipPos = -1;
|
||||||
|
|
||||||
state->mEquivalentCharStrongCount = 0;
|
state->mSumOfDistance = 0;
|
||||||
state->mEquivalentCharNormalCount = 0;
|
state->mEquivalentCharCount = 0;
|
||||||
state->mEquivalentCharWeakCount = 0;
|
|
||||||
state->mProximityCount = 0;
|
state->mProximityCount = 0;
|
||||||
state->mTransposedCount = 0;
|
state->mTransposedCount = 0;
|
||||||
state->mExcessiveCount = 0;
|
state->mExcessiveCount = 0;
|
||||||
|
|
|
@ -162,6 +162,7 @@ static void dumpWord(const unsigned short* word, const int length) {
|
||||||
#define NEW_DICTIONARY_HEADER_SIZE 5
|
#define NEW_DICTIONARY_HEADER_SIZE 5
|
||||||
#define NOT_VALID_WORD -99
|
#define NOT_VALID_WORD -99
|
||||||
#define NOT_A_CHARACTER -1
|
#define NOT_A_CHARACTER -1
|
||||||
|
#define NOT_A_DISTANCE -1
|
||||||
|
|
||||||
#define KEYCODE_SPACE ' '
|
#define KEYCODE_SPACE ' '
|
||||||
|
|
||||||
|
@ -180,8 +181,8 @@ static void dumpWord(const unsigned short* word, const int length) {
|
||||||
#define WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE 75
|
#define WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE 75
|
||||||
#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
|
#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
|
||||||
#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
|
#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
|
||||||
#define WORDS_WITH_EQUIVALENT_CHAR_STRONG_PROMOTION_RATE 105
|
#define WORDS_WITH_EQUIVALENT_CHAR_STRONGEST_PROMOTION_RATE 110
|
||||||
#define WORDS_WITH_EQUIVALENT_CHAR_WEAK_DEMOTION_RATE 95
|
#define WORDS_WITH_EQUIVALENT_CHAR_WEAKEST_DEMOTION_RATE 90
|
||||||
#define FULL_MATCHED_WORDS_PROMOTION_RATE 120
|
#define FULL_MATCHED_WORDS_PROMOTION_RATE 120
|
||||||
#define WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE 90
|
#define WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE 90
|
||||||
#define WORDS_WITH_MATCH_SKIP_PROMOTION_RATE 105
|
#define WORDS_WITH_MATCH_SKIP_PROMOTION_RATE 105
|
||||||
|
|
|
@ -115,41 +115,42 @@ void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength,
|
||||||
}
|
}
|
||||||
mPrimaryInputWord[inputLength] = 0;
|
mPrimaryInputWord[inputLength] = 0;
|
||||||
for (int i = 0; i < mInputLength; ++i) {
|
for (int i = 0; i < mInputLength; ++i) {
|
||||||
mSweetSpotTypes[i] = calculateSweetSpotType(i);
|
float normalizedSquaredDistance = calculateNormalizedSquaredDistance(i);
|
||||||
|
if (normalizedSquaredDistance >= 0.0f) {
|
||||||
|
mNormalizedSquaredDistance[i] =
|
||||||
|
(int)(normalizedSquaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
|
||||||
|
} else {
|
||||||
|
mNormalizedSquaredDistance[i] = NOT_A_DISTANCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float square(const float x) { return x * x; }
|
inline float square(const float x) { return x * x; }
|
||||||
|
|
||||||
ProximityInfo::SweetSpotType ProximityInfo::calculateSweetSpotType(int index) const {
|
float ProximityInfo::calculateNormalizedSquaredDistance(int index) const {
|
||||||
|
static const float NOT_A_DISTANCE_FLOAT = -1.0f;
|
||||||
if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) {
|
if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) {
|
||||||
// We do not have the coordinate data
|
// We do not have the coordinate data
|
||||||
return UNKNOWN;
|
return NOT_A_DISTANCE_FLOAT;
|
||||||
}
|
}
|
||||||
const int currentChar = getPrimaryCharAt(index);
|
const int currentChar = getPrimaryCharAt(index);
|
||||||
const unsigned short baseLowerC = Dictionary::toBaseLowerCase(currentChar);
|
const unsigned short baseLowerC = Dictionary::toBaseLowerCase(currentChar);
|
||||||
if (baseLowerC > MAX_CHAR_CODE) {
|
if (baseLowerC > MAX_CHAR_CODE) {
|
||||||
return UNKNOWN;
|
return NOT_A_DISTANCE_FLOAT;
|
||||||
}
|
}
|
||||||
const int keyIndex = mCodeToKeyIndex[baseLowerC];
|
const int keyIndex = mCodeToKeyIndex[baseLowerC];
|
||||||
if (keyIndex < 0) {
|
if (keyIndex < 0) {
|
||||||
return UNKNOWN;
|
return NOT_A_DISTANCE_FLOAT;
|
||||||
}
|
}
|
||||||
const float radius = mSweetSpotRadii[keyIndex];
|
const float radius = mSweetSpotRadii[keyIndex];
|
||||||
if (radius <= 0.0) {
|
if (radius <= 0.0) {
|
||||||
// When there are no calibration data for a key,
|
// When there are no calibration data for a key,
|
||||||
// the radius of the key is assigned to zero.
|
// the radius of the key is assigned to zero.
|
||||||
return UNKNOWN;
|
return NOT_A_DISTANCE;
|
||||||
}
|
}
|
||||||
const float squaredRadius = square(radius);
|
const float squaredRadius = square(radius);
|
||||||
const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(keyIndex, index);
|
const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(keyIndex, index);
|
||||||
if (squaredDistance <= squaredRadius) {
|
return squaredDistance / squaredRadius;
|
||||||
return IN_SWEET_SPOT;
|
|
||||||
}
|
|
||||||
if (squaredDistance <= square(NEUTRAL_AREA_RADIUS_RATIO) * squaredRadius) {
|
|
||||||
return IN_NEUTRAL_AREA;
|
|
||||||
}
|
|
||||||
return OUT_OF_NEUTRAL_AREA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float ProximityInfo::calculateSquaredDistanceFromSweetSpotCenter(
|
float ProximityInfo::calculateSquaredDistanceFromSweetSpotCenter(
|
||||||
|
@ -213,22 +214,7 @@ ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(
|
||||||
// The first char in the array is what user typed. If it matches right away,
|
// The first char in the array is what user typed. If it matches right away,
|
||||||
// that means the user typed that same char for this pos.
|
// that means the user typed that same char for this pos.
|
||||||
if (firstChar == baseLowerC || firstChar == c) {
|
if (firstChar == baseLowerC || firstChar == c) {
|
||||||
if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES) {
|
return EQUIVALENT_CHAR;
|
||||||
switch (mSweetSpotTypes[index]) {
|
|
||||||
case UNKNOWN:
|
|
||||||
return EQUIVALENT_CHAR_NORMAL;
|
|
||||||
case IN_SWEET_SPOT:
|
|
||||||
return EQUIVALENT_CHAR_STRONG;
|
|
||||||
case IN_NEUTRAL_AREA:
|
|
||||||
return EQUIVALENT_CHAR_NORMAL;
|
|
||||||
case OUT_OF_NEUTRAL_AREA:
|
|
||||||
return EQUIVALENT_CHAR_WEAK;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return EQUIVALENT_CHAR_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkProximityChars) return UNRELATED_CHAR;
|
if (!checkProximityChars) return UNRELATED_CHAR;
|
||||||
|
@ -266,6 +252,8 @@ bool ProximityInfo::sameAsTyped(const unsigned short *word, int length) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||||
|
const int ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
|
||||||
const int ProximityInfo::MAX_KEY_COUNT_IN_A_KEYBOARD;
|
const int ProximityInfo::MAX_KEY_COUNT_IN_A_KEYBOARD;
|
||||||
const int ProximityInfo::MAX_CHAR_CODE;
|
const int ProximityInfo::MAX_CHAR_CODE;
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,12 @@ class Correction;
|
||||||
|
|
||||||
class ProximityInfo {
|
class ProximityInfo {
|
||||||
public:
|
public:
|
||||||
|
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
|
||||||
|
|
||||||
// Used as a return value for character comparison
|
// Used as a return value for character comparison
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// Same char, possibly with different case or accent, and in the sweet spot of the char
|
// Same char, possibly with different case or accent
|
||||||
EQUIVALENT_CHAR_STRONG,
|
EQUIVALENT_CHAR,
|
||||||
// Same char, possibly with different case or accent, and in the outer sweet spot
|
|
||||||
EQUIVALENT_CHAR_NORMAL,
|
|
||||||
// Same char, possibly with different case or accent, and in the hit box of the char
|
|
||||||
EQUIVALENT_CHAR_WEAK,
|
|
||||||
// It is a char located nearby on the keyboard
|
// It is a char located nearby on the keyboard
|
||||||
NEAR_PROXIMITY_CHAR,
|
NEAR_PROXIMITY_CHAR,
|
||||||
// It is an unrelated char
|
// It is an unrelated char
|
||||||
|
@ -57,31 +55,25 @@ public:
|
||||||
bool existsAdjacentProximityChars(const int index) const;
|
bool existsAdjacentProximityChars(const int index) const;
|
||||||
ProximityType getMatchedProximityId(
|
ProximityType getMatchedProximityId(
|
||||||
const int index, const unsigned short c, const bool checkProximityChars) const;
|
const int index, const unsigned short c, const bool checkProximityChars) const;
|
||||||
|
int getNormalizedSquaredDistance(int index) const {
|
||||||
|
return mNormalizedSquaredDistance[index];
|
||||||
|
}
|
||||||
bool sameAsTyped(const unsigned short *word, int length) const;
|
bool sameAsTyped(const unsigned short *word, int length) const;
|
||||||
const unsigned short* getPrimaryInputWord() const {
|
const unsigned short* getPrimaryInputWord() const {
|
||||||
return mPrimaryInputWord;
|
return mPrimaryInputWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
|
||||||
|
1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||||
// The max number of the keys in one keyboard layout
|
// The max number of the keys in one keyboard layout
|
||||||
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;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
// cannot figure out the sweet spot type
|
|
||||||
UNKNOWN,
|
|
||||||
// touch position is out of neutral area of the given char
|
|
||||||
OUT_OF_NEUTRAL_AREA,
|
|
||||||
// touch position is in the neutral area of the given char
|
|
||||||
IN_NEUTRAL_AREA,
|
|
||||||
// touch position is in the sweet spot of the given char
|
|
||||||
IN_SWEET_SPOT
|
|
||||||
} SweetSpotType;
|
|
||||||
|
|
||||||
int getStartIndexFromCoordinates(const int x, const int y) const;
|
int getStartIndexFromCoordinates(const int x, const int y) const;
|
||||||
void initializeCodeToKeyIndex();
|
void initializeCodeToKeyIndex();
|
||||||
SweetSpotType calculateSweetSpotType(int index) const;
|
float calculateNormalizedSquaredDistance(int index) const;
|
||||||
float calculateSquaredDistanceFromSweetSpotCenter(int keyIndex, int inputIndex) const;
|
float calculateSquaredDistanceFromSweetSpotCenter(int keyIndex, int inputIndex) const;
|
||||||
|
|
||||||
const int MAX_PROXIMITY_CHARS_SIZE;
|
const int MAX_PROXIMITY_CHARS_SIZE;
|
||||||
|
@ -104,7 +96,7 @@ private:
|
||||||
float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
||||||
float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
||||||
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
|
||||||
SweetSpotType mSweetSpotTypes[MAX_WORD_LENGTH_INTERNAL];
|
int mNormalizedSquaredDistance[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mInputLength;
|
int mInputLength;
|
||||||
unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
|
unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
|
int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
|
||||||
|
|
Loading…
Reference in New Issue