Add functions to calculate proximity characters in the native code

Bug: 4343280

Change-Id: I17f8f6295b01900948b98680d0267753f33a46cf
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index 6e4fefd..844b230 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -30,7 +30,7 @@
 
 static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object,
         jint maxProximityCharsSize, jint displayWidth, jint displayHeight, jint gridWidth,
-        jint gridHeight, jintArray proximityCharsArray, jint keyCount,
+        jint gridHeight, jint mostCommonkeyWidth, jintArray proximityCharsArray, jint keyCount,
         jintArray keyXCoordinateArray, jintArray keyYCoordinateArray, jintArray keyWidthArray,
         jintArray keyHeightArray, jintArray keyCharCodeArray,
         jfloatArray sweetSpotCenterXArray, jfloatArray sweetSpotCenterYArray,
@@ -45,7 +45,8 @@
     jfloat *sweetSpotCenterYs = safeGetFloatArrayElements(env, sweetSpotCenterYArray);
     jfloat *sweetSpotRadii = safeGetFloatArrayElements(env, sweetSpotRadiusArray);
     ProximityInfo *proximityInfo = new ProximityInfo(maxProximityCharsSize, displayWidth,
-            displayHeight, gridWidth, gridHeight, (const uint32_t*)proximityChars,
+            displayHeight, gridWidth, gridHeight, mostCommonkeyWidth,
+            (const uint32_t*)proximityChars,
             keyCount, (const int32_t*)keyXCoordinates, (const int32_t*)keyYCoordinates,
             (const int32_t*)keyWidths, (const int32_t*)keyHeights, (const int32_t*)keyCharCodes,
             (const float*)sweetSpotCenterXs, (const float*)sweetSpotCenterYs,
@@ -69,7 +70,7 @@
 }
 
 static JNINativeMethod sKeyboardMethods[] = {
-    {"setProximityInfoNative", "(IIIII[II[I[I[I[I[I[F[F[F)J",
+    {"setProximityInfoNative", "(IIIIII[II[I[I[I[I[I[F[F[F)J",
             (void*)latinime_Keyboard_setProximityInfo},
     {"releaseProximityInfoNative", "(J)V", (void*)latinime_Keyboard_release}
 };
diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp
index b6bab22..ad19f58 100644
--- a/native/src/proximity_info.cpp
+++ b/native/src/proximity_info.cpp
@@ -35,12 +35,14 @@
 
 ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
         const int keyboardHeight, const int gridWidth, const int gridHeight,
+        const int mostCommonKeyWidth,
         const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates,
         const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights,
         const int32_t *keyCharCodes, const float *sweetSpotCenterXs, const float *sweetSpotCenterYs,
         const float *sweetSpotRadii)
         : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth),
           KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight),
+          MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
           CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth),
           CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight),
           KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)),
@@ -123,6 +125,47 @@
     return false;
 }
 
+bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) {
+    const int left = mKeyXCoordinates[keyId];
+    const int top = mKeyYCoordinates[keyId];
+    const int right = left + mKeyWidths[keyId] + 1;
+    const int bottom = top + mKeyHeights[keyId];
+    return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
+}
+
+int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) {
+    const int left = mKeyXCoordinates[keyId];
+    const int top = mKeyYCoordinates[keyId];
+    const int right = left + mKeyWidths[keyId] + 1;
+    const int bottom = top + mKeyHeights[keyId];
+    const int edgeX = x < left ? left : (x > right ? right : x);
+    const int edgeY = y < top ? top : (y > bottom ? bottom : y);
+    const int dx = x - edgeX;
+    const int dy = y - edgeY;
+    return dx * dx + dy * dy;
+}
+
+void ProximityInfo::calculateNearbyKeyCodes(
+        const int x, const int y, const uint32_t primaryKey, int *inputCodes) {
+    int insertPos = 0;
+    inputCodes[insertPos++] = primaryKey;
+    const int startIndex = getStartIndexFromCoordinates(x, y);
+    for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
+        const uint32_t c = mProximityCharsArray[startIndex + i];
+        if (c < KEYCODE_SPACE || c == primaryKey) {
+            continue;
+        }
+        for (int j = 0; j < KEY_COUNT; ++j) {
+            const bool onKey = isOnKey(j, x, y);
+            const int distance = squaredDistanceToEdge(j, x, y);
+            if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) {
+                inputCodes[insertPos++] = c;
+            }
+        }
+    }
+    // TODO: calculate additional chars
+}
+
 // TODO: Calculate nearby codes here.
 void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength,
         const int* xCoordinates, const int* yCoordinates) {
diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h
index b77c1bb..caabadf 100644
--- a/native/src/proximity_info.h
+++ b/native/src/proximity_info.h
@@ -45,13 +45,14 @@
 
     ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth,
             const int keybaordHeight, const int gridWidth, const int gridHeight,
+            const int mostCommonkeyWidth,
             const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates,
             const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights,
             const int32_t *keyCharCodes, const float *sweetSpotCenterXs,
             const float *sweetSpotCenterYs, const float *sweetSpotRadii);
     ~ProximityInfo();
     bool hasSpaceProximity(const int x, const int y) const;
-    void setInputParams(const int* inputCodes, const int inputLength,
+    void setInputParams(const int *inputCodes, const int inputLength,
             const int *xCoordinates, const int *yCoordinates);
     const int* getProximityCharsAt(const int index) const;
     unsigned short getPrimaryCharAt(const int index) const;
@@ -87,12 +88,17 @@
         // the radius of the key is assigned to zero.
         return mSweetSpotRadii[keyIndex] > 0.0;
     }
+    bool isOnKey(const int keyId, const int x, const int y);
+    int squaredDistanceToEdge(const int keyId, const int x, const int y);
+    void calculateNearbyKeyCodes(
+            const int x, const int y, const uint32_t primaryKey, int *inputCodes);
 
     const int MAX_PROXIMITY_CHARS_SIZE;
     const int KEYBOARD_WIDTH;
     const int KEYBOARD_HEIGHT;
     const int GRID_WIDTH;
     const int GRID_HEIGHT;
+    const int MOST_COMMON_KEY_WIDTH_SQUARE;
     const int CELL_WIDTH;
     const int CELL_HEIGHT;
     const int KEY_COUNT;