proximity_info_state.cpp revision 687a244703a02323ebd64433cbaead5def499861
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <cstring> // for memset() 18#include <stdint.h> 19 20#define LOG_TAG "LatinIME: proximity_info_state.cpp" 21 22#include "defines.h" 23#include "geometry_utils.h" 24#include "proximity_info.h" 25#include "proximity_info_state.h" 26 27namespace latinime { 28void ProximityInfoState::initInputParams(const int pointerId, const float maxLength, 29 const ProximityInfo *proximityInfo, const int32_t *inputCodes, const int inputSize, 30 const int *const xCoordinates, const int *const yCoordinates, const int *const times, 31 const int *const pointerIds, const bool isGeometric) { 32 mProximityInfo = proximityInfo; 33 mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData(); 34 mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare(); 35 mLocaleStr = proximityInfo->getLocaleStr(); 36 mKeyCount = proximityInfo->getKeyCount(); 37 mCellHeight = proximityInfo->getCellHeight(); 38 mCellWidth = proximityInfo->getCellWidth(); 39 mGridHeight = proximityInfo->getGridWidth(); 40 mGridWidth = proximityInfo->getGridHeight(); 41 const int normalizedSquaredDistancesLength = 42 MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL; 43 for (int i = 0; i < normalizedSquaredDistancesLength; ++i) { 44 mNormalizedSquaredDistances[i] = NOT_A_DISTANCE; 45 } 46 47 memset(mInputCodes, 0, 48 MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE_INTERNAL * sizeof(mInputCodes[0])); 49 50 for (int i = 0; i < inputSize; ++i) { 51 const int32_t primaryKey = inputCodes[i]; 52 const int x = xCoordinates[i]; 53 const int y = yCoordinates[i]; 54 int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL]; 55 mProximityInfo->calculateNearbyKeyCodes(x, y, primaryKey, proximities); 56 } 57 58 if (DEBUG_PROXIMITY_CHARS) { 59 for (int i = 0; i < inputSize; ++i) { 60 AKLOGI("---"); 61 for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) { 62 int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j]; 63 int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j]; 64 icc += 0; 65 icfjc += 0; 66 AKLOGI("--- (%d)%c,%c", i, icc, icfjc); AKLOGI("--- A<%d>,B<%d>", icc, icfjc); 67 } 68 } 69 } 70 71 mMaxPointToKeyLength = maxLength; 72 /////////////////////// 73 // Setup touch points 74 mInputXs.clear(); 75 mInputYs.clear(); 76 mTimes.clear(); 77 mLengthCache.clear(); 78 mDistanceCache.clear(); 79 80 mInputSize = 0; 81 if (xCoordinates && yCoordinates) { 82 const bool proximityOnly = !isGeometric && (xCoordinates[0] < 0 || yCoordinates[0] < 0); 83 for (int i = 0; i < inputSize; ++i) { 84 ++mInputSize; 85 // Assuming pointerId == 0 if pointerIds is null. 86 const int pid = pointerIds ? pointerIds[i] : 0; 87 if (pointerId == pid) { 88 const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCharAt(i); 89 const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i]; 90 const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i]; 91 const int time = times ? times[i] : -1; 92 pushTouchPoint(c, x, y, time, isGeometric); 93 } 94 } 95 } 96 97 if (mInputSize > 0) { 98 const int keyCount = mProximityInfo->getKeyCount(); 99 mDistanceCache.resize(mInputSize * keyCount); 100 for (int i = 0; i < mInputSize; ++i) { 101 for (int k = 0; k < keyCount; ++k) { 102 const int index = i * keyCount + k; 103 const int x = mInputXs[i]; 104 const int y = mInputYs[i]; 105 mDistanceCache[index] = 106 mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y); 107 } 108 } 109 } 110 // end 111 /////////////////////// 112 113 for (int i = 0; i < inputSize; ++i) { 114 mPrimaryInputWord[i] = getPrimaryCharAt(i); 115 } 116 mPrimaryInputWord[inputSize] = 0; 117 118 mTouchPositionCorrectionEnabled = 119 mHasTouchPositionCorrectionData && xCoordinates && yCoordinates && !isGeometric; 120 for (int i = 0; i < mInputSize && mTouchPositionCorrectionEnabled; ++i) { 121 const int *proximityChars = getProximityCharsAt(i); 122 const int primaryKey = proximityChars[0]; 123 const int x = xCoordinates[i]; 124 const int y = yCoordinates[i]; 125 if (DEBUG_PROXIMITY_CHARS) { 126 int a = x + y + primaryKey; 127 a += 0; 128 AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y); 129 } 130 for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityChars[j] > 0; ++j) { 131 const int currentChar = proximityChars[j]; 132 const float squaredDistance = 133 hasInputCoordinates() ? calculateNormalizedSquaredDistance( 134 mProximityInfo->getKeyIndex(currentChar), i) : 135 NOT_A_DISTANCE_FLOAT; 136 if (squaredDistance >= 0.0f) { 137 mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = 138 (int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); 139 } else { 140 mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = 141 (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO : 142 PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; 143 } 144 if (DEBUG_PROXIMITY_CHARS) { 145 AKLOGI("--- Proximity (%d) = %c", j, currentChar); 146 } 147 } 148 } 149} 150 151void ProximityInfoState::pushTouchPoint(const int nodeChar, int x, int y, 152 const int time, const bool sample) { 153 const uint32_t size = mInputXs.size(); 154 // TODO: Should have a const variable for 10 155 const int sampleRate = mProximityInfo->getMostCommonKeyWidth() / 10; 156 if (size > 0) { 157 const int dist = getDistanceInt(x, y, mInputXs[size - 1], mInputYs[size - 1]); 158 if (sample && dist < sampleRate) { 159 return; 160 } 161 mLengthCache.push_back(mLengthCache[size - 1] + dist); 162 } else { 163 mLengthCache.push_back(0); 164 } 165 if (nodeChar >= 0 && (x < 0 || y < 0)) { 166 const int keyId = mProximityInfo->getKeyIndex(nodeChar); 167 if (keyId >= 0) { 168 x = mProximityInfo->getKeyCenterXOfIdG(keyId); 169 y = mProximityInfo->getKeyCenterYOfIdG(keyId); 170 } 171 } 172 mInputXs.push_back(x); 173 mInputYs.push_back(y); 174 mTimes.push_back(time); 175} 176 177float ProximityInfoState::calculateNormalizedSquaredDistance( 178 const int keyIndex, const int inputIndex) const { 179 if (keyIndex == NOT_AN_INDEX) { 180 return NOT_A_DISTANCE_FLOAT; 181 } 182 if (!mProximityInfo->hasSweetSpotData(keyIndex)) { 183 return NOT_A_DISTANCE_FLOAT; 184 } 185 if (NOT_A_COORDINATE == mInputXs[inputIndex]) { 186 return NOT_A_DISTANCE_FLOAT; 187 } 188 const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter( 189 keyIndex, inputIndex); 190 const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex)); 191 return squaredDistance / squaredRadius; 192} 193 194int ProximityInfoState::getDuration(const int index) const { 195 if (mTimes.size() == 0 || index <= 0 || index >= static_cast<int>(mInputSize) - 1) { 196 return 0; 197 } 198 return mTimes[index + 1] - mTimes[index - 1]; 199} 200 201float ProximityInfoState::getPointToKeyLength(int inputIndex, int charCode, float scale) { 202 const int keyId = mProximityInfo->getKeyIndex(charCode); 203 if (keyId >= 0) { 204 const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; 205 return min(mDistanceCache[index] * scale, mMaxPointToKeyLength); 206 } 207 return 0; 208} 209 210int ProximityInfoState::getKeyKeyDistance(int key0, int key1) { 211 return mProximityInfo->getKeyKeyDistanceG(key0, key1); 212} 213 214int ProximityInfoState::getSpaceY() { 215 const int keyId = mProximityInfo->getKeyIndex(' '); 216 return mProximityInfo->getKeyCenterYOfIdG(keyId); 217} 218 219float ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter( 220 const int keyIndex, const int inputIndex) const { 221 const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex); 222 const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex); 223 const float inputX = static_cast<float>(mInputXs[inputIndex]); 224 const float inputY = static_cast<float>(mInputYs[inputIndex]); 225 return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY); 226} 227} // namespace latinime 228