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
178fbd55229243cb66c03d5ea1f79dfb39f596590dsatok#ifndef LATINIME_PROXIMITY_INFO_H
188fbd55229243cb66c03d5ea1f79dfb39f596590dsatok#define LATINIME_PROXIMITY_INFO_H
198fbd55229243cb66c03d5ea1f79dfb39f596590dsatok
208ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa#include <unordered_map>
218ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa
228fbd55229243cb66c03d5ea1f79dfb39f596590dsatok#include "defines.h"
23bb005f787f4e00bd832e6a78797be10af2994061Ken Wakasa#include "jni.h"
2429432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/proximity_info_utils.h"
258fbd55229243cb66c03d5ea1f79dfb39f596590dsatok
268fbd55229243cb66c03d5ea1f79dfb39f596590dsatoknamespace latinime {
278fbd55229243cb66c03d5ea1f79dfb39f596590dsatok
288fbd55229243cb66c03d5ea1f79dfb39f596590dsatokclass ProximityInfo {
29e12e9b5b69e6242af61ee690a81bedde1bdd4936Ken Wakasa public:
306c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa    ProximityInfo(JNIEnv *env, const jstring localeJStr,
31a58ebc73ae3eb2783713c471d8abb348c7dfc8daTadashi G. Takaoka            const int keyboardWidth, const int keyboardHeight, const int gridWidth,
3287fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi            const int gridHeight, const int mostCommonKeyWidth, const int mostCommonKeyHeight,
3387fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi            const jintArray proximityChars, const int keyCount, const jintArray keyXCoordinates,
3487fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi            const jintArray keyYCoordinates, const jintArray keyWidths, const jintArray keyHeights,
3587fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi            const jintArray keyCharCodes, const jfloatArray sweetSpotCenterXs,
3687fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi            const jfloatArray sweetSpotCenterYs, const jfloatArray sweetSpotRadii);
378fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    ~ProximityInfo();
38817e517e463cb32726ff5a62196ac8744848e29bsatok    bool hasSpaceProximity(const int x, const int y) const;
390edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka    float getNormalizedSquaredDistanceFromCenterFloatG(
400052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi            const int keyId, const int x, const int y, const bool isGeometric) const;
41f2789819bd005b5b0581e8439601b5501306327dKen Wakasa    int getCodePointOf(const int keyIndex) const;
422fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int getOriginalCodePointOf(const int keyIndex) const;
433e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    bool hasSweetSpotData(const int keyIndex) const {
443e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka        // When there are no calibration data for a key,
453e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka        // the radius of the key is assigned to zero.
46fee0ac60b1cd0a4760ca8f310ff8a86b925d833bKen Wakasa        return mSweetSpotRadii[keyIndex] > 0.0f;
473e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
48a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    float getSweetSpotRadiiAt(int keyIndex) const { return mSweetSpotRadii[keyIndex]; }
49a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    float getSweetSpotCenterXAt(int keyIndex) const { return mSweetSpotCenterXs[keyIndex]; }
50a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    float getSweetSpotCenterYAt(int keyIndex) const { return mSweetSpotCenterYs[keyIndex]; }
51a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    bool hasTouchPositionCorrectionData() const { return HAS_TOUCH_POSITION_CORRECTION_DATA; }
52a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getMostCommonKeyWidth() const { return MOST_COMMON_KEY_WIDTH; }
53a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getMostCommonKeyWidthSquare() const { return MOST_COMMON_KEY_WIDTH_SQUARE; }
5487fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi    float getNormalizedSquaredMostCommonKeyHypotenuse() const {
5587fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi        return NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE;
5687fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi    }
57a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getKeyCount() const { return KEY_COUNT; }
58a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getCellHeight() const { return CELL_HEIGHT; }
59a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getCellWidth() const { return CELL_WIDTH; }
60a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getGridWidth() const { return GRID_WIDTH; }
61a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getGridHeight() const { return GRID_HEIGHT; }
62a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getKeyboardWidth() const { return KEYBOARD_WIDTH; }
63a47c699faadfe9ab677f52c29a7c61fd7ff9b492Ken Wakasa    int getKeyboardHeight() const { return KEYBOARD_HEIGHT; }
64625778fd36f4b304d9bc70c87be7fdc0f717cb50Tom Ouyang    float getKeyboardHypotenuse() const { return KEYBOARD_HYPOTENUSE; }
6595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi
660052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi    int getKeyCenterXOfKeyIdG(
670052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi            const int keyId, const int referencePointX, const bool isGeometric) const;
680052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi    int getKeyCenterYOfKeyIdG(
690052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi            const int keyId, const int referencePointY, const bool isGeometric) const;
70ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    int getKeyKeyDistanceG(int keyId0, int keyId1) const;
716b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka
72697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka    AK_FORCE_INLINE void initializeProximities(const int *const inputCodes,
73d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa            const int *const inputXCoordinates, const int *const inputYCoordinates,
74d74214d7266bdd53fc69971fd82b59a7a92d8c63Ken Wakasa            const int inputSize, int *allInputCodes) const {
75bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka        ProximityInfoUtils::initializeProximities(inputCodes, inputXCoordinates, inputYCoordinates,
76bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka                inputSize, mKeyXCoordinates, mKeyYCoordinates, mKeyWidths, mKeyHeights,
776e2ba9b01e61d214e8d6fad8d7093a80a97dd243Ken Wakasa                mProximityCharsArray, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH, MOST_COMMON_KEY_WIDTH,
782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                KEY_COUNT, mLocaleStr, &mLowerCodePointToKeyMap, allInputCodes);
79bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka    }
80bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka
81697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka    AK_FORCE_INLINE int getKeyIndexOf(const int c) const {
822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, c, &mLowerCodePointToKeyMap);
83bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka    }
84bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka
85697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka    AK_FORCE_INLINE bool isCodePointOnKeyboard(const int codePoint) const {
86697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka        return getKeyIndexOf(codePoint) != NOT_AN_INDEX;
87697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka    }
88697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka
89e12e9b5b69e6242af61ee690a81bedde1bdd4936Ken Wakasa private:
901bc038c5e40bd0fa7a44331a569abe3ae88f0152satok    DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo);
910e1f656c1be7f2916cf57c94d99b001795856270Yusuke Nojima
926b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka    void initializeG();
93c25c7ccf25dd45464b82d29adca067f9a941c11cYusuke Nojima
948fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    const int GRID_WIDTH;
958fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    const int GRID_HEIGHT;
966b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka    const int MOST_COMMON_KEY_WIDTH;
97a70ee6e3b3fe65acab205b935ebd52e7bb0eccb8satok    const int MOST_COMMON_KEY_WIDTH_SQUARE;
9887fdde6ec48844ddbb482c50fbda226c63ca5e85Keisuke Kuroynagi    const float NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE;
99de3070a71b39742c3ac7b613f45af88cc95c1205Ken Wakasa    const int CELL_WIDTH;
100de3070a71b39742c3ac7b613f45af88cc95c1205Ken Wakasa    const int CELL_HEIGHT;
1010e1f656c1be7f2916cf57c94d99b001795856270Yusuke Nojima    const int KEY_COUNT;
10295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    const int KEYBOARD_WIDTH;
10395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    const int KEYBOARD_HEIGHT;
104625778fd36f4b304d9bc70c87be7fdc0f717cb50Tom Ouyang    const float KEYBOARD_HYPOTENUSE;
105a4c1f1c1fde5e9492523842dd95a4c9f17f40c3aYusuke Nojima    const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
1069e15b4551eaff96c3cde6e99132a1aab3900f923Ken Wakasa    // Assuming locale strings such as en_US, sr-Latn etc.
1079e15b4551eaff96c3cde6e99132a1aab3900f923Ken Wakasa    static const int MAX_LOCALE_STRING_LENGTH = 10;
1089e0c711a6230af1db0753af401804c95e4bee69dKen Wakasa    char mLocaleStr[MAX_LOCALE_STRING_LENGTH];
1091d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int *mProximityCharsArray;
1101d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
1111d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
1121d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int mKeyWidths[MAX_KEY_COUNT_IN_A_KEYBOARD];
1131d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int mKeyHeights[MAX_KEY_COUNT_IN_A_KEYBOARD];
1141d516fb1b08002cea6db060c9f8196d96ba5e428Ken Wakasa    int mKeyCodePoints[MAX_KEY_COUNT_IN_A_KEYBOARD];
115ad35835baccb4101c3d8766fadbf4d127e41b6cbYusuke Nojima    float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
116ad35835baccb4101c3d8766fadbf4d127e41b6cbYusuke Nojima    float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
1170052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi    // Sweet spots for geometric input. Note that we have extra sweet spots only for Y coordinates.
1180052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi    float mSweetSpotCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
119ad35835baccb4101c3d8766fadbf4d127e41b6cbYusuke Nojima    float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
1208ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa    std::unordered_map<int, int> mLowerCodePointToKeyMap;
1212fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int mKeyIndexToOriginalCodePoint[MAX_KEY_COUNT_IN_A_KEYBOARD];
1222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int mKeyIndexToLowerCodePointG[MAX_KEY_COUNT_IN_A_KEYBOARD];
1236b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka    int mCenterXsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
1246b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka    int mCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
1256b4a1d79eba19a55715e20b4ee75b3934f397db2Satoshi Kataoka    int mKeyKeyDistancesG[MAX_KEY_COUNT_IN_A_KEYBOARD][MAX_KEY_COUNT_IN_A_KEYBOARD];
1268fbd55229243cb66c03d5ea1f79dfb39f596590dsatok};
127ce9e52a12a6af8fca0eba42aaae24602fbd5c998Ken Wakasa} // namespace latinime
1288fbd55229243cb66c03d5ea1f79dfb39f596590dsatok#endif // LATINIME_PROXIMITY_INFO_H
129