blob: 81eb0b37d806c427675d454e61a82db0c956b5c4 [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>
Tom Ouyang625778f2013-02-08 11:35:19 -080018#include <cmath>
satok8fbd5522011-02-22 17:28:55 +090019
satok817e5172011-03-04 06:06:45 -080020#define LOG_TAG "LatinIME: proximity_info.cpp"
21
satok552c3c22012-03-13 16:33:47 +090022#include "additional_proximity_chars.h"
Ken Wakasa77e8e812012-08-02 19:48:08 +090023#include "char_utils.h"
Ken Wakasa3b088a22012-05-16 23:05:32 +090024#include "defines.h"
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +090025#include "geometry_utils.h"
Ken Wakasabb005f72012-08-08 20:43:47 +090026#include "jni.h"
satok8fbd5522011-02-22 17:28:55 +090027#include "proximity_info.h"
Ken Wakasaee456af2013-02-01 19:59:40 +090028#include "proximity_info_params.h"
satok8fbd5522011-02-22 17:28:55 +090029
30namespace latinime {
Ken Wakasace9e52a2011-06-18 13:09:55 +090031
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),
Tom Ouyang625778f2013-02-08 11:35:19 -080063 KEYBOARD_HYPOTENUSE(hypotf(KEYBOARD_WIDTH, KEYBOARD_HEIGHT)),
Yusuke Nojimaa4c1f1c2011-10-06 19:12:20 +090064 HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
65 && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
Ken Wakasa162c2112012-08-24 14:51:15 +090066 && sweetSpotCenterYs && sweetSpotRadii),
Ken Wakasa1d516fb2012-12-03 19:43:15 +090067 mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE
Ken Wakasa6c224392013-01-22 13:14:53 +090068 /* proximityCharsLength */]),
Tom Ouyang13216852012-09-03 12:50:21 -070069 mCodeToKeyMap() {
Ken Wakasa6c224392013-01-22 13:14:53 +090070 /* Let's check the input array length here to make sure */
71 const jsize proximityCharsLength = env->GetArrayLength(proximityChars);
72 if (proximityCharsLength != GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE) {
73 AKLOGE("Invalid proximityCharsLength: %d", proximityCharsLength);
74 ASSERT(false);
75 return;
76 }
satok817e5172011-03-04 06:06:45 -080077 if (DEBUG_PROXIMITY_INFO) {
Ken Wakasa6c224392013-01-22 13:14:53 +090078 AKLOGI("Create proximity info array %d", proximityCharsLength);
satok817e5172011-03-04 06:06:45 -080079 }
Ken Wakasa01511452012-08-09 15:58:15 +090080 const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090081 if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
82 AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
Ken Wakasaccebd5c2013-01-09 15:21:44 +090083 ASSERT(false);
Ken Wakasa9e0c7112012-08-09 22:26:58 +090084 }
85 memset(mLocaleStr, 0, sizeof(mLocaleStr));
86 env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
Ken Wakasa6c224392013-01-22 13:14:53 +090087 safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityCharsLength,
88 mProximityCharsArray);
Ken Wakasabb005f72012-08-08 20:43:47 +090089 safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates);
90 safeGetOrFillZeroIntArrayRegion(env, keyYCoordinates, KEY_COUNT, mKeyYCoordinates);
91 safeGetOrFillZeroIntArrayRegion(env, keyWidths, KEY_COUNT, mKeyWidths);
92 safeGetOrFillZeroIntArrayRegion(env, keyHeights, KEY_COUNT, mKeyHeights);
Ken Wakasaf2789812012-09-04 12:49:46 +090093 safeGetOrFillZeroIntArrayRegion(env, keyCharCodes, KEY_COUNT, mKeyCodePoints);
Ken Wakasabb005f72012-08-08 20:43:47 +090094 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterXs, KEY_COUNT, mSweetSpotCenterXs);
95 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs);
96 safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +090097 initializeG();
Yusuke Nojima0e1f6562011-09-21 12:02:47 +090098}
99
satok8fbd5522011-02-22 17:28:55 +0900100ProximityInfo::~ProximityInfo() {
101 delete[] mProximityCharsArray;
102}
satok817e5172011-03-04 06:06:45 -0800103
satok817e5172011-03-04 06:06:45 -0800104bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
satok744dab62011-12-15 22:29:05 +0900105 if (x < 0 || y < 0) {
106 if (DEBUG_DICT) {
satok9fb6f472012-01-13 18:01:22 +0900107 AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
Ken Wakasaf2789812012-09-04 12:49:46 +0900108 // TODO: Enable this assertion.
Ken Wakasaccebd5c2013-01-09 15:21:44 +0900109 //ASSERT(false);
satok744dab62011-12-15 22:29:05 +0900110 }
111 return false;
112 }
113
Ken Wakasa6e2ba9b2013-01-30 19:24:03 +0900114 const int startIndex = ProximityInfoUtils::getStartIndexFromCoordinates(x, y,
115 CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH);
satok817e5172011-03-04 06:06:45 -0800116 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900117 AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
satok817e5172011-03-04 06:06:45 -0800118 }
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900119 int *proximityCharsArray = mProximityCharsArray;
satok817e5172011-03-04 06:06:45 -0800120 for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
121 if (DEBUG_PROXIMITY_INFO) {
satok9fb6f472012-01-13 18:01:22 +0900122 AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
satok817e5172011-03-04 06:06:45 -0800123 }
Satoshi Kataoka3e8c58f2012-06-05 17:55:52 +0900124 if (proximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
satok817e5172011-03-04 06:06:45 -0800125 return true;
126 }
127 }
128 return false;
129}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900130
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900131float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900132 const int keyId, const int x, const int y) const {
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900133 const bool correctTouchPosition = hasTouchPositionCorrectionData();
Ken Wakasaee456af2013-02-01 19:59:40 +0900134 const float centerX = static_cast<float>(correctTouchPosition ? getSweetSpotCenterXAt(keyId)
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900135 : getKeyCenterXOfKeyIdG(keyId));
136 const float visualKeyCenterY = static_cast<float>(getKeyCenterYOfKeyIdG(keyId));
137 float centerY;
138 if (correctTouchPosition) {
139 const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
140 const float gapY = sweetSpotCenterY - visualKeyCenterY;
Ken Wakasaee456af2013-02-01 19:59:40 +0900141 centerY = visualKeyCenterY + gapY * ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G;
Satoshi Kataoka0edab9d2012-09-24 18:29:31 +0900142 } else {
143 centerY = visualKeyCenterY;
144 }
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900145 const float touchX = static_cast<float>(x);
146 const float touchY = static_cast<float>(y);
147 const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
Ken Wakasa0c2227a2013-01-21 11:37:54 +0900148 return ProximityInfoUtils::getSquaredDistanceFloat(centerX, centerY, touchX, touchY)
149 / SQUARE_FLOAT(keyWidth);
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900150}
151
Ken Wakasaf2789812012-09-04 12:49:46 +0900152int ProximityInfo::getCodePointOf(const int keyIndex) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900153 if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900154 return NOT_A_CODE_POINT;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900155 }
Ken Wakasaf2789812012-09-04 12:49:46 +0900156 return mKeyIndexToCodePointG[keyIndex];
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900157}
158
159void ProximityInfo::initializeG() {
Satoshi Kataokae7398cd2012-08-13 20:20:04 +0900160 // TODO: Optimize
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900161 for (int i = 0; i < KEY_COUNT; ++i) {
Ken Wakasaf2789812012-09-04 12:49:46 +0900162 const int code = mKeyCodePoints[i];
Ken Wakasa1d516fb2012-12-03 19:43:15 +0900163 const int lowerCode = toLowerCase(code);
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900164 mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
165 mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
Tom Ouyang13216852012-09-03 12:50:21 -0700166 mCodeToKeyMap[lowerCode] = i;
167 mKeyIndexToCodePointG[i] = lowerCode;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900168 }
169 for (int i = 0; i < KEY_COUNT; i++) {
170 mKeyKeyDistancesG[i][i] = 0;
171 for (int j = i + 1; j < KEY_COUNT; j++) {
Satoshi Kataoka47cc5242013-01-21 16:33:24 +0900172 mKeyKeyDistancesG[i][j] = getDistanceInt(
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900173 mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
174 mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
175 }
176 }
177}
178
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900179int ProximityInfo::getKeyCenterXOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900180 return getKeyCenterXOfKeyIdG(
181 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900182}
183
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900184int ProximityInfo::getKeyCenterYOfCodePointG(int charCode) const {
Satoshi Kataokabf78e132013-01-17 19:46:12 +0900185 return getKeyCenterYOfKeyIdG(
186 ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, charCode, &mCodeToKeyMap));
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900187}
188
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900189int ProximityInfo::getKeyCenterXOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900190 if (keyId >= 0) {
191 return mCenterXsG[keyId];
192 }
193 return 0;
194}
195
Ken Wakasa5964d4e2012-09-10 16:49:36 +0900196int ProximityInfo::getKeyCenterYOfKeyIdG(int keyId) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900197 if (keyId >= 0) {
198 return mCenterYsG[keyId];
199 }
200 return 0;
201}
202
Keisuke Kuroyanagiff74cc32012-10-11 13:08:06 +0900203int ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const {
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900204 if (keyId0 >= 0 && keyId1 >= 0) {
205 return mKeyKeyDistancesG[keyId0][keyId1];
206 }
Jean Chalard07aea402012-08-29 20:09:27 +0900207 return MAX_POINT_TO_KEY_LENGTH;
Satoshi Kataoka6b4a1d72012-08-10 15:42:56 +0900208}
Ken Wakasace9e52a2011-06-18 13:09:55 +0900209} // namespace latinime