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 <cstring> // for memset()
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "defines.h"
25 #include "suggest/core/layout/proximity_info_params.h"
26 #include "suggest/core/layout/proximity_info_state_utils.h"
27 
28 namespace latinime {
29 
30 class ProximityInfo;
31 
32 class ProximityInfoState {
33  public:
34     /////////////////////////////////////////
35     // Defined in proximity_info_state.cpp //
36     /////////////////////////////////////////
37     void initInputParams(const int pointerId, const float maxPointToKeyLength,
38             const ProximityInfo *proximityInfo, const int *const inputCodes,
39             const int inputSize, const int *xCoordinates, const int *yCoordinates,
40             const int *const times, const int *const pointerIds, const bool isGeometric,
41             const std::vector<int> *locale);
42 
43     /////////////////////////////////////////
44     // Defined here                        //
45     /////////////////////////////////////////
ProximityInfoState()46     AK_FORCE_INLINE ProximityInfoState()
47             : mProximityInfo(nullptr), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f),
48               mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0),
49               mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
50               mIsContinuousSuggestionPossible(false), mHasBeenUpdatedByGeometricInput(false),
51               mSampledInputXs(), mSampledInputYs(), mSampledTimes(), mSampledInputIndice(),
52               mSampledLengthCache(), mBeelineSpeedPercentiles(),
53               mSampledNormalizedSquaredLengthCache(), mSpeedRates(), mDirections(),
54               mCharProbabilities(), mSampledSearchKeySets(), mSampledSearchKeyVectors(),
55               mTouchPositionCorrectionEnabled(false), mSampledInputSize(0),
56               mMostProbableStringProbability(0.0f) {
57         memset(mInputProximities, 0, sizeof(mInputProximities));
58         memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
59         memset(mMostProbableString, 0, sizeof(mMostProbableString));
60     }
61 
62     // Non virtual inline destructor -- never inherit this class
~ProximityInfoState()63     AK_FORCE_INLINE ~ProximityInfoState() {}
64 
getPrimaryCodePointAt(const int index)65     inline int getPrimaryCodePointAt(const int index) const {
66         return getProximityCodePointsAt(index)[0];
67     }
68 
69     int getPrimaryOriginalCodePointAt(const int index) const;
70 
sameAsTyped(const int * word,int length)71     inline bool sameAsTyped(const int *word, int length) const {
72         if (length != mSampledInputSize) {
73             return false;
74         }
75         const int *inputProximities = mInputProximities;
76         while (length--) {
77             if (*inputProximities != *word) {
78                 return false;
79             }
80             inputProximities += MAX_PROXIMITY_CHARS_SIZE;
81             word++;
82         }
83         return true;
84     }
85 
existsCodePointInProximityAt(const int index,const int c)86     AK_FORCE_INLINE bool existsCodePointInProximityAt(const int index, const int c) const {
87         const int *codePoints = getProximityCodePointsAt(index);
88         int i = 0;
89         while (codePoints[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE) {
90             if (codePoints[i++] == c) {
91                 return true;
92             }
93         }
94         return false;
95     }
96 
existsAdjacentProximityChars(const int index)97     AK_FORCE_INLINE bool existsAdjacentProximityChars(const int index) const {
98         if (index < 0 || index >= mSampledInputSize) return false;
99         const int currentCodePoint = getPrimaryCodePointAt(index);
100         const int leftIndex = index - 1;
101         if (leftIndex >= 0 && existsCodePointInProximityAt(leftIndex, currentCodePoint)) {
102             return true;
103         }
104         const int rightIndex = index + 1;
105         if (rightIndex < mSampledInputSize
106                 && existsCodePointInProximityAt(rightIndex, currentCodePoint)) {
107             return true;
108         }
109         return false;
110     }
111 
touchPositionCorrectionEnabled()112     inline bool touchPositionCorrectionEnabled() const {
113         return mTouchPositionCorrectionEnabled;
114     }
115 
isUsed()116     bool isUsed() const {
117         return mSampledInputSize > 0;
118     }
119 
size()120     int size() const {
121         return mSampledInputSize;
122     }
123 
getInputX(const int index)124     int getInputX(const int index) const {
125         return mSampledInputXs[index];
126     }
127 
getInputY(const int index)128     int getInputY(const int index) const {
129         return mSampledInputYs[index];
130     }
131 
getInputIndexOfSampledPoint(const int sampledIndex)132     int getInputIndexOfSampledPoint(const int sampledIndex) const {
133         return mSampledInputIndice[sampledIndex];
134     }
135 
136     bool hasSpaceProximity(const int index) const;
137 
getLengthCache(const int index)138     int getLengthCache(const int index) const {
139         return mSampledLengthCache[index];
140     }
141 
isContinuousSuggestionPossible()142     bool isContinuousSuggestionPossible() const {
143         return mIsContinuousSuggestionPossible;
144     }
145 
146     // TODO: Rename s/Length/NormalizedSquaredLength/
147     float getPointToKeyByIdLength(const int inputIndex, const int keyId) const;
148     // TODO: Rename s/Length/NormalizedSquaredLength/
149     float getPointToKeyLength(const int inputIndex, const int codePoint) const;
150 
151     ProximityType getProximityType(const int index, const int codePoint,
152             const bool checkProximityChars, int *proximityIndex = 0) const;
153 
154     ProximityType getProximityTypeG(const int index, const int codePoint) const;
155 
getSpeedRate(const int index)156     float getSpeedRate(const int index) const {
157         return mSpeedRates[index];
158     }
159 
getBeelineSpeedPercentile(const int id)160     AK_FORCE_INLINE int getBeelineSpeedPercentile(const int id) const {
161         return mBeelineSpeedPercentiles[id];
162     }
163 
getDoubleLetterLevel(const int id)164     AK_FORCE_INLINE DoubleLetterLevel getDoubleLetterLevel(const int id) const {
165         const int beelineSpeedRate = getBeelineSpeedPercentile(id);
166         if (beelineSpeedRate == 0) {
167             return A_STRONG_DOUBLE_LETTER;
168         } else if (beelineSpeedRate
169                 < ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE) {
170             return A_DOUBLE_LETTER;
171         } else {
172             return NOT_A_DOUBLE_LETTER;
173         }
174     }
175 
getDirection(const int index)176     float getDirection(const int index) const {
177         return mDirections[index];
178     }
179     // get xy direction
180     float getDirection(const int x, const int y) const;
181 
182     float getMostProbableString(int *const codePointBuf) const;
183 
184     float getProbability(const int index, const int charCode) const;
185 
186     bool isKeyInSerchKeysAfterIndex(const int index, const int keyId) const;
187 
188  private:
189     DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
190 
getProximityCodePointsAt(const int index)191     inline const int *getProximityCodePointsAt(const int index) const {
192         return ProximityInfoStateUtils::getProximityCodePointsAt(mInputProximities, index);
193     }
194 
195     // const
196     const ProximityInfo *mProximityInfo;
197     float mMaxPointToKeyLength;
198     float mAverageSpeed;
199     bool mHasTouchPositionCorrectionData;
200     int mMostCommonKeyWidthSquare;
201     int mKeyCount;
202     int mCellHeight;
203     int mCellWidth;
204     int mGridHeight;
205     int mGridWidth;
206     bool mIsContinuousSuggestionPossible;
207     bool mHasBeenUpdatedByGeometricInput;
208 
209     std::vector<int> mSampledInputXs;
210     std::vector<int> mSampledInputYs;
211     std::vector<int> mSampledTimes;
212     std::vector<int> mSampledInputIndice;
213     std::vector<int> mSampledLengthCache;
214     std::vector<int> mBeelineSpeedPercentiles;
215     std::vector<float> mSampledNormalizedSquaredLengthCache;
216     std::vector<float> mSpeedRates;
217     std::vector<float> mDirections;
218     // probabilities of skipping or mapping to a key for each point.
219     std::vector<std::unordered_map<int, float>> mCharProbabilities;
220     // The vector for the key code set which holds nearby keys of some trailing sampled input points
221     // for each sampled input point. These nearby keys contain the next characters which can be in
222     // the dictionary. Specifically, currently we are looking for keys nearby trailing sampled
223     // inputs including the current input point.
224     std::vector<ProximityInfoStateUtils::NearKeycodesSet> mSampledSearchKeySets;
225     std::vector<std::vector<int>> mSampledSearchKeyVectors;
226     bool mTouchPositionCorrectionEnabled;
227     int mInputProximities[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH];
228     int mSampledInputSize;
229     int mPrimaryInputWord[MAX_WORD_LENGTH];
230     float mMostProbableStringProbability;
231     int mMostProbableString[MAX_WORD_LENGTH];
232 };
233 } // namespace latinime
234 #endif // LATINIME_PROXIMITY_INFO_STATE_H
235