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> 224ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard#include <vector> 230c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 24bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#include "defines.h" 2594da44e43eac54047fb690c753d3af2a7d3a03c8Ken Wakasa#include "suggest/core/layout/additional_proximity_chars.h" 2629432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/geometry_utils.h" 27addea83bad5751308fef508d79c6989b8872f050Ken Wakasa#include "utils/char_utils.h" 28bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 29bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataokanamespace latinime { 30bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataokaclass ProximityInfoUtils { 31bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka public: 32d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE int getKeyIndexOf(const int keyCount, const int c, 338ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<int, int> *const codeToKeyMap) { 34bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (keyCount == 0) { 35bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // We do not have the coordinate data 36bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 37bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 38bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (c == NOT_A_CODE_POINT) { 39bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 40bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 41464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa const int lowerCode = CharUtils::toLowerCase(c); 428ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa std::unordered_map<int, int>::const_iterator mapPos = codeToKeyMap->find(lowerCode); 43bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (mapPos != codeToKeyMap->end()) { 44bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return mapPos->second; 45bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 46bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return NOT_AN_INDEX; 47bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 48bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 49d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE void initializeProximities(const int *const inputCodes, 50bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const inputXCoordinates, const int *const inputYCoordinates, 51bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int inputSize, const int *const keyXCoordinates, 52bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 536e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const proximityCharsArray, const int cellHeight, const int cellWidth, 546e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int gridWidth, const int mostCommonKeyWidth, const int keyCount, 554ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard const std::vector<int> *locale, 568ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<int, int> *const codeToKeyMap, int *inputProximities) { 57bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // Initialize 58bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // - mInputCodes 59bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // - mNormalizedSquaredDistances 60bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // TODO: Merge 61bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 62bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int primaryKey = inputCodes[i]; 63bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int x = inputXCoordinates[i]; 64bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int y = inputYCoordinates[i]; 656c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa int *proximities = &inputProximities[i * MAX_PROXIMITY_CHARS_SIZE]; 66bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka calculateProximities(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, 676e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa proximityCharsArray, cellHeight, cellWidth, gridWidth, mostCommonKeyWidth, 684ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard keyCount, x, y, primaryKey, locale, codeToKeyMap, proximities); 69bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 70bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 71bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_PROXIMITY_CHARS) { 72bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int i = 0; i < inputSize; ++i) { 73bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AKLOGI("---"); 746c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) { 75bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int proximityChar = 766c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa inputProximities[i * MAX_PROXIMITY_CHARS_SIZE + j]; 77bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximityChar += 0; 78bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka AKLOGI("--- (%d)%c", i, proximityChar); 79bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 80bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 81bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 82bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 83bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 846e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa static AK_FORCE_INLINE int getStartIndexFromCoordinates(const int x, const int y, 856e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int cellHeight, const int cellWidth, const int gridWidth) { 866e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa return ((y / cellHeight) * gridWidth + (x / cellWidth)) * MAX_PROXIMITY_CHARS_SIZE; 87bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 88bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 890c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2, 900c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float y2) { 9129432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa return GeometryUtils::SQUARE_FLOAT(x1 - x2) + GeometryUtils::SQUARE_FLOAT(y1 - y2); 920c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 930c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 940c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y, 950c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float x1, const float y1, const float x2, const float y2, const bool extend) { 960c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray1x = x - x1; 970c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray1y = y - y1; 980c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray2x = x2 - x1; 990c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float ray2y = y2 - y1; 1000c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1010c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float dotProduct = ray1x * ray2x + ray1y * ray2y; 10229432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x) 10329432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa + GeometryUtils::SQUARE_FLOAT(ray2y); 104a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi if (lineLengthSqr <= 0.0f) { 105a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi // Return point to the point distance. 106a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi return getSquaredDistanceFloat(x, y, x1, y1); 107a1e0ef4836f59a9fd5a2b44ecb94c27227e159c6Keisuke Kuroyanagi } 1080c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa const float projectionLengthSqr = dotProduct / lineLengthSqr; 1090c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1100c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionX; 1110c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa float projectionY; 1120c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa if (!extend && projectionLengthSqr < 0.0f) { 1130c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1; 1140c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1; 1150c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else if (!extend && projectionLengthSqr > 1.0f) { 1160c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x2; 1170c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y2; 1180c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } else { 1190c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionX = x1 + projectionLengthSqr * ray2x; 1200c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa projectionY = y1 + projectionLengthSqr * ray2y; 1210c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1220c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa return getSquaredDistanceFloat(x, y, projectionX, projectionY); 1230c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa } 1240c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa 1257a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi static AK_FORCE_INLINE bool isMatchOrProximityChar(const ProximityType type) { 1267a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi return type == MATCH_CHAR || type == PROXIMITY_CHAR || type == ADDITIONAL_PROXIMITY_CHAR; 1277a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi } 1287a06a792871c38517264fcb63b80a9c09bfe4766Keisuke Kuroynagi 129bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka private: 130bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoUtils); 131bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 132bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static bool isOnKey(const int *const keyXCoordinates, const int *const keyYCoordinates, 133bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyWidths, const int *keyHeights, const int keyId, const int x, 134bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int y) { 135bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case 136bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 137bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 138bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId] + 1; 139bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 140bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; 141bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 142bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 143d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa static AK_FORCE_INLINE void calculateProximities(const int *const keyXCoordinates, 1446e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 1456e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int *const proximityCharsArray, const int cellHeight, const int cellWidth, 146bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int gridWidth, const int mostCommonKeyWidth, const int keyCount, 1474ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard const int x, const int y, const int primaryKey, const std::vector<int> *locale, 1488ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa const std::unordered_map<int, int> *const codeToKeyMap, int *proximities) { 149bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int mostCommonKeyWidthSquare = mostCommonKeyWidth * mostCommonKeyWidth; 150bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int insertPos = 0; 151bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = primaryKey; 1529fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi if (x == NOT_A_COORDINATE || y == NOT_A_COORDINATE) { 1539fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 1549fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi proximities[i] = NOT_A_CODE_POINT; 1559fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi } 1569fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi return; 1579fd50e34a863c18da42d6cfc8f62986a387dd5f8Keisuke Kuroyanagi } 1586e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa const int startIndex = getStartIndexFromCoordinates(x, y, cellHeight, cellWidth, gridWidth); 159bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (startIndex >= 0) { 1606e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 161bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int c = proximityCharsArray[startIndex + i]; 162bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (c < KEYCODE_SPACE || c == primaryKey) { 163bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 164bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 165bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyIndex = getKeyIndexOf(keyCount, c, codeToKeyMap); 166bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const bool onKey = isOnKey(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, 167bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyIndex, x, y); 168bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int distance = squaredLengthToEdge(keyXCoordinates, keyYCoordinates, 169bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka keyWidths, keyHeights, keyIndex, x, y); 170bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (onKey || distance < mostCommonKeyWidthSquare) { 171bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = c; 1726e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 173bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 174bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 175bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 176bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 177bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 178bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 179bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 180bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int additionalProximitySize = 1814ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard AdditionalProximityChars::getAdditionalCharsSize(locale, primaryKey); 182bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (additionalProximitySize > 0) { 183bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; 1846e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 185bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 186bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 187bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 188bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 189bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 190bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 191bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *additionalProximityChars = 1924ef27c035892888df82d9c9f32ac12ed48c8308fJean Chalard AdditionalProximityChars::getAdditionalChars(locale, primaryKey); 193bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (int j = 0; j < additionalProximitySize; ++j) { 194bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int ac = additionalProximityChars[j]; 195bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka int k = 0; 196bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka for (; k < insertPos; ++k) { 197bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (ac == proximities[k]) { 198bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka break; 199bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 200bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 201bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (k < insertPos) { 202bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka continue; 203bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 204bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[insertPos++] = ac; 2056e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 206bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka if (DEBUG_DICT) { 207bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka ASSERT(false); 208bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 209bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return; 210bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 211bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 212bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 213bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 214bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // Add a delimiter for the proximity characters 2156e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 216bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka proximities[i] = NOT_A_CODE_POINT; 217bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 218bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 219bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka 220bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka static int squaredLengthToEdge(const int *const keyXCoordinates, 221bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights, 222bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int keyId, const int x, const int y) { 223bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka // NOT_A_ID is -1, but return whenever < 0 just in case 224830ba67498c6da53b38212dd9ac5ba318a00de11Satoshi Kataoka if (keyId < 0) return MAX_VALUE_FOR_WEIGHTING; 225bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int left = keyXCoordinates[keyId]; 226bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int top = keyYCoordinates[keyId]; 227bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int right = left + keyWidths[keyId]; 228bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int bottom = top + keyHeights[keyId]; 229bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeX = x < left ? left : (x > right ? right : x); 230bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int edgeY = y < top ? top : (y > bottom ? bottom : y); 231bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dx = x - edgeX; 232bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka const int dy = y - edgeY; 233bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka return dx * dx + dy * dy; 234bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka } 235bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka}; 236bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka} // namespace latinime 237bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka#endif // LATINIME_PROXIMITY_INFO_UTILS_H 238