blob: 8157fe2d0945b6d241ec93fc3589e44c438297e9 [file] [log] [blame]
satok8fbd5522011-02-22 17:28:55 +09001/*
2 * Copyright (C) 2011 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
Ken Wakasaf1008c52012-07-31 17:56:40 +090017#include <cstring>
satok8fbd5522011-02-22 17:28:55 +090018
satok817e5172011-03-04 06:06:45 -080019#define LOG_TAG "LatinIME: proximity_info.cpp"
20
satok552c3c22012-03-13 16:33:47 +090021#include "additional_proximity_chars.h"
Ken Wakasa77e8e812012-08-02 19:48:08 +090022#include "char_utils.h"
Ken Wakasa3b088a22012-05-16 23:05:32 +090023#include "defines.h"
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +090024#include "geometry_utils.h"
Ken Wakasabb005f72012-08-08 20:43:47 +090025#include "jni.h"
satok8fbd5522011-02-22 17:28:55 +090026#include "proximity_info.h"
27
28namespace latinime {
Ken Wakasace9e52a2011-06-18 13:09:55 +090029
Ken Wakasa162c2112012-08-24 14:51:15 +090030/* static */ const float ProximityInfo::NOT_A_DISTANCE_FLOAT = -1.0f;
31
Ken Wakasa6e663492012-11-03 02:50:47 +090032static AK_FORCE_INLINE void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray,
33 jsize len, jint *buffer) {
Ken Wakasabb005f72012-08-08 20:43:47 +090034 if (jArray && buffer) {
35 env->GetIntArrayRegion(jArray, 0, len, buffer);
36 } else if (buffer) {
Ken Wakasa44d9c1e2012-11-01 17:05:08 +090037 memset(buffer, 0, len * sizeof(buffer[0]));
Yusuke Nojimade2f8422011-09-27 11:15:18 +090038 }
39}
40
Ken Wakasa6e663492012-11-03 02:50:47 +090041static AK_FORCE_INLINE void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray,
42 jsize len, jfloat *buffer) {
Ken Wakasabb005f72012-08-08 20:43:47 +090043 if (jArray && buffer) {
44 env->GetFloatArrayRegion(jArray, 0, len, buffer);
45 } else if (buffer) {
Ken Wakasa44d9c1e2012-11-01 17:05:08 +090046 memset(buffer, 0, len * sizeof(buffer[0]));
Ken Wakasabb005f72012-08-08 20:43:47 +090047 }
48}
49
Ken Wakasa6c224392013-01-22 13:14:53 +090050ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr,
satok552c3c22012-03-13 16:33:47 +090051 const int keyboardWidth, const int keyboardHeight, const int gridWidth,
Ken Wakasabb005f72012-08-08 20:43:47 +090052 const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars,
53 const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates,
54 const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes,
55 const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs,
56 const jfloatArray sweetSpotRadii)
Ken Wakasa6c224392013-01-22 13:14:53 +090057 : GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth),
satoka70ee6e2012-03-07 15:12:22 +090058 MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
satok817e5172011-03-04 06:06:45 -080059 CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
Yusuke Nojima0e1f6562011-09-21 12:02:47 +090060 CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
Yusuke Nojima258bfe62011-09-28 12:59:43 +090061 KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
Keisuke Kuroyanagi95a49a52012-09-04 17:00:24 +090062 KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight),
Yusuke Nojimaa4c1f1c2011-10-06 19:12:20 +090063 HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
64 && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
Ken Wakasa162c2112012-08-24 14:51:15 +090065 && sweetSpotCenterYs && sweetSpotRadii),
Ken Wakasa1d516fb2012-12-03 19:43:15 +090066 mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE
Ken Wakasa6c224392013-01-22 13:14:53 +090067 /* proximityCharsLength */]),
Tom Ouyang13216852012-09-03 12:50:21 -070068 mCodeToKeyMap() {
Ken Wakasa6c224392013-01-22 13:14:53 +090069 /* Let's check the input array length here to make sure */
70 const jsize proximityCharsLength = env->GetArrayLength(proximityChars);
71 if (proximityCharsLength != GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE) {
72 AKLOGE("Invalid proximityCharsLength: %d", proximityCharsLength);
73 ASSERT(false);
74 return;
75 }
satok817e5172011-03-04 06:06:45 -080076 if (DEBUG_PROXIMITY_INFO) {
Ken Wakasa6c224392013-01-22 13:14:53 +090077 AKLOGI("Create proximity info array %d", proximityCharsLength);
satok817e5172011-03-04 06:06:45 -080078 }
Ken Wakasa01511452012-08-09 15:58:15 +090079 const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090080 if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
81 AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
Ken Wakasaccebd5c2013-01-09 15:21:44 +090082 ASSERT(false);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090083 }
84 memset(mLocaleStr, 0, sizeof(mLocaleStr));
85 env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
Ken Wakasa6c224392013-01-22 13:14:53 +090086 safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityCharsLength,
87 mProximityCharsArray);
Ken Wakasabb005f72012-08-08 20:43:47 +090088 safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates);
89 safeGetOrFillZeroIntArrayRegion(env, keyYCoordinates, KEY_COUNT, mKeyYCoordinates);
90 safeGetOrFillZeroIntArrayRegion(env, keyWidths, KEY_COUNT, mKeyWidths);
91 safeGetOrFillZeroIntArrayRegion(env, keyHeights, KEY_COUNT, mKeyHeights);
Ken Wakasaf2789812012-09-04 12:49:46 +090092 safeGetOrFillZeroIntArrayRegion(env, keyCharCodes, KEY_COUNT, mKeyCodePoints);
Ken Wakasabb005f72012-08-08 20:43:47 +090093 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterXs, KEY_COUNT, mSweetSpotCenterXs);
94 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs);
95 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +090096 initializeG();
Yusuke Nojima0e1f6562011-09-21 12:02:47 +090097}
98
satok8fbd5522011-02-22 17:28:55 +090099ProximityInfo::~ProximityInfo() {
100 delete[] mProximityCharsArray;
101}
satok817e5172011-03-04 06:06:45 -0800102
satok817e5172011-03-04 06:06:45 -0800103bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
satok744dab62011-12-15 22:29:05 +0900104 if (x < 0 || y < 0) {
105 if (DEBUG_DICT) {
satok9fb6f472012-01-13 18:01:22 +0900106 AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
Ken Wakasaf2789812012-09-04 12:49:46 +0900107 // TODO: Enable this assertion.
Ken Wakasaccebd5c2013-01-09 15:21:44 +0900108 //ASSERT(false);
satok744dab62011-12-15 22:29:05 +0900109 }
110 return false;
111 }
112
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900113 const int startIndex = ProximityInfoUtils::getStartIndexFromCoordinates(
114 MAX_PROXIMITY_CHARS_SIZE, x, y, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH);
satok817e5172011-03-04 06:06:45 -0800115 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900116 AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
satok817e5172011-03-04 06:06:45 -0800117 }
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900118 int *proximityCharsArray = mProximityCharsArray;
satok817e5172011-03-04 06:06:45 -0800119 for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
120 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900121 AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
satok817e5172011-03-04 06:06:45 -0800122 }
Satoshi Kataoka3e8c58f2012-06-05 17:55:52 +0900123 if (proximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
satok817e5172011-03-04 06:06:45 -0800124 return true;
125 }
126 }
127 return false;
128}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900129
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900130float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900131 const int keyId, const int x, const int y) const {
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900132 const static float verticalSweetSpotScaleForGeometric = 1.1f;
133 const bool correctTouchPosition = hasTouchPositionCorrectionData();
134 const float centerX = static_cast<float>(correctTouchPosition
135 ? getSweetSpotCenterXAt(keyId)
136 : getKeyCenterXOfKeyIdG(keyId));
137 const float visualKeyCenterY = static_cast<float>(getKeyCenterYOfKeyIdG(keyId));
138 float centerY;
139 if (correctTouchPosition) {
140 const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
141 const float gapY = sweetSpotCenterY - visualKeyCenterY;
142 centerY = visualKeyCenterY + gapY * verticalSweetSpotScaleForGeometric;
143 } else {
144 centerY = visualKeyCenterY;
145 }
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900146 const float touchX = static_cast<float>(x);
147 const float touchY = static_cast<float>(y);
148 const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
Ken Wakasa0c2227a2013-01-21 11:37:54 +0900149 return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
150 / SQUARE_FLOAT(keyWidth);
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900151}
152
Ken Wakasaf2789812012-09-04 12:49:46 +0900153int ProximityInfo::getCodePointOf(const int keyIndex) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900154 if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900155 return NOT_A_CODE_POINT;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900156 }
Ken Wakasaf2789812012-09-04 12:49:46 +0900157 return mKeyIndexToCodePointG[keyIndex];
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900158}
159
160void ProximityInfo::initializeG() {
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900161 // TODO: Optimize
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900162 for (int i = 0; i < KEY_COUNT; ++i) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900163 const int code = mKeyCodePoints[i];
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900164 const int lowerCode = toLowerCase(code);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900165 mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
166 mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
Tom Ouyang13216852012-09-03 12:50:21 -0700167 mCodeToKeyMap[lowerCode] = i;
168 mKeyIndexToCodePointG[i] = lowerCode;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900169 }
170 for (int i = 0; i < KEY_COUNT; i++) {
171 mKeyKeyDistancesG[i][i] = 0;
172 for (int j = i + 1; j < KEY_COUNT; j++) {
Satoshi Kataoka47cc5242013-01-21 16:33:24 +0900173 mKeyKeyDistancesG[i][j] = getDistanceInt(
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900174 mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
175 mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
176 }
177 }
178}
179
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900180int ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900181 return getKeyCenterXOfKeyIdG(
182 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900183}
184
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900185int ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900186 return getKeyCenterYOfKeyIdG(
187 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900188}
189
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900190int ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900191 if (keyId >= 0) {
192 return mCenterXsG[keyId];
193 }
194 return 0;
195}
196
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900197int ProximityInfo::getKeyCenterYOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900198 if (keyId >= 0) {
199 return mCenterYsG[keyId];
200 }
201 return 0;
202}
203
Keisuke Kuroyanagiff74cc32012-10-11 13:08:06 +0900204int ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900205 if (keyId0 >= 0 && keyId1 >= 0) {
206 return mKeyKeyDistancesG[keyId0][keyId1];
207 }
Jean Chalard07aea402012-08-29 20:09:27 +0900208 return MAX_POINT_TO_KEY_LENGTH;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900209}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900210} // namespace latinime