proximity_info_utils.h revision 830ba67498c6da53b38212dd9ac5ba318a00de11
1bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka/* 2bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * Copyright (C) 2013 The Android Open Source Project 3bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * 4bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 5bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * you may not use this file except in compliance with the License. 6bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * You may obtain a copy of the License at 7bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * 8bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 9bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * 10bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software 11bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 12bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * See the License for the specific language governing permissions and 14bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka * limitations under the License. 15bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka */ 16bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 17bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#ifndef LATINIME_PROXIMITY_INFO_UTILS_H 18bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#define LATINIME_PROXIMITY_INFO_UTILS_H 19bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 200c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa#include <cmath> 210c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 22bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "additional_proximity_chars.h" 23bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "char_utils.h" 24bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "defines.h" 250c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa#include "geometry_utils.h" 26bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "hash_map_compat.h" 27bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 28bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataokanamespace latinime { 29bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataokaclass ProximityInfoUtils { 30bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka public: 31d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE int getKeyIndexOf(const int keyCount, const int c, 32bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const hash_map_compat<int, int> *const codeToKeyMap) { 33bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (keyCount == 0) { 34bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // We do not have the coordinate data 35bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 36bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 37bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (c == NOT_A_CODE_POINT) { 38bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 39bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 40bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int lowerCode = toLowerCase(c); 41bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka hash_map_compat<int, int>::const_iterator mapPos = codeToKeyMap->find(lowerCode); 42bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (mapPos != codeToKeyMap->end()) { 43bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return mapPos->second; 44bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 45bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 46bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 47bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 48d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE void initializeProximities(const int *const inputCodes, 49bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const inputXCoordinates, const int *const inputYCoordinates, 50bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int inputSize, const int *const keyXCoordinates, 51bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 526e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const proximityCharsArray, const int cellHeight, const int cellWidth, 536e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int gridWidth, const int mostCommonKeyWidth, const int keyCount, 546e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const char *const localeStr, 55bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const hash_map_compat<int, int> *const codeToKeyMap, int *inputProximities) { 56bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // Initialize 57bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // - mInputCodes 58bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // - mNormalizedSquaredDistances 59bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // TODO: Merge 60bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 61bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int primaryKey = inputCodes[i]; 62bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int x = inputXCoordinates[i]; 63bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int y = inputYCoordinates[i]; 646c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa int *proximities = &inputProximities[i * MAX_PROXIMITY_CHARS_SIZE]; 65bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka calculateProximities(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, 666e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa proximityCharsArray, cellHeight, cellWidth, gridWidth, mostCommonKeyWidth, 676e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa keyCount, x, y, primaryKey, localeStr, codeToKeyMap, proximities); 68bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 69bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 70bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 71bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 72bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AKLOGI("---"); 736c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) { 74bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int proximityChar = 756c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa inputProximities[i * MAX_PROXIMITY_CHARS_SIZE + j]; 76bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximityChar += 0; 77bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AKLOGI("--- (%d)%c", i, proximityChar); 78bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 79bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 80bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 81bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 82bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 836e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa static AK_FORCE_INLINE int getStartIndexFromCoordinates(const int x, const int y, 846e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int cellHeight, const int cellWidth, const int gridWidth) { 856e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa return ((y / cellHeight) * gridWidth + (x / cellWidth)) * MAX_PROXIMITY_CHARS_SIZE; 86bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 87bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 880c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2, 890c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float y2) { 900c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return SQUARE_FLOAT(x1 - x2) + SQUARE_FLOAT(y1 - y2); 910c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 920c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 930c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y, 940c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float x1, const float y1, const float x2, const float y2, const bool extend) { 950c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray1x = x - x1; 960c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray1y = y - y1; 970c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray2x = x2 - x1; 980c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray2y = y2 - y1; 990c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1000c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float dotProduct = ray1x * ray2x + ray1y * ray2y; 1010c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float lineLengthSqr = SQUARE_FLOAT(ray2x) + SQUARE_FLOAT(ray2y); 1020c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float projectionLengthSqr = dotProduct / lineLengthSqr; 1030c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1040c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionX; 1050c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionY; 1060c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa if (!extend && projectionLengthSqr < 0.0f) { 1070c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1; 1080c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1; 1090c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else if (!extend && projectionLengthSqr > 1.0f) { 1100c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x2; 1110c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y2; 1120c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else { 1130c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1 + projectionLengthSqr * ray2x; 1140c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1 + projectionLengthSqr * ray2y; 1150c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1160c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return getSquaredDistanceFloat(x, y, projectionX, projectionY); 1170c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1180c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1190c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa // Normal distribution N(u, sigma^2). 1200c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa struct NormalDistribution { 1210c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa public: 1220c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa NormalDistribution(const float u, const float sigma) 1230c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa : mU(u), mSigma(sigma), 1240c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))), 1250c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {} 1260c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1270c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float getProbabilityDensity(const float x) const { 1280c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float shiftedX = x - mU; 1290c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX)); 1300c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1310c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1320c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa private: 1330c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa DISALLOW_IMPLICIT_CONSTRUCTORS(NormalDistribution); 1340c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float mU; // mean value 1350c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float mSigma; // standard deviation 1360c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float mPreComputedNonExpPart; // = 1 / sqrt(2 * PI * sigma^2) 1370c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float mPreComputedExponentPart; // = -1 / (2 * sigma^2) 1380c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa }; // struct NormalDistribution 1390c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 140bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka private: 141bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoUtils); 142bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 143bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static bool isOnKey(const int *const keyXCoordinates, const int *const keyYCoordinates, 144bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyWidths, const int *keyHeights, const int keyId, const int x, 145bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int y) { 146bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case 147bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 148bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 149bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId] + 1; 150bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 151bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; 152bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 153bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 154d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE void calculateProximities(const int *const keyXCoordinates, 1556e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 1566e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const proximityCharsArray, const int cellHeight, const int cellWidth, 157bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int gridWidth, const int mostCommonKeyWidth, const int keyCount, 158bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int x, const int y, const int primaryKey, const char *const localeStr, 159bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const hash_map_compat<int, int> *const codeToKeyMap, int *proximities) { 160bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int mostCommonKeyWidthSquare = mostCommonKeyWidth * mostCommonKeyWidth; 161bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int insertPos = 0; 162bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = primaryKey; 1636e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int startIndex = getStartIndexFromCoordinates(x, y, cellHeight, cellWidth, gridWidth); 164bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (startIndex >= 0) { 1656e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 166bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int c = proximityCharsArray[startIndex + i]; 167bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (c < KEYCODE_SPACE || c == primaryKey) { 168bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 169bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 170bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyIndex = getKeyIndexOf(keyCount, c, codeToKeyMap); 171bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const bool onKey = isOnKey(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, 172bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyIndex, x, y); 173bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int distance = squaredLengthToEdge(keyXCoordinates, keyYCoordinates, 174bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyWidths, keyHeights, keyIndex, x, y); 175bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (onKey || distance < mostCommonKeyWidthSquare) { 176bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = c; 1776e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 178bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 179bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 180bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 181bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 182bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 183bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 184bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 185bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int additionalProximitySize = 186bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AdditionalProximityChars::getAdditionalCharsSize(localeStr, primaryKey); 187bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (additionalProximitySize > 0) { 188bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; 1896e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 190bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 191bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 192bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 193bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 194bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 195bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 196bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *additionalProximityChars = 197bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AdditionalProximityChars::getAdditionalChars(localeStr, primaryKey); 198bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int j = 0; j < additionalProximitySize; ++j) { 199bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int ac = additionalProximityChars[j]; 200bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int k = 0; 201bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (; k < insertPos; ++k) { 202bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (ac == proximities[k]) { 203bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka break; 204bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 205bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 206bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (k < insertPos) { 207bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 208bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 209bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ac; 2106e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 211bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 212bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 213bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 214bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 215bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 216bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 217bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 218bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 219bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // Add a delimiter for the proximity characters 2206e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 221bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[i] = NOT_A_CODE_POINT; 222bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 223bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 224bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 225bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static int squaredLengthToEdge(const int *const keyXCoordinates, 226bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 227bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyId, const int x, const int y) { 228bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // NOT_A_ID is -1, but return whenever < 0 just in case 229830ba67498c6da53b38212dd9ac5ba318a00de11Satoshi Kataoka if (keyId < 0) return MAX_VALUE_FOR_WEIGHTING; 230bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 231bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 232bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId]; 233bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 234bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeX = x < left ? left : (x > right ? right : x); 235bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeY = y < top ? top : (y > bottom ? bottom : y); 236bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dx = x - edgeX; 237bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dy = y - edgeY; 238bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return dx * dx + dy * dy; 239bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 240bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka}; 241bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka} // namespace latinime 242bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#endif // LATINIME_PROXIMITY_INFO_UTILS_H 243