2012-06-05 08:55:52 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 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.
|
|
|
|
*/
|
|
|
|
|
2013-01-24 08:08:30 +00:00
|
|
|
#include <cstring> // for memset() and memcpy()
|
2012-10-09 10:57:08 +00:00
|
|
|
#include <sstream> // for debug prints
|
2012-06-05 08:55:52 +00:00
|
|
|
|
|
|
|
#define LOG_TAG "LatinIME: proximity_info_state.cpp"
|
|
|
|
|
|
|
|
#include "defines.h"
|
2013-01-15 07:15:48 +00:00
|
|
|
#include "geometry_utils.h"
|
2012-06-05 08:55:52 +00:00
|
|
|
#include "proximity_info.h"
|
|
|
|
#include "proximity_info_state.h"
|
2013-01-21 07:33:24 +00:00
|
|
|
#include "proximity_info_state_utils.h"
|
2012-06-05 08:55:52 +00:00
|
|
|
|
|
|
|
namespace latinime {
|
2012-09-15 16:23:56 +00:00
|
|
|
|
2012-08-24 05:45:54 +00:00
|
|
|
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
|
2012-10-29 09:06:22 +00:00
|
|
|
const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
|
2012-08-23 06:46:43 +00:00
|
|
|
const int *const xCoordinates, const int *const yCoordinates, const int *const times,
|
|
|
|
const int *const pointerIds, const bool isGeometric) {
|
2013-01-24 06:20:50 +00:00
|
|
|
ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH));
|
|
|
|
mIsContinuationPossible = ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(
|
|
|
|
inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
|
|
|
|
&mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
|
2012-09-07 12:04:12 +00:00
|
|
|
|
2012-06-08 06:29:44 +00:00
|
|
|
mProximityInfo = proximityInfo;
|
|
|
|
mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
|
|
|
|
mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare();
|
|
|
|
mKeyCount = proximityInfo->getKeyCount();
|
|
|
|
mCellHeight = proximityInfo->getCellHeight();
|
|
|
|
mCellWidth = proximityInfo->getCellWidth();
|
|
|
|
mGridHeight = proximityInfo->getGridWidth();
|
|
|
|
mGridWidth = proximityInfo->getGridHeight();
|
2012-06-05 08:55:52 +00:00
|
|
|
|
2013-01-17 10:46:12 +00:00
|
|
|
memset(mInputProximities, 0, sizeof(mInputProximities));
|
2012-06-05 08:55:52 +00:00
|
|
|
|
2012-08-24 06:19:56 +00:00
|
|
|
if (!isGeometric && pointerId == 0) {
|
2013-01-17 10:46:12 +00:00
|
|
|
mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates,
|
|
|
|
inputSize, mInputProximities);
|
2012-06-05 08:55:52 +00:00
|
|
|
}
|
2012-08-23 06:46:43 +00:00
|
|
|
|
|
|
|
///////////////////////
|
|
|
|
// Setup touch points
|
2012-09-07 12:04:12 +00:00
|
|
|
int pushTouchPointStartIndex = 0;
|
|
|
|
int lastSavedInputSize = 0;
|
2012-08-24 06:19:56 +00:00
|
|
|
mMaxPointToKeyLength = maxPointToKeyLength;
|
2013-01-24 08:08:30 +00:00
|
|
|
mSampledInputSize = 0;
|
|
|
|
mMostProbableStringProbability = 0.0f;
|
|
|
|
|
2013-01-22 08:00:43 +00:00
|
|
|
if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
|
2012-09-07 12:04:12 +00:00
|
|
|
// Just update difference.
|
2013-01-24 08:08:30 +00:00
|
|
|
// Previous two points are never skipped. Thus, we pop 2 input point data here.
|
|
|
|
pushTouchPointStartIndex = ProximityInfoStateUtils::trimLastTwoTouchPoints(
|
|
|
|
&mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
|
|
|
|
&mSampledInputIndice);
|
2012-11-16 10:03:36 +00:00
|
|
|
lastSavedInputSize = mSampledInputXs.size();
|
2012-09-07 12:04:12 +00:00
|
|
|
} else {
|
|
|
|
// Clear all data.
|
2012-11-16 10:03:36 +00:00
|
|
|
mSampledInputXs.clear();
|
|
|
|
mSampledInputYs.clear();
|
2013-01-22 08:00:43 +00:00
|
|
|
mSampledTimes.clear();
|
|
|
|
mSampledInputIndice.clear();
|
|
|
|
mSampledLengthCache.clear();
|
2013-01-23 07:47:17 +00:00
|
|
|
mSampledDistanceCache_G.clear();
|
|
|
|
mSampledNearKeysVector.clear();
|
|
|
|
mSampledSearchKeysVector.clear();
|
2012-11-16 14:06:41 +00:00
|
|
|
mSpeedRates.clear();
|
2012-11-22 11:15:40 +00:00
|
|
|
mBeelineSpeedPercentiles.clear();
|
2012-10-09 10:57:08 +00:00
|
|
|
mCharProbabilities.clear();
|
2012-10-11 11:24:41 +00:00
|
|
|
mDirections.clear();
|
2012-09-07 12:04:12 +00:00
|
|
|
}
|
2013-01-24 08:08:30 +00:00
|
|
|
|
2012-09-11 08:47:55 +00:00
|
|
|
if (DEBUG_GEO_FULL) {
|
|
|
|
AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d",
|
|
|
|
pushTouchPointStartIndex, lastSavedInputSize);
|
|
|
|
}
|
2012-08-31 12:22:14 +00:00
|
|
|
|
2012-08-23 06:46:43 +00:00
|
|
|
if (xCoordinates && yCoordinates) {
|
2013-01-21 07:33:24 +00:00
|
|
|
mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(
|
|
|
|
mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength,
|
|
|
|
mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize,
|
2013-01-22 08:00:43 +00:00
|
|
|
isGeometric, pointerId, pushTouchPointStartIndex, &mSampledInputXs,
|
|
|
|
&mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice);
|
2012-06-05 08:55:52 +00:00
|
|
|
}
|
2012-08-23 06:46:43 +00:00
|
|
|
|
2012-11-16 10:03:36 +00:00
|
|
|
if (mSampledInputSize > 0 && isGeometric) {
|
2013-01-21 09:29:27 +00:00
|
|
|
mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(
|
|
|
|
inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize,
|
2013-01-22 08:00:43 +00:00
|
|
|
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
|
|
|
|
&mSampledLengthCache, &mSampledInputIndice, &mSpeedRates, &mDirections);
|
2013-01-21 09:29:27 +00:00
|
|
|
ProximityInfoStateUtils::refreshBeelineSpeedRates(
|
|
|
|
mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize,
|
|
|
|
xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
|
2013-01-22 08:00:43 +00:00
|
|
|
&mSampledInputYs, &mSampledInputIndice, &mBeelineSpeedPercentiles);
|
2012-10-11 04:08:06 +00:00
|
|
|
}
|
|
|
|
|
2012-11-16 10:03:36 +00:00
|
|
|
if (mSampledInputSize > 0) {
|
2013-01-22 08:00:43 +00:00
|
|
|
ProximityInfoStateUtils::initGeometricDistanceInfos(
|
|
|
|
mProximityInfo, mProximityInfo->getKeyCount(),
|
|
|
|
mSampledInputSize, lastSavedInputSize, &mSampledInputXs, &mSampledInputYs,
|
2013-01-23 07:47:17 +00:00
|
|
|
&mSampledNearKeysVector, &mSampledDistanceCache_G);
|
2012-10-11 04:08:06 +00:00
|
|
|
if (isGeometric) {
|
|
|
|
// updates probabilities of skipping or mapping each key for all points.
|
2013-01-22 04:18:40 +00:00
|
|
|
ProximityInfoStateUtils::updateAlignPointProbabilities(
|
|
|
|
mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(),
|
2013-01-22 08:00:43 +00:00
|
|
|
mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize,
|
|
|
|
&mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache,
|
2013-01-23 07:47:17 +00:00
|
|
|
&mSampledDistanceCache_G, &mSampledNearKeysVector, &mCharProbabilities);
|
|
|
|
ProximityInfoStateUtils::updateSampledSearchKeysVector(mProximityInfo,
|
|
|
|
mSampledInputSize, lastSavedInputSize, &mSampledLengthCache,
|
|
|
|
&mSampledNearKeysVector, &mSampledSearchKeysVector);
|
2013-01-24 08:08:30 +00:00
|
|
|
mMostProbableStringProbability = ProximityInfoStateUtils::getMostProbableString(
|
|
|
|
mProximityInfo, mSampledInputSize, &mCharProbabilities, mMostProbableString);
|
|
|
|
|
2012-08-23 06:46:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-24 06:19:56 +00:00
|
|
|
|
2012-10-09 10:57:08 +00:00
|
|
|
if (DEBUG_SAMPLING_POINTS) {
|
2013-01-22 08:00:43 +00:00
|
|
|
ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates,
|
2013-01-23 05:37:56 +00:00
|
|
|
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSpeedRates,
|
2013-01-22 08:00:43 +00:00
|
|
|
&mBeelineSpeedPercentiles);
|
2012-10-09 10:57:08 +00:00
|
|
|
}
|
2012-08-23 06:46:43 +00:00
|
|
|
// end
|
|
|
|
///////////////////////
|
|
|
|
|
2012-11-16 10:03:36 +00:00
|
|
|
mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
|
2012-09-24 09:29:31 +00:00
|
|
|
&& xCoordinates && yCoordinates;
|
2012-08-24 06:19:56 +00:00
|
|
|
if (!isGeometric && pointerId == 0) {
|
2013-01-22 08:00:43 +00:00
|
|
|
ProximityInfoStateUtils::initPrimaryInputWord(
|
|
|
|
inputSize, mInputProximities, mPrimaryInputWord);
|
|
|
|
if (mTouchPositionCorrectionEnabled) {
|
|
|
|
ProximityInfoStateUtils::initNormalizedSquaredDistances(
|
|
|
|
mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
|
2013-01-24 08:08:30 +00:00
|
|
|
&mSampledInputXs, &mSampledInputYs, mNormalizedSquaredDistances);
|
2012-06-05 08:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-11 06:51:38 +00:00
|
|
|
if (DEBUG_GEO_FULL) {
|
2012-11-16 10:03:36 +00:00
|
|
|
AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-12 11:19:18 +00:00
|
|
|
// TODO: Remove the "scale" parameter
|
|
|
|
// This function basically converts from a length to an edit distance. Accordingly, it's obviously
|
|
|
|
// wrong to compare with mMaxPointToKeyLength.
|
|
|
|
float ProximityInfoState::getPointToKeyLength(
|
|
|
|
const int inputIndex, const int codePoint, const float scale) const {
|
2012-10-11 04:08:06 +00:00
|
|
|
const int keyId = mProximityInfo->getKeyIndexOf(codePoint);
|
|
|
|
if (keyId != NOT_AN_INDEX) {
|
|
|
|
const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
|
2013-01-23 07:47:17 +00:00
|
|
|
return min(mSampledDistanceCache_G[index] * scale, mMaxPointToKeyLength);
|
2012-10-11 04:08:06 +00:00
|
|
|
}
|
2012-10-29 09:06:22 +00:00
|
|
|
if (isSkippableCodePoint(codePoint)) {
|
2012-10-09 10:57:08 +00:00
|
|
|
return 0.0f;
|
|
|
|
}
|
2012-10-11 04:08:06 +00:00
|
|
|
// If the char is not a key on the keyboard then return the max length.
|
|
|
|
return MAX_POINT_TO_KEY_LENGTH;
|
2012-10-09 10:57:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-15 10:16:38 +00:00
|
|
|
float ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const {
|
2012-12-12 11:19:18 +00:00
|
|
|
return getPointToKeyLength(inputIndex, codePoint, 1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Remove the "scale" parameter
|
|
|
|
float ProximityInfoState::getPointToKeyByIdLength(
|
|
|
|
const int inputIndex, const int keyId, const float scale) const {
|
2013-01-22 04:18:40 +00:00
|
|
|
return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength,
|
2013-01-23 07:47:17 +00:00
|
|
|
&mSampledDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId, scale);
|
2012-08-23 06:46:43 +00:00
|
|
|
}
|
|
|
|
|
2012-12-12 11:19:18 +00:00
|
|
|
float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const {
|
|
|
|
return getPointToKeyByIdLength(inputIndex, keyId, 1.0f);
|
|
|
|
}
|
|
|
|
|
2012-11-02 09:29:03 +00:00
|
|
|
// In the following function, c is the current character of the dictionary word currently examined.
|
|
|
|
// currentChars is an array containing the keys close to the character the user actually typed at
|
|
|
|
// the same position. We want to see if c is in it: if so, then the word contains at that position
|
|
|
|
// a character close to what the user typed.
|
|
|
|
// What the user typed is actually the first character of the array.
|
|
|
|
// proximityIndex is a pointer to the variable where getMatchedProximityId returns the index of c
|
|
|
|
// in the proximity chars of the input index.
|
|
|
|
// Notice : accented characters do not have a proximity list, so they are alone in their list. The
|
|
|
|
// non-accented version of the character should be considered "close", but not the other keys close
|
|
|
|
// to the non-accented version.
|
|
|
|
ProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c,
|
|
|
|
const bool checkProximityChars, int *proximityIndex) const {
|
|
|
|
const int *currentCodePoints = getProximityCodePointsAt(index);
|
|
|
|
const int firstCodePoint = currentCodePoints[0];
|
|
|
|
const int baseLowerC = toBaseLowerCase(c);
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
if (firstCodePoint == baseLowerC || firstCodePoint == c) {
|
|
|
|
return EQUIVALENT_CHAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!checkProximityChars) return UNRELATED_CHAR;
|
|
|
|
|
|
|
|
// If the non-accented, lowercased version of that first character matches c, then we have a
|
|
|
|
// non-accented version of the accented character the user typed. Treat it as a close char.
|
|
|
|
if (toBaseLowerCase(firstCodePoint) == baseLowerC) {
|
|
|
|
return NEAR_PROXIMITY_CHAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not an exact nor an accent-alike match: search the list of close keys
|
|
|
|
int j = 1;
|
2013-01-22 04:14:53 +00:00
|
|
|
while (j < MAX_PROXIMITY_CHARS_SIZE
|
2012-11-02 09:29:03 +00:00
|
|
|
&& currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
|
|
|
|
const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
|
|
|
|
if (matched) {
|
|
|
|
if (proximityIndex) {
|
|
|
|
*proximityIndex = j;
|
|
|
|
}
|
|
|
|
return NEAR_PROXIMITY_CHAR;
|
|
|
|
}
|
|
|
|
++j;
|
|
|
|
}
|
2013-01-22 04:14:53 +00:00
|
|
|
if (j < MAX_PROXIMITY_CHARS_SIZE
|
2012-11-02 09:29:03 +00:00
|
|
|
&& currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
|
|
|
|
++j;
|
2013-01-22 04:14:53 +00:00
|
|
|
while (j < MAX_PROXIMITY_CHARS_SIZE
|
2012-11-02 09:29:03 +00:00
|
|
|
&& currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
|
|
|
|
const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
|
|
|
|
if (matched) {
|
|
|
|
if (proximityIndex) {
|
|
|
|
*proximityIndex = j;
|
|
|
|
}
|
|
|
|
return ADDITIONAL_PROXIMITY_CHAR;
|
|
|
|
}
|
|
|
|
++j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Was not included, signal this as an unrelated character.
|
|
|
|
return UNRELATED_CHAR;
|
|
|
|
}
|
|
|
|
|
2012-09-04 08:00:24 +00:00
|
|
|
// Puts possible characters into filter and returns new filter size.
|
2012-12-10 14:36:22 +00:00
|
|
|
int ProximityInfoState::getAllPossibleChars(
|
|
|
|
const size_t index, int *const filter, const int filterSize) const {
|
2012-11-16 10:03:36 +00:00
|
|
|
if (index >= mSampledInputXs.size()) {
|
2012-09-04 08:00:24 +00:00
|
|
|
return filterSize;
|
|
|
|
}
|
2012-09-19 03:03:47 +00:00
|
|
|
int newFilterSize = filterSize;
|
2012-10-11 04:08:06 +00:00
|
|
|
const int keyCount = mProximityInfo->getKeyCount();
|
|
|
|
for (int j = 0; j < keyCount; ++j) {
|
2013-01-23 07:47:17 +00:00
|
|
|
if (mSampledSearchKeysVector[index].test(j)) {
|
2012-12-10 14:36:22 +00:00
|
|
|
const int keyCodePoint = mProximityInfo->getCodePointOf(j);
|
2012-09-04 08:00:24 +00:00
|
|
|
bool insert = true;
|
|
|
|
// TODO: Avoid linear search
|
|
|
|
for (int k = 0; k < filterSize; ++k) {
|
|
|
|
if (filter[k] == keyCodePoint) {
|
|
|
|
insert = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (insert) {
|
2012-09-19 03:03:47 +00:00
|
|
|
filter[newFilterSize++] = keyCodePoint;
|
2012-09-04 08:00:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-19 03:03:47 +00:00
|
|
|
return newFilterSize;
|
2012-09-04 08:00:24 +00:00
|
|
|
}
|
2012-09-06 11:55:45 +00:00
|
|
|
|
2012-10-11 04:08:06 +00:00
|
|
|
bool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const {
|
2013-01-24 08:08:30 +00:00
|
|
|
ASSERT(keyId >= 0 && index >= 0 && index < mSampledInputSize);
|
2013-01-23 07:47:17 +00:00
|
|
|
return mSampledSearchKeysVector[index].test(keyId);
|
2012-10-11 04:08:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float ProximityInfoState::getDirection(const int index0, const int index1) const {
|
2013-01-21 09:29:27 +00:00
|
|
|
return ProximityInfoStateUtils::getDirection(
|
|
|
|
&mSampledInputXs, &mSampledInputYs, index0, index1);
|
2012-10-11 04:08:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float ProximityInfoState::getLineToKeyDistance(
|
|
|
|
const int from, const int to, const int keyId, const bool extend) const {
|
2012-11-16 10:03:36 +00:00
|
|
|
if (from < 0 || from > mSampledInputSize - 1) {
|
2012-10-11 04:08:06 +00:00
|
|
|
return 0.0f;
|
|
|
|
}
|
2012-11-16 10:03:36 +00:00
|
|
|
if (to < 0 || to > mSampledInputSize - 1) {
|
2012-10-11 04:08:06 +00:00
|
|
|
return 0.0f;
|
|
|
|
}
|
2012-11-16 10:03:36 +00:00
|
|
|
const int x0 = mSampledInputXs[from];
|
|
|
|
const int y0 = mSampledInputYs[from];
|
|
|
|
const int x1 = mSampledInputXs[to];
|
|
|
|
const int y1 = mSampledInputYs[to];
|
2012-10-11 04:08:06 +00:00
|
|
|
|
|
|
|
const int keyX = mProximityInfo->getKeyCenterXOfKeyIdG(keyId);
|
|
|
|
const int keyY = mProximityInfo->getKeyCenterYOfKeyIdG(keyId);
|
|
|
|
|
2013-01-21 02:37:54 +00:00
|
|
|
return ProximityInfoUtils::pointToLineSegSquaredDistanceFloat(
|
|
|
|
keyX, keyY, x0, y0, x1, y1, extend);
|
2012-10-09 10:57:08 +00:00
|
|
|
}
|
|
|
|
|
2012-12-17 06:20:58 +00:00
|
|
|
float ProximityInfoState::getMostProbableString(int *const codePointBuf) const {
|
2013-01-24 08:08:30 +00:00
|
|
|
memcpy(codePointBuf, mMostProbableString, sizeof(mMostProbableString));
|
|
|
|
return mMostProbableStringProbability;
|
2012-10-11 04:08:06 +00:00
|
|
|
}
|
|
|
|
|
2013-01-18 09:01:59 +00:00
|
|
|
bool ProximityInfoState::hasSpaceProximity(const int index) const {
|
|
|
|
ASSERT(0 <= index && index < mSampledInputSize);
|
|
|
|
return mProximityInfo->hasSpaceProximity(getInputX(index), getInputY(index));
|
|
|
|
}
|
|
|
|
|
2012-10-11 04:08:06 +00:00
|
|
|
// Returns a probability of mapping index to keyIndex.
|
|
|
|
float ProximityInfoState::getProbability(const int index, const int keyIndex) const {
|
2012-11-16 10:03:36 +00:00
|
|
|
ASSERT(0 <= index && index < mSampledInputSize);
|
2012-10-11 04:08:06 +00:00
|
|
|
hash_map_compat<int, float>::const_iterator it = mCharProbabilities[index].find(keyIndex);
|
|
|
|
if (it != mCharProbabilities[index].end()) {
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
|
2012-10-09 10:57:08 +00:00
|
|
|
}
|
2012-06-05 08:55:52 +00:00
|
|
|
} // namespace latinime
|