blob: d812745ca55c582643311a6cc60b3efdfbdea795 [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"
Ken Wakasaee456af2013-02-01 19:59:40 +090027#include "proximity_info_params.h"
satok8fbd5522011-02-22 17:28:55 +090028
29namespace latinime {
Ken Wakasace9e52a2011-06-18 13:09:55 +090030
Ken Wakasa6e663492012-11-03 02:50:47 +090031static AK_FORCE_INLINE void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray,
32 jsize len, jint *buffer) {
Ken Wakasabb005f72012-08-08 20:43:47 +090033 if (jArray && buffer) {
34 env->GetIntArrayRegion(jArray, 0, len, buffer);
35 } else if (buffer) {
Ken Wakasa44d9c1e2012-11-01 17:05:08 +090036 memset(buffer, 0, len * sizeof(buffer[0]));
Yusuke Nojimade2f8422011-09-27 11:15:18 +090037 }
38}
39
Ken Wakasa6e663492012-11-03 02:50:47 +090040static AK_FORCE_INLINE void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray,
41 jsize len, jfloat *buffer) {
Ken Wakasabb005f72012-08-08 20:43:47 +090042 if (jArray && buffer) {
43 env->GetFloatArrayRegion(jArray, 0, len, buffer);
44 } else if (buffer) {
Ken Wakasa44d9c1e2012-11-01 17:05:08 +090045 memset(buffer, 0, len * sizeof(buffer[0]));
Ken Wakasabb005f72012-08-08 20:43:47 +090046 }
47}
48
Ken Wakasa6c224392013-01-22 13:14:53 +090049ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr,
satok552c3c22012-03-13 16:33:47 +090050 const int keyboardWidth, const int keyboardHeight, const int gridWidth,
Ken Wakasabb005f72012-08-08 20:43:47 +090051 const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars,
52 const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates,
53 const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes,
54 const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs,
55 const jfloatArray sweetSpotRadii)
Ken Wakasa6c224392013-01-22 13:14:53 +090056 : GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth),
satoka70ee6e2012-03-07 15:12:22 +090057 MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
satok817e5172011-03-04 06:06:45 -080058 CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
Yusuke Nojima0e1f6562011-09-21 12:02:47 +090059 CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
Yusuke Nojima258bfe62011-09-28 12:59:43 +090060 KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
Keisuke Kuroyanagi95a49a52012-09-04 17:00:24 +090061 KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight),
Yusuke Nojimaa4c1f1c2011-10-06 19:12:20 +090062 HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
63 && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
Ken Wakasa162c2112012-08-24 14:51:15 +090064 && sweetSpotCenterYs && sweetSpotRadii),
Ken Wakasa1d516fb2012-12-03 19:43:15 +090065 mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE
Ken Wakasa6c224392013-01-22 13:14:53 +090066 /* proximityCharsLength */]),
Tom Ouyang13216852012-09-03 12:50:21 -070067 mCodeToKeyMap() {
Ken Wakasa6c224392013-01-22 13:14:53 +090068 /* Let's check the input array length here to make sure */
69 const jsize proximityCharsLength = env->GetArrayLength(proximityChars);
70 if (proximityCharsLength != GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE) {
71 AKLOGE("Invalid proximityCharsLength: %d", proximityCharsLength);
72 ASSERT(false);
73 return;
74 }
satok817e5172011-03-04 06:06:45 -080075 if (DEBUG_PROXIMITY_INFO) {
Ken Wakasa6c224392013-01-22 13:14:53 +090076 AKLOGI("Create proximity info array %d", proximityCharsLength);
satok817e5172011-03-04 06:06:45 -080077 }
Ken Wakasa01511452012-08-09 15:58:15 +090078 const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090079 if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
80 AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
Ken Wakasaccebd5c2013-01-09 15:21:44 +090081 ASSERT(false);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090082 }
83 memset(mLocaleStr, 0, sizeof(mLocaleStr));
84 env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
Ken Wakasa6c224392013-01-22 13:14:53 +090085 safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityCharsLength,
86 mProximityCharsArray);
Ken Wakasabb005f72012-08-08 20:43:47 +090087 safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates);
88 safeGetOrFillZeroIntArrayRegion(env, keyYCoordinates, KEY_COUNT, mKeyYCoordinates);
89 safeGetOrFillZeroIntArrayRegion(env, keyWidths, KEY_COUNT, mKeyWidths);
90 safeGetOrFillZeroIntArrayRegion(env, keyHeights, KEY_COUNT, mKeyHeights);
Ken Wakasaf2789812012-09-04 12:49:46 +090091 safeGetOrFillZeroIntArrayRegion(env, keyCharCodes, KEY_COUNT, mKeyCodePoints);
Ken Wakasabb005f72012-08-08 20:43:47 +090092 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterXs, KEY_COUNT, mSweetSpotCenterXs);
93 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs);
94 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +090095 initializeG();
Yusuke Nojima0e1f6562011-09-21 12:02:47 +090096}
97
satok8fbd5522011-02-22 17:28:55 +090098ProximityInfo::~ProximityInfo() {
99 delete[] mProximityCharsArray;
100}
satok817e5172011-03-04 06:06:45 -0800101
satok817e5172011-03-04 06:06:45 -0800102bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
satok744dab62011-12-15 22:29:05 +0900103 if (x < 0 || y < 0) {
104 if (DEBUG_DICT) {
satok9fb6f472012-01-13 18:01:22 +0900105 AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
Ken Wakasaf2789812012-09-04 12:49:46 +0900106 // TODO: Enable this assertion.
Ken Wakasaccebd5c2013-01-09 15:21:44 +0900107 //ASSERT(false);
satok744dab62011-12-15 22:29:05 +0900108 }
109 return false;
110 }
111
Ken Wakasa6e2ba9b2013-01-30 19:24:03 +0900112 const int startIndex = ProximityInfoUtils::getStartIndexFromCoordinates(x, y,
113 CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH);
satok817e5172011-03-04 06:06:45 -0800114 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900115 AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
satok817e5172011-03-04 06:06:45 -0800116 }
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900117 int *proximityCharsArray = mProximityCharsArray;
satok817e5172011-03-04 06:06:45 -0800118 for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
119 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900120 AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
satok817e5172011-03-04 06:06:45 -0800121 }
Satoshi Kataoka3e8c58f2012-06-05 17:55:52 +0900122 if (proximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
satok817e5172011-03-04 06:06:45 -0800123 return true;
124 }
125 }
126 return false;
127}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900128
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900129float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900130 const int keyId, const int x, const int y) const {
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900131 const bool correctTouchPosition = hasTouchPositionCorrectionData();
Ken Wakasaee456af2013-02-01 19:59:40 +0900132 const float centerX = static_cast<float>(correctTouchPosition ? getSweetSpotCenterXAt(keyId)
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900133 : getKeyCenterXOfKeyIdG(keyId));
134 const float visualKeyCenterY = static_cast<float>(getKeyCenterYOfKeyIdG(keyId));
135 float centerY;
136 if (correctTouchPosition) {
137 const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
138 const float gapY = sweetSpotCenterY - visualKeyCenterY;
Ken Wakasaee456af2013-02-01 19:59:40 +0900139 centerY = visualKeyCenterY + gapY * ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G;
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900140 } else {
141 centerY = visualKeyCenterY;
142 }
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900143 const float touchX = static_cast<float>(x);
144 const float touchY = static_cast<float>(y);
145 const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
Ken Wakasa0c2227a2013-01-21 11:37:54 +0900146 return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
147 / SQUARE_FLOAT(keyWidth);
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900148}
149
Ken Wakasaf2789812012-09-04 12:49:46 +0900150int ProximityInfo::getCodePointOf(const int keyIndex) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900151 if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900152 return NOT_A_CODE_POINT;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900153 }
Ken Wakasaf2789812012-09-04 12:49:46 +0900154 return mKeyIndexToCodePointG[keyIndex];
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900155}
156
157void ProximityInfo::initializeG() {
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900158 // TODO: Optimize
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900159 for (int i = 0; i < KEY_COUNT; ++i) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900160 const int code = mKeyCodePoints[i];
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900161 const int lowerCode = toLowerCase(code);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900162 mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
163 mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
Tom Ouyang13216852012-09-03 12:50:21 -0700164 mCodeToKeyMap[lowerCode] = i;
165 mKeyIndexToCodePointG[i] = lowerCode;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900166 }
167 for (int i = 0; i < KEY_COUNT; i++) {
168 mKeyKeyDistancesG[i][i] = 0;
169 for (int j = i + 1; j < KEY_COUNT; j++) {
Satoshi Kataoka47cc5242013-01-21 16:33:24 +0900170 mKeyKeyDistancesG[i][j] = getDistanceInt(
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900171 mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
172 mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
173 }
174 }
175}
176
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900177int ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900178 return getKeyCenterXOfKeyIdG(
179 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900180}
181
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900182int ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900183 return getKeyCenterYOfKeyIdG(
184 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900185}
186
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900187int ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900188 if (keyId >= 0) {
189 return mCenterXsG[keyId];
190 }
191 return 0;
192}
193
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900194int ProximityInfo::getKeyCenterYOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900195 if (keyId >= 0) {
196 return mCenterYsG[keyId];
197 }
198 return 0;
199}
200
Keisuke Kuroyanagiff74cc32012-10-11 13:08:06 +0900201int ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900202 if (keyId0 >= 0 && keyId1 >= 0) {
203 return mKeyKeyDistancesG[keyId0][keyId1];
204 }
Jean Chalard07aea402012-08-29 20:09:27 +0900205 return MAX_POINT_TO_KEY_LENGTH;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900206}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900207} // namespace latinime