Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2012 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 
     17 #ifndef LATINIME_PROXIMITY_INFO_STATE_H
     18 #define LATINIME_PROXIMITY_INFO_STATE_H
     19 
     20 #include <bitset>
     21 #include <cstring> // for memset()
     22 #include <stdint.h>
     23 #include <string>
     24 #include <vector>
     25 
     26 #include "char_utils.h"
     27 #include "defines.h"
     28 #include "hash_map_compat.h"
     29 
     30 namespace latinime {
     31 
     32 class ProximityInfo;
     33 
     34 class ProximityInfoState {
     35  public:
     36     typedef std::bitset<MAX_KEY_COUNT_IN_A_KEYBOARD> NearKeycodesSet;
     37     static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
     38     static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
     39     static const float NOT_A_DISTANCE_FLOAT;
     40     static const int NOT_A_CODE;
     41 
     42     /////////////////////////////////////////
     43     // Defined in proximity_info_state.cpp //
     44     /////////////////////////////////////////
     45     void initInputParams(const int pointerId, const float maxPointToKeyLength,
     46             const ProximityInfo *proximityInfo, const int32_t *const inputCodes,
     47             const int inputSize, const int *xCoordinates, const int *yCoordinates,
     48             const int *const times, const int *const pointerIds, const bool isGeometric);
     49 
     50     /////////////////////////////////////////
     51     // Defined here                        //
     52     /////////////////////////////////////////
     53     ProximityInfoState()
     54             : mProximityInfo(0), mMaxPointToKeyLength(0),
     55               mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(),
     56               mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
     57               mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(),
     58               mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mNearKeysVector(),
     59               mTouchPositionCorrectionEnabled(false), mInputSize(0) {
     60         memset(mInputCodes, 0, sizeof(mInputCodes));
     61         memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
     62         memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
     63     }
     64 
     65     virtual ~ProximityInfoState() {}
     66 
     67     inline unsigned short getPrimaryCharAt(const int index) const {
     68         return getProximityCharsAt(index)[0];
     69     }
     70 
     71     inline bool existsCharInProximityAt(const int index, const int c) const {
     72         const int *chars = getProximityCharsAt(index);
     73         int i = 0;
     74         while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) {
     75             if (chars[i++] == c) {
     76                 return true;
     77             }
     78         }
     79         return false;
     80     }
     81 
     82     inline bool existsAdjacentProximityChars(const int index) const {
     83         if (index < 0 || index >= mInputSize) return false;
     84         const int currentChar = getPrimaryCharAt(index);
     85         const int leftIndex = index - 1;
     86         if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) {
     87             return true;
     88         }
     89         const int rightIndex = index + 1;
     90         if (rightIndex < mInputSize && existsCharInProximityAt(rightIndex, currentChar)) {
     91             return true;
     92         }
     93         return false;
     94     }
     95 
     96     // In the following function, c is the current character of the dictionary word
     97     // currently examined.
     98     // currentChars is an array containing the keys close to the character the
     99     // user actually typed at the same position. We want to see if c is in it: if so,
    100     // then the word contains at that position a character close to what the user
    101     // typed.
    102     // What the user typed is actually the first character of the array.
    103     // proximityIndex is a pointer to the variable where getMatchedProximityId returns
    104     // the index of c in the proximity chars of the input index.
    105     // Notice : accented characters do not have a proximity list, so they are alone
    106     // in their list. The non-accented version of the character should be considered
    107     // "close", but not the other keys close to the non-accented version.
    108     inline ProximityType getMatchedProximityId(const int index,
    109             const unsigned short c, const bool checkProximityChars, int *proximityIndex = 0) const {
    110         const int *currentChars = getProximityCharsAt(index);
    111         const int firstChar = currentChars[0];
    112         const unsigned short baseLowerC = toBaseLowerCase(c);
    113 
    114         // The first char in the array is what user typed. If it matches right away,
    115         // that means the user typed that same char for this pos.
    116         if (firstChar == baseLowerC || firstChar == c) {
    117             return EQUIVALENT_CHAR;
    118         }
    119 
    120         if (!checkProximityChars) return UNRELATED_CHAR;
    121 
    122         // If the non-accented, lowercased version of that first character matches c,
    123         // then we have a non-accented version of the accented character the user
    124         // typed. Treat it as a close char.
    125         if (toBaseLowerCase(firstChar) == baseLowerC)
    126             return NEAR_PROXIMITY_CHAR;
    127 
    128         // Not an exact nor an accent-alike match: search the list of close keys
    129         int j = 1;
    130         while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
    131                 && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
    132             const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
    133             if (matched) {
    134                 if (proximityIndex) {
    135                     *proximityIndex = j;
    136                 }
    137                 return NEAR_PROXIMITY_CHAR;
    138             }
    139             ++j;
    140         }
    141         if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
    142                 && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
    143             ++j;
    144             while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
    145                     && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
    146                 const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
    147                 if (matched) {
    148                     if (proximityIndex) {
    149                         *proximityIndex = j;
    150                     }
    151                     return ADDITIONAL_PROXIMITY_CHAR;
    152                 }
    153                 ++j;
    154             }
    155         }
    156 
    157         // Was not included, signal this as an unrelated character.
    158         return UNRELATED_CHAR;
    159     }
    160 
    161     inline int getNormalizedSquaredDistance(
    162             const int inputIndex, const int proximityIndex) const {
    163         return mNormalizedSquaredDistances[
    164                 inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex];
    165     }
    166 
    167     inline const unsigned short *getPrimaryInputWord() const {
    168         return mPrimaryInputWord;
    169     }
    170 
    171     inline bool touchPositionCorrectionEnabled() const {
    172         return mTouchPositionCorrectionEnabled;
    173     }
    174 
    175     inline bool sameAsTyped(const unsigned short *word, int length) const {
    176         if (length != mInputSize) {
    177             return false;
    178         }
    179         const int *inputCodes = mInputCodes;
    180         while (length--) {
    181             if (static_cast<unsigned int>(*inputCodes) != static_cast<unsigned int>(*word)) {
    182                 return false;
    183             }
    184             inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
    185             word++;
    186         }
    187         return true;
    188     }
    189 
    190     int getDuration(const int index) const;
    191 
    192     bool isUsed() const {
    193         return mInputSize > 0;
    194     }
    195 
    196     uint32_t size() const {
    197         return mInputSize;
    198     }
    199 
    200     int getInputX(const int index) const {
    201         return mInputXs[index];
    202     }
    203 
    204     int getInputY(const int index) const {
    205         return mInputYs[index];
    206     }
    207 
    208     int getLengthCache(const int index) const {
    209         return mLengthCache[index];
    210     }
    211 
    212     bool isContinuationPossible() const {
    213         return mIsContinuationPossible;
    214     }
    215 
    216     float getPointToKeyLength(const int inputIndex, const int charCode, const float scale) const;
    217 
    218     int getSpaceY() const;
    219 
    220     int32_t getAllPossibleChars(
    221             const size_t startIndex, int32_t *const filter, const int32_t filterSize) const;
    222 
    223     float getRelativeSpeed(const int index) const {
    224         return mRelativeSpeeds[index];
    225     }
    226  private:
    227     DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
    228     typedef hash_map_compat<int, float> NearKeysDistanceMap;
    229     /////////////////////////////////////////
    230     // Defined in proximity_info_state.cpp //
    231     /////////////////////////////////////////
    232     float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
    233 
    234     float calculateSquaredDistanceFromSweetSpotCenter(
    235             const int keyIndex, const int inputIndex) const;
    236 
    237     bool pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, const int time,
    238             const bool sample, const bool isLastPoint,
    239             NearKeysDistanceMap *const currentNearKeysDistances,
    240             const NearKeysDistanceMap *const prevNearKeysDistances,
    241             const NearKeysDistanceMap *const prevPrevNearKeysDistances);
    242     /////////////////////////////////////////
    243     // Defined here                        //
    244     /////////////////////////////////////////
    245     inline float square(const float x) const { return x * x; }
    246 
    247     bool hasInputCoordinates() const {
    248         return mInputXs.size() > 0 && mInputYs.size() > 0;
    249     }
    250 
    251     inline const int *getProximityCharsAt(const int index) const {
    252         return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
    253     }
    254 
    255     float updateNearKeysDistances(const int x, const int y,
    256             NearKeysDistanceMap *const currentNearKeysDistances);
    257     bool isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances,
    258             const NearKeysDistanceMap *const prevNearKeysDistances,
    259             const NearKeysDistanceMap *const prevPrevNearKeysDistances) const;
    260     float getPointScore(
    261             const int x, const int y, const int time, const bool last, const float nearest,
    262             const NearKeysDistanceMap *const currentNearKeysDistances,
    263             const NearKeysDistanceMap *const prevNearKeysDistances,
    264             const NearKeysDistanceMap *const prevPrevNearKeysDistances) const;
    265     bool checkAndReturnIsContinuationPossible(const int inputSize, const int *const xCoordinates,
    266             const int *const yCoordinates, const int *const times);
    267     void popInputData();
    268 
    269     // const
    270     const ProximityInfo *mProximityInfo;
    271     float mMaxPointToKeyLength;
    272     bool mHasTouchPositionCorrectionData;
    273     int mMostCommonKeyWidthSquare;
    274     std::string mLocaleStr;
    275     int mKeyCount;
    276     int mCellHeight;
    277     int mCellWidth;
    278     int mGridHeight;
    279     int mGridWidth;
    280     bool mIsContinuationPossible;
    281 
    282     std::vector<int> mInputXs;
    283     std::vector<int> mInputYs;
    284     std::vector<int> mTimes;
    285     std::vector<int> mInputIndice;
    286     std::vector<float> mDistanceCache;
    287     std::vector<int>  mLengthCache;
    288     std::vector<float> mRelativeSpeeds;
    289     std::vector<NearKeycodesSet> mNearKeysVector;
    290     bool mTouchPositionCorrectionEnabled;
    291     int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
    292     int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
    293     int mInputSize;
    294     unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
    295 };
    296 } // namespace latinime
    297 #endif // LATINIME_PROXIMITY_INFO_STATE_H
    298