proximity_info_utils.h revision 8ca9be17db2f1845c7c7a3b584507cf60c9ca53d
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> 218ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa#include <unordered_map> 220c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 23bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "defines.h" 2494da44e43eac54047fb690c753d3af2a7d3a03c8Ken Wakasa#include "suggest/core/layout/additional_proximity_chars.h" 2529432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/geometry_utils.h" 26addea83bad5751308fef508d79c6989b8872f050Ken Wakasa#include "utils/char_utils.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, 328ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<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 } 40464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa const int lowerCode = CharUtils::toLowerCase(c); 418ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa std::unordered_map<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, 558ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<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) { 9029432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa return GeometryUtils::SQUARE_FLOAT(x1 - x2) + GeometryUtils::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; 10129432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x) 10229432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa + GeometryUtils::SQUARE_FLOAT(ray2y); 103a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi if (lineLengthSqr <= 0.0f) { 104a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi // Return point to the point distance. 105a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi return getSquaredDistanceFloat(x, y, x1, y1); 106a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi } 1070c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float projectionLengthSqr = dotProduct / lineLengthSqr; 1080c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1090c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionX; 1100c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionY; 1110c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa if (!extend && projectionLengthSqr < 0.0f) { 1120c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1; 1130c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1; 1140c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else if (!extend && projectionLengthSqr > 1.0f) { 1150c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x2; 1160c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y2; 1170c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else { 1180c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1 + projectionLengthSqr * ray2x; 1190c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1 + projectionLengthSqr * ray2y; 1200c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1210c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return getSquaredDistanceFloat(x, y, projectionX, projectionY); 1220c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1230c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1247a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi static AK_FORCE_INLINE bool isMatchOrProximityChar(const ProximityType type) { 1257a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi return type == MATCH_CHAR || type == PROXIMITY_CHAR || type == ADDITIONAL_PROXIMITY_CHAR; 1267a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi } 1277a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi 128bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka private: 129bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoUtils); 130bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 131bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static bool isOnKey(const int *const keyXCoordinates, const int *const keyYCoordinates, 132bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyWidths, const int *keyHeights, const int keyId, const int x, 133bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int y) { 134bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case 135bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 136bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 137bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId] + 1; 138bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 139bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; 140bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 141bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 142d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE void calculateProximities(const int *const keyXCoordinates, 1436e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 1446e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const proximityCharsArray, const int cellHeight, const int cellWidth, 145bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int gridWidth, const int mostCommonKeyWidth, const int keyCount, 146bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int x, const int y, const int primaryKey, const char *const localeStr, 1478ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<int, int> *const codeToKeyMap, int *proximities) { 148bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int mostCommonKeyWidthSquare = mostCommonKeyWidth * mostCommonKeyWidth; 149bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int insertPos = 0; 150bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = primaryKey; 1519fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi if (x == NOT_A_COORDINATE || y == NOT_A_COORDINATE) { 1529fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 1539fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi proximities[i] = NOT_A_CODE_POINT; 1549fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi } 1559fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi return; 1569fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi } 1576e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int startIndex = getStartIndexFromCoordinates(x, y, cellHeight, cellWidth, gridWidth); 158bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (startIndex >= 0) { 1596e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 160bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int c = proximityCharsArray[startIndex + i]; 161bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (c < KEYCODE_SPACE || c == primaryKey) { 162bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 163bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 164bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyIndex = getKeyIndexOf(keyCount, c, codeToKeyMap); 165bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const bool onKey = isOnKey(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, 166bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyIndex, x, y); 167bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int distance = squaredLengthToEdge(keyXCoordinates, keyYCoordinates, 168bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyWidths, keyHeights, keyIndex, x, y); 169bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (onKey || distance < mostCommonKeyWidthSquare) { 170bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = c; 1716e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 172bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 173bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 174bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 175bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 176bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 177bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 178bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 179bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int additionalProximitySize = 180bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AdditionalProximityChars::getAdditionalCharsSize(localeStr, primaryKey); 181bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (additionalProximitySize > 0) { 182bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; 1836e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 184bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 185bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 186bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 187bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 188bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 189bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 190bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *additionalProximityChars = 191bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AdditionalProximityChars::getAdditionalChars(localeStr, primaryKey); 192bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int j = 0; j < additionalProximitySize; ++j) { 193bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int ac = additionalProximityChars[j]; 194bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int k = 0; 195bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (; k < insertPos; ++k) { 196bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (ac == proximities[k]) { 197bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka break; 198bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 199bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 200bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (k < insertPos) { 201bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 202bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 203bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ac; 2046e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 205bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 206bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 207bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 208bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 209bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 210bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 211bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 212bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 213bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // Add a delimiter for the proximity characters 2146e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 215bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[i] = NOT_A_CODE_POINT; 216bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 217bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 218bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 219bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static int squaredLengthToEdge(const int *const keyXCoordinates, 220bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 221bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyId, const int x, const int y) { 222bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // NOT_A_ID is -1, but return whenever < 0 just in case 223830ba67498c6da53b38212dd9ac5ba318a00de11Satoshi Kataoka if (keyId < 0) return MAX_VALUE_FOR_WEIGHTING; 224bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 225bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 226bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId]; 227bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 228bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeX = x < left ? left : (x > right ? right : x); 229bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeY = y < top ? top : (y > bottom ? bottom : y); 230bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dx = x - edgeX; 231bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dy = y - edgeY; 232bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return dx * dx + dy * dy; 233bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 234bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka}; 235bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka} // namespace latinime 236bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#endif // LATINIME_PROXIMITY_INFO_UTILS_H 237