proximity_info.cpp revision ccebd5cefe0b6b17676edd8639f62bb708a7dd2e
18fbd55229243cb66c03d5ea1f79dfb39f596590dsatok/* 28fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * Copyright (C) 2011 The Android Open Source Project 38fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * 48fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * Licensed under the Apache License, Version 2.0 (the "License"); 58fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * you may not use this file except in compliance with the License. 68fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * You may obtain a copy of the License at 78fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * 88fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * http://www.apache.org/licenses/LICENSE-2.0 98fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * 108fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * Unless required by applicable law or agreed to in writing, software 118fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * distributed under the License is distributed on an "AS IS" BASIS, 128fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * See the License for the specific language governing permissions and 148fbd55229243cb66c03d5ea1f79dfb39f596590dsatok * limitations under the License. 158fbd55229243cb66c03d5ea1f79dfb39f596590dsatok */ 168fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 17f1008c550168e50f930ea1e043000b395ce0f129Ken Wakasa#include <cstring> 188fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 19817e517e463cb32726ff5a62196ac8744848e29bsatok#define LOG_TAG "LatinIME: proximity_info.cpp" 20817e517e463cb32726ff5a62196ac8744848e29bsatok 21552c3c27f04e6769e40cffbce3a9e8eed1269294satok#include "additional_proximity_chars.h" 2277e8e81ad95cfc1eb8f8407fc872674b8d08bbe9Ken Wakasa#include "char_utils.h" 233b088a2f365a9ce06f58243c83cb961ea2920b7eKen Wakasa#include "defines.h" 246b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka#include "geometry_utils.h" 25bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa#include "jni.h" 268fbd55229243cb66c03d5ea1f79dfb39f596590dsatok#include "proximity_info.h" 278fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 288fbd55229243cb66c03d5ea1f79dfb39f596590dsatoknamespace latinime { 29ce9e52a12a6af8fca0eba42aaae24602fbd5c998Ken Wakasa 30162c211b44c1546b2e9be36e0cec50de497217a9Ken Wakasa/* static */ const float ProximityInfo::NOT_A_DISTANCE_FLOAT = -1.0f; 31162c211b44c1546b2e9be36e0cec50de497217a9Ken Wakasa 326e66349ed1d37c24a1a23bf117df6750ad53d322Ken Wakasastatic AK_FORCE_INLINE void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray, 336e66349ed1d37c24a1a23bf117df6750ad53d322Ken Wakasa jsize len, jint *buffer) { 34bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa if (jArray && buffer) { 35bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa env->GetIntArrayRegion(jArray, 0, len, buffer); 36bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa } else if (buffer) { 3744d9c1ebfc2a847233190f6201ae97b22df30ae7Ken Wakasa memset(buffer, 0, len * sizeof(buffer[0])); 38de2f8424ea7e201ab8ee0d3c64fac0b52514d24eYusuke Nojima } 39de2f8424ea7e201ab8ee0d3c64fac0b52514d24eYusuke Nojima} 40de2f8424ea7e201ab8ee0d3c64fac0b52514d24eYusuke Nojima 416e66349ed1d37c24a1a23bf117df6750ad53d322Ken Wakasastatic AK_FORCE_INLINE void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray, 426e66349ed1d37c24a1a23bf117df6750ad53d322Ken Wakasa jsize len, jfloat *buffer) { 43bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa if (jArray && buffer) { 44bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa env->GetFloatArrayRegion(jArray, 0, len, buffer); 45bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa } else if (buffer) { 4644d9c1ebfc2a847233190f6201ae97b22df30ae7Ken Wakasa memset(buffer, 0, len * sizeof(buffer[0])); 47bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa } 48bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa} 49bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa 50015114592460cca82e5196f2c2e2eff23f9d97aeKen WakasaProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize, 51552c3c27f04e6769e40cffbce3a9e8eed1269294satok const int keyboardWidth, const int keyboardHeight, const int gridWidth, 52bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars, 53bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates, 54bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes, 55bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs, 56bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa const jfloatArray sweetSpotRadii) 57162c211b44c1546b2e9be36e0cec50de497217a9Ken Wakasa : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), GRID_WIDTH(gridWidth), 58162c211b44c1546b2e9be36e0cec50de497217a9Ken Wakasa GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth), 59a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth), 60817e517e463cb32726ff5a62196ac8744848e29bsatok CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth), 610e1f656c1be7f2916cf57c94d99b001795856270Yusuke Nojima CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight), 62258bfe66e0fcfc89b59534a9cc7f50ff07d5f78dYusuke Nojima KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), 6395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight), 64a4c1f1c1fde5e9492523842dd95a4c9f17f40c3aYusuke Nojima HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates 65a4c1f1c1fde5e9492523842dd95a4c9f17f40c3aYusuke Nojima && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs 66162c211b44c1546b2e9be36e0cec50de497217a9Ken Wakasa && sweetSpotCenterYs && sweetSpotRadii), 671d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE 68132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang /* proximityGridLength */]), 69132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang mCodeToKeyMap() { 701035bc990d9d704d8cf1002548e5dddb3ba96797satok const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; 71817e517e463cb32726ff5a62196ac8744848e29bsatok if (DEBUG_PROXIMITY_INFO) { 729fb6f47a6a11f62d134d4d6259181ac987fc1ad3satok AKLOGI("Create proximity info array %d", proximityGridLength); 73817e517e463cb32726ff5a62196ac8744848e29bsatok } 74015114592460cca82e5196f2c2e2eff23f9d97aeKen Wakasa const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr); 759e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) { 769e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length); 77ccebd5cefe0b6b17676edd8639f62bb708a7dd2eKen Wakasa ASSERT(false); 789e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa } 799e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa memset(mLocaleStr, 0, sizeof(mLocaleStr)); 809e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr); 81bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityGridLength, mProximityCharsArray); 82bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates); 83bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroIntArrayRegion(env, keyYCoordinates, KEY_COUNT, mKeyYCoordinates); 84bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroIntArrayRegion(env, keyWidths, KEY_COUNT, mKeyWidths); 85bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroIntArrayRegion(env, keyHeights, KEY_COUNT, mKeyHeights); 86f2789819bd005b5b0581e8439601b5501306327dKen Wakasa safeGetOrFillZeroIntArrayRegion(env, keyCharCodes, KEY_COUNT, mKeyCodePoints); 87bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterXs, KEY_COUNT, mSweetSpotCenterXs); 88bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs); 89bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii); 906b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka initializeG(); 910e1f656c1be7f2916cf57c94d99b001795856270Yusuke Nojima} 920e1f656c1be7f2916cf57c94d99b001795856270Yusuke Nojima 938fbd55229243cb66c03d5ea1f79dfb39f596590dsatokProximityInfo::~ProximityInfo() { 948fbd55229243cb66c03d5ea1f79dfb39f596590dsatok delete[] mProximityCharsArray; 958fbd55229243cb66c03d5ea1f79dfb39f596590dsatok} 96817e517e463cb32726ff5a62196ac8744848e29bsatok 97817e517e463cb32726ff5a62196ac8744848e29bsatokinline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const { 983c4bb7747d1a16d6b9d2d34992bad250069632a7satok return ((y / CELL_HEIGHT) * GRID_WIDTH + (x / CELL_WIDTH)) 99817e517e463cb32726ff5a62196ac8744848e29bsatok * MAX_PROXIMITY_CHARS_SIZE; 100817e517e463cb32726ff5a62196ac8744848e29bsatok} 101817e517e463cb32726ff5a62196ac8744848e29bsatok 102817e517e463cb32726ff5a62196ac8744848e29bsatokbool ProximityInfo::hasSpaceProximity(const int x, const int y) const { 103744dab691e45ff8c5ca9745ee673f50060bcb7a9satok if (x < 0 || y < 0) { 104744dab691e45ff8c5ca9745ee673f50060bcb7a9satok if (DEBUG_DICT) { 1059fb6f47a6a11f62d134d4d6259181ac987fc1ad3satok AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y); 106f2789819bd005b5b0581e8439601b5501306327dKen Wakasa // TODO: Enable this assertion. 107ccebd5cefe0b6b17676edd8639f62bb708a7dd2eKen Wakasa //ASSERT(false); 108744dab691e45ff8c5ca9745ee673f50060bcb7a9satok } 109744dab691e45ff8c5ca9745ee673f50060bcb7a9satok return false; 110744dab691e45ff8c5ca9745ee673f50060bcb7a9satok } 111744dab691e45ff8c5ca9745ee673f50060bcb7a9satok 112817e517e463cb32726ff5a62196ac8744848e29bsatok const int startIndex = getStartIndexFromCoordinates(x, y); 113817e517e463cb32726ff5a62196ac8744848e29bsatok if (DEBUG_PROXIMITY_INFO) { 1149fb6f47a6a11f62d134d4d6259181ac987fc1ad3satok AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y); 115817e517e463cb32726ff5a62196ac8744848e29bsatok } 1161d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa int *proximityCharsArray = mProximityCharsArray; 117817e517e463cb32726ff5a62196ac8744848e29bsatok for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 118817e517e463cb32726ff5a62196ac8744848e29bsatok if (DEBUG_PROXIMITY_INFO) { 1199fb6f47a6a11f62d134d4d6259181ac987fc1ad3satok AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]); 120817e517e463cb32726ff5a62196ac8744848e29bsatok } 1213e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka if (proximityCharsArray[startIndex + i] == KEYCODE_SPACE) { 122817e517e463cb32726ff5a62196ac8744848e29bsatok return true; 123817e517e463cb32726ff5a62196ac8744848e29bsatok } 124817e517e463cb32726ff5a62196ac8744848e29bsatok } 125817e517e463cb32726ff5a62196ac8744848e29bsatok return false; 1268fbd55229243cb66c03d5ea1f79dfb39f596590dsatok} 127ce9e52a12a6af8fca0eba42aaae24602fbd5c998Ken Wakasa 1280edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataokafloat ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG( 129e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka const int keyId, const int x, const int y) const { 1300edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const static float verticalSweetSpotScaleForGeometric = 1.1f; 1310edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const bool correctTouchPosition = hasTouchPositionCorrectionData(); 1320edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const float centerX = static_cast<float>(correctTouchPosition 1330edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka ? getSweetSpotCenterXAt(keyId) 1340edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka : getKeyCenterXOfKeyIdG(keyId)); 1350edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const float visualKeyCenterY = static_cast<float>(getKeyCenterYOfKeyIdG(keyId)); 1360edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka float centerY; 1370edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka if (correctTouchPosition) { 1380edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId)); 1390edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka const float gapY = sweetSpotCenterY - visualKeyCenterY; 1400edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka centerY = visualKeyCenterY + gapY * verticalSweetSpotScaleForGeometric; 1410edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka } else { 1420edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka centerY = visualKeyCenterY; 1430edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka } 144e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka const float touchX = static_cast<float>(x); 145e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka const float touchY = static_cast<float>(y); 146e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka const float keyWidth = static_cast<float>(getMostCommonKeyWidth()); 147e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka return getNormalizedSquaredDistanceFloat(centerX, centerY, touchX, touchY, keyWidth); 148e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka} 149e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka 1509df4a4527a9bc2e671f644d6e2ec0121385740ecsatokint ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) const { 151081616cd2f472295449268cecb570771b969cba3Jean Chalard if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case 152a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int left = mKeyXCoordinates[keyId]; 153a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int top = mKeyYCoordinates[keyId]; 1541caff47ecdfcf413df709371a919cf9377e26bf7satok const int right = left + mKeyWidths[keyId]; 155a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int bottom = top + mKeyHeights[keyId]; 156a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int edgeX = x < left ? left : (x > right ? right : x); 157a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int edgeY = y < top ? top : (y > bottom ? bottom : y); 158a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int dx = x - edgeX; 159a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int dy = y - edgeY; 160a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok return dx * dx + dy * dy; 161a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok} 162a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok 163a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satokvoid ProximityInfo::calculateNearbyKeyCodes( 1641d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int x, const int y, const int primaryKey, int *inputCodes) const { 1651d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa int *proximityCharsArray = mProximityCharsArray; 166a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok int insertPos = 0; 167a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok inputCodes[insertPos++] = primaryKey; 168a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok const int startIndex = getStartIndexFromCoordinates(x, y); 16952612a0d1b0ce7796fa0a0b50bfda172ebc2a5efJean Chalard if (startIndex >= 0) { 17088ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 1711d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int c = proximityCharsArray[startIndex + i]; 17288ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (c < KEYCODE_SPACE || c == primaryKey) { 17388ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard continue; 17488ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard } 175f2789819bd005b5b0581e8439601b5501306327dKen Wakasa const int keyIndex = getKeyIndexOf(c); 17688ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard const bool onKey = isOnKey(keyIndex, x, y); 17788ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard const int distance = squaredDistanceToEdge(keyIndex, x, y); 17888ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) { 17988ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard inputCodes[insertPos++] = c; 18088ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 18188ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (DEBUG_DICT) { 182ccebd5cefe0b6b17676edd8639f62bb708a7dd2eKen Wakasa ASSERT(false); 18388ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard } 18488ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard return; 1850cb2097a45a41875ec2265da316eb770565b6706satok } 186a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok } 187a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok } 18888ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard const int additionalProximitySize = 189015114592460cca82e5196f2c2e2eff23f9d97aeKen Wakasa AdditionalProximityChars::getAdditionalCharsSize(mLocaleStr, primaryKey); 19088ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (additionalProximitySize > 0) { 19188ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; 19288ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 1933094d12cdcf0583b44f1b32468f0189b530d8c73Jean Chalard if (DEBUG_DICT) { 194ccebd5cefe0b6b17676edd8639f62bb708a7dd2eKen Wakasa ASSERT(false); 1953094d12cdcf0583b44f1b32468f0189b530d8c73Jean Chalard } 1963094d12cdcf0583b44f1b32468f0189b530d8c73Jean Chalard return; 1971caff47ecdfcf413df709371a919cf9377e26bf7satok } 1981caff47ecdfcf413df709371a919cf9377e26bf7satok 1991d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int *additionalProximityChars = 200015114592460cca82e5196f2c2e2eff23f9d97aeKen Wakasa AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey); 20188ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard for (int j = 0; j < additionalProximitySize; ++j) { 2021d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int ac = additionalProximityChars[j]; 20388ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard int k = 0; 20488ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard for (; k < insertPos; ++k) { 2051d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa if (ac == inputCodes[k]) { 20688ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard break; 20788ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard } 2085eec574cf0eb6b8ec23723b5f566563453edd42fsatok } 20988ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (k < insertPos) { 21088ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard continue; 2110cb2097a45a41875ec2265da316eb770565b6706satok } 21288ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard inputCodes[insertPos++] = ac; 21388ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { 21488ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard if (DEBUG_DICT) { 215ccebd5cefe0b6b17676edd8639f62bb708a7dd2eKen Wakasa ASSERT(false); 21688ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard } 21788ec125cfcbb06e84f611dd26097efa9731979b7Jean Chalard return; 2183094d12cdcf0583b44f1b32468f0189b530d8c73Jean Chalard } 2190cb2097a45a41875ec2265da316eb770565b6706satok } 2205eec574cf0eb6b8ec23723b5f566563453edd42fsatok } 22152612a0d1b0ce7796fa0a0b50bfda172ebc2a5efJean Chalard } 2220cb2097a45a41875ec2265da316eb770565b6706satok // Add a delimiter for the proximity characters 2231caff47ecdfcf413df709371a919cf9377e26bf7satok for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { 224f2789819bd005b5b0581e8439601b5501306327dKen Wakasa inputCodes[i] = NOT_A_CODE_POINT; 2251caff47ecdfcf413df709371a919cf9377e26bf7satok } 226a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok} 227a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok 228f2789819bd005b5b0581e8439601b5501306327dKen Wakasaint ProximityInfo::getKeyIndexOf(const int c) const { 2291caff47ecdfcf413df709371a919cf9377e26bf7satok if (KEY_COUNT == 0) { 230a4c1f1c1fde5e9492523842dd95a4c9f17f40c3aYusuke Nojima // We do not have the coordinate data 231bbc25607f01cf9a0cdbc3e8664b27c7f26bd6e18Jean Chalard return NOT_AN_INDEX; 23216717159fffc7731669143a8e9ed866e7d88ecefYusuke Nojima } 233ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (c == NOT_A_CODE_POINT) { 234ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return NOT_AN_INDEX; 235ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 2361d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int lowerCode = toLowerCase(c); 237f34ec5aa9557d9986a296c3e636b5c1ab42ff641Tom Ouyang hash_map_compat<int, int>::const_iterator mapPos = mCodeToKeyMap.find(lowerCode); 238132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang if (mapPos != mCodeToKeyMap.end()) { 239132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang return mapPos->second; 24016717159fffc7731669143a8e9ed866e7d88ecefYusuke Nojima } 241132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang return NOT_AN_INDEX; 24216717159fffc7731669143a8e9ed866e7d88ecefYusuke Nojima} 243efb63246c2e5df29d62416d48f62e2b57b14de7cSatoshi Kataoka 244f2789819bd005b5b0581e8439601b5501306327dKen Wakasaint ProximityInfo::getCodePointOf(const int keyIndex) const { 2456b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka if (keyIndex < 0 || keyIndex >= KEY_COUNT) { 246f2789819bd005b5b0581e8439601b5501306327dKen Wakasa return NOT_A_CODE_POINT; 2476b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 248f2789819bd005b5b0581e8439601b5501306327dKen Wakasa return mKeyIndexToCodePointG[keyIndex]; 2496b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2506b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 2516b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataokavoid ProximityInfo::initializeG() { 252e7398cdb2b48eb52dc9676c8efa75bc7cb9af3e9Satoshi Kataoka // TODO: Optimize 2536b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka for (int i = 0; i < KEY_COUNT; ++i) { 254f2789819bd005b5b0581e8439601b5501306327dKen Wakasa const int code = mKeyCodePoints[i]; 2551d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa const int lowerCode = toLowerCase(code); 2566b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2; 2576b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2; 258132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang mCodeToKeyMap[lowerCode] = i; 259132168519e1d681ea1b8fd7fcf283155a0b3997eTom Ouyang mKeyIndexToCodePointG[i] = lowerCode; 2606b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 2616b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka for (int i = 0; i < KEY_COUNT; i++) { 2626b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka mKeyKeyDistancesG[i][i] = 0; 2636b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka for (int j = i + 1; j < KEY_COUNT; j++) { 264bcec82de66f52655593dc233346f11468f5077a0Ken Wakasa mKeyKeyDistancesG[i][j] = getDistanceInt( 2656b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]); 2666b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j]; 2676b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 2686b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 2696b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2706b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 2715964d4e607008d29cca3bc07c878fbc7eb540a1bKen Wakasaint ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const { 272f2789819bd005b5b0581e8439601b5501306327dKen Wakasa return getKeyCenterXOfKeyIdG(getKeyIndexOf(charCode)); 2736b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2746b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 2755964d4e607008d29cca3bc07c878fbc7eb540a1bKen Wakasaint ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const { 276f2789819bd005b5b0581e8439601b5501306327dKen Wakasa return getKeyCenterYOfKeyIdG(getKeyIndexOf(charCode)); 2776b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2786b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 2795964d4e607008d29cca3bc07c878fbc7eb540a1bKen Wakasaint ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const { 2806b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka if (keyId >= 0) { 2816b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka return mCenterXsG[keyId]; 2826b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 2836b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka return 0; 2846b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2856b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 2865964d4e607008d29cca3bc07c878fbc7eb540a1bKen Wakasaint ProximityInfo::getKeyCenterYOfKeyIdG(int keyId) const { 2876b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka if (keyId >= 0) { 2886b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka return mCenterYsG[keyId]; 2896b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 2906b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka return 0; 2916b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 2926b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka 293ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagiint ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const { 2946b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka if (keyId0 >= 0 && keyId1 >= 0) { 2956b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka return mKeyKeyDistancesG[keyId0][keyId1]; 2966b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka } 29707aea409ba400da22067b1048bf2bd00c07c4e4cJean Chalard return MAX_POINT_TO_KEY_LENGTH; 2986b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka} 299ce9e52a12a6af8fca0eba42aaae24602fbd5c998Ken Wakasa} // namespace latinime 300