proximity_info_state.h revision 37b153e205c9672b299b47e97921fee2462a78bb
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 <stdint.h>
22#include <string>
23#include <vector>
24
25#include "char_utils.h"
26#include "defines.h"
27
28namespace latinime {
29
30class ProximityInfo;
31
32class ProximityInfoState {
33 public:
34    static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
35    static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
36            1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
37    // The upper limit of the char code in mCodeToKeyIndex
38    static const int MAX_CHAR_CODE = 127;
39    static const float NOT_A_DISTANCE_FLOAT = -1.0f;
40    static const int NOT_A_CODE = -1;
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              mInputXs(), mInputYs(), mTimes(), mDistanceCache(), mLengthCache(),
58              mTouchPositionCorrectionEnabled(false), mInputSize(0) {
59        memset(mInputCodes, 0, sizeof(mInputCodes));
60        memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
61        memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
62    }
63
64    virtual ~ProximityInfoState() {}
65
66    inline unsigned short getPrimaryCharAt(const int index) const {
67        return getProximityCharsAt(index)[0];
68    }
69
70    inline bool existsCharInProximityAt(const int index, const int c) const {
71        const int *chars = getProximityCharsAt(index);
72        int i = 0;
73        while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) {
74            if (chars[i++] == c) {
75                return true;
76            }
77        }
78        return false;
79    }
80
81    inline bool existsAdjacentProximityChars(const int index) const {
82        if (index < 0 || index >= mInputSize) return false;
83        const int currentChar = getPrimaryCharAt(index);
84        const int leftIndex = index - 1;
85        if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) {
86            return true;
87        }
88        const int rightIndex = index + 1;
89        if (rightIndex < mInputSize && existsCharInProximityAt(rightIndex, currentChar)) {
90            return true;
91        }
92        return false;
93    }
94
95    // In the following function, c is the current character of the dictionary word
96    // currently examined.
97    // currentChars is an array containing the keys close to the character the
98    // user actually typed at the same position. We want to see if c is in it: if so,
99    // then the word contains at that position a character close to what the user
100    // typed.
101    // What the user typed is actually the first character of the array.
102    // proximityIndex is a pointer to the variable where getMatchedProximityId returns
103    // the index of c in the proximity chars of the input index.
104    // Notice : accented characters do not have a proximity list, so they are alone
105    // in their list. The non-accented version of the character should be considered
106    // "close", but not the other keys close to the non-accented version.
107    inline ProximityType getMatchedProximityId(const int index,
108            const unsigned short c, const bool checkProximityChars, int *proximityIndex = 0) const {
109        const int *currentChars = getProximityCharsAt(index);
110        const int firstChar = currentChars[0];
111        const unsigned short baseLowerC = toBaseLowerCase(c);
112
113        // The first char in the array is what user typed. If it matches right away,
114        // that means the user typed that same char for this pos.
115        if (firstChar == baseLowerC || firstChar == c) {
116            return EQUIVALENT_CHAR;
117        }
118
119        if (!checkProximityChars) return UNRELATED_CHAR;
120
121        // If the non-accented, lowercased version of that first character matches c,
122        // then we have a non-accented version of the accented character the user
123        // typed. Treat it as a close char.
124        if (toBaseLowerCase(firstChar) == baseLowerC)
125            return NEAR_PROXIMITY_CHAR;
126
127        // Not an exact nor an accent-alike match: search the list of close keys
128        int j = 1;
129        while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
130                && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
131            const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
132            if (matched) {
133                if (proximityIndex) {
134                    *proximityIndex = j;
135                }
136                return NEAR_PROXIMITY_CHAR;
137            }
138            ++j;
139        }
140        if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
141                && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
142            ++j;
143            while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
144                    && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
145                const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
146                if (matched) {
147                    if (proximityIndex) {
148                        *proximityIndex = j;
149                    }
150                    return ADDITIONAL_PROXIMITY_CHAR;
151                }
152                ++j;
153            }
154        }
155
156        // Was not included, signal this as an unrelated character.
157        return UNRELATED_CHAR;
158    }
159
160    inline int getNormalizedSquaredDistance(
161            const int inputIndex, const int proximityIndex) const {
162        return mNormalizedSquaredDistances[
163                inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex];
164    }
165
166    inline const unsigned short *getPrimaryInputWord() const {
167        return mPrimaryInputWord;
168    }
169
170    inline bool touchPositionCorrectionEnabled() const {
171        return mTouchPositionCorrectionEnabled;
172    }
173
174    inline bool sameAsTyped(const unsigned short *word, int length) const {
175        if (length != mInputSize) {
176            return false;
177        }
178        const int *inputCodes = mInputCodes;
179        while (length--) {
180            if (static_cast<unsigned int>(*inputCodes) != static_cast<unsigned int>(*word)) {
181                return false;
182            }
183            inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
184            word++;
185        }
186        return true;
187    }
188
189    int getDuration(const int index) const;
190
191    bool isUsed() const {
192        return mInputSize > 0;
193    }
194
195    uint32_t size() const {
196        return mInputSize;
197    }
198
199    int getInputX(int index) const {
200        return mInputXs[index];
201    }
202
203    int getInputY(int index) const {
204        return mInputYs[index];
205    }
206
207    int getLengthCache(int index) const {
208        return mLengthCache[index];
209    }
210
211    float getPointToKeyLength(int inputIndex, int charCode, float scale);
212
213    int getKeyKeyDistance(int key0, int key1);
214
215    int getSpaceY();
216
217 private:
218    DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
219    /////////////////////////////////////////
220    // Defined in proximity_info_state.cpp //
221    /////////////////////////////////////////
222    float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
223
224    float calculateSquaredDistanceFromSweetSpotCenter(
225            const int keyIndex, const int inputIndex) const;
226
227    bool pushTouchPoint(const int nodeChar, int x, int y, const int time, const bool sample);
228    /////////////////////////////////////////
229    // Defined here                        //
230    /////////////////////////////////////////
231    inline float square(const float x) const { return x * x; }
232
233    bool hasInputCoordinates() const {
234        return mInputXs.size() > 0 && mInputYs.size() > 0;
235    }
236
237    inline const int *getProximityCharsAt(const int index) const {
238        return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
239    }
240
241    // const
242    const ProximityInfo *mProximityInfo;
243    float mMaxPointToKeyLength;
244    bool mHasTouchPositionCorrectionData;
245    int mMostCommonKeyWidthSquare;
246    std::string mLocaleStr;
247    int mKeyCount;
248    int mCellHeight;
249    int mCellWidth;
250    int mGridHeight;
251    int mGridWidth;
252
253    std::vector<int> mInputXs;
254    std::vector<int> mInputYs;
255    std::vector<int> mTimes;
256    std::vector<float> mDistanceCache;
257    std::vector<int>  mLengthCache;
258    bool mTouchPositionCorrectionEnabled;
259    int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
260    int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
261    int mInputSize;
262    unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
263};
264} // namespace latinime
265#endif // LATINIME_PROXIMITY_INFO_STATE_H
266