aboutsummaryrefslogtreecommitdiffstats
path: root/native/jni/src
diff options
context:
space:
mode:
Diffstat (limited to 'native/jni/src')
-rw-r--r--native/jni/src/additional_proximity_chars.cpp4
-rw-r--r--native/jni/src/additional_proximity_chars.h23
-rw-r--r--native/jni/src/bigram_dictionary.cpp14
-rw-r--r--native/jni/src/binary_format.h7
-rw-r--r--native/jni/src/char_utils.cpp8
-rw-r--r--native/jni/src/correction.cpp14
-rw-r--r--native/jni/src/correction.h1
-rw-r--r--native/jni/src/debug.h7
-rw-r--r--native/jni/src/defines.h3
-rw-r--r--native/jni/src/dic_traverse_wrapper.cpp26
-rw-r--r--native/jni/src/dic_traverse_wrapper.h66
-rw-r--r--native/jni/src/dictionary.cpp25
-rw-r--r--native/jni/src/dictionary.h19
-rw-r--r--native/jni/src/geometry_utils.h98
-rw-r--r--native/jni/src/gesture/gesture_decoder_wrapper.h32
-rw-r--r--native/jni/src/gesture/incremental_decoder_interface.h14
-rw-r--r--native/jni/src/gesture/incremental_decoder_wrapper.h32
-rw-r--r--native/jni/src/proximity_info.cpp152
-rw-r--r--native/jni/src/proximity_info.h38
-rw-r--r--native/jni/src/proximity_info_state.h30
-rw-r--r--native/jni/src/terminal_attributes.h3
-rw-r--r--native/jni/src/unigram_dictionary.cpp37
-rw-r--r--native/jni/src/words_priority_queue.h27
23 files changed, 479 insertions, 201 deletions
diff --git a/native/jni/src/additional_proximity_chars.cpp b/native/jni/src/additional_proximity_chars.cpp
index de8764678..f59492741 100644
--- a/native/jni/src/additional_proximity_chars.cpp
+++ b/native/jni/src/additional_proximity_chars.cpp
@@ -17,7 +17,9 @@
#include "additional_proximity_chars.h"
namespace latinime {
-const std::string AdditionalProximityChars::LOCALE_EN_US("en");
+// TODO: Stop using hardcoded additional proximity characters.
+// TODO: Have proximity character informations in each language's binary dictionary.
+const char *AdditionalProximityChars::LOCALE_EN_US = "en";
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = {
'e', 'i', 'o', 'u'
diff --git a/native/jni/src/additional_proximity_chars.h b/native/jni/src/additional_proximity_chars.h
index ba76cfced..1fe996d0d 100644
--- a/native/jni/src/additional_proximity_chars.h
+++ b/native/jni/src/additional_proximity_chars.h
@@ -17,8 +17,8 @@
#ifndef LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
#define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
+#include <cstring>
#include <stdint.h>
-#include <string>
#include "defines.h"
@@ -27,7 +27,7 @@ namespace latinime {
class AdditionalProximityChars {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AdditionalProximityChars);
- static const std::string LOCALE_EN_US;
+ static const char *LOCALE_EN_US;
static const int EN_US_ADDITIONAL_A_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_A[];
static const int EN_US_ADDITIONAL_E_SIZE = 4;
@@ -39,14 +39,15 @@ class AdditionalProximityChars {
static const int EN_US_ADDITIONAL_U_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_U[];
- static bool isEnLocale(const std::string *locale_str) {
- return locale_str && locale_str->size() >= LOCALE_EN_US.size()
- && LOCALE_EN_US.compare(0, LOCALE_EN_US.size(), *locale_str);
+ static bool isEnLocale(const char *localeStr) {
+ const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US);
+ return localeStr && strlen(localeStr) >= LOCALE_EN_US_SIZE
+ && strncmp(localeStr, LOCALE_EN_US, LOCALE_EN_US_SIZE) == 0;
}
public:
- static int getAdditionalCharsSize(const std::string *locale_str, const int32_t c) {
- if (!isEnLocale(locale_str)) {
+ static int getAdditionalCharsSize(const char *localeStr, const int32_t c) {
+ if (!isEnLocale(localeStr)) {
return 0;
}
switch(c) {
@@ -65,8 +66,8 @@ class AdditionalProximityChars {
}
}
- static const int32_t *getAdditionalChars(const std::string *locale_str, const int32_t c) {
- if (!isEnLocale(locale_str)) {
+ static const int32_t *getAdditionalChars(const char *localeStr, const int32_t c) {
+ if (!isEnLocale(localeStr)) {
return 0;
}
switch(c) {
@@ -84,10 +85,6 @@ class AdditionalProximityChars {
return 0;
}
}
-
- static bool hasAdditionalChars(const std::string *locale_str, const int32_t c) {
- return getAdditionalCharsSize(locale_str, c) > 0;
- }
};
} // namespace latinime
#endif // LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 220171127..f1d538095 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -60,15 +60,15 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ
AKLOGI("Bigram: InsertAt -> %d MAX_PREDICTIONS: %d", insertAt, MAX_PREDICTIONS);
}
if (insertAt < MAX_PREDICTIONS) {
- memmove((char*) bigramFreq + (insertAt + 1) * sizeof(bigramFreq[0]),
- (char*) bigramFreq + insertAt * sizeof(bigramFreq[0]),
- (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramFreq[0]));
+ memmove(bigramFreq + (insertAt + 1),
+ bigramFreq + insertAt,
+ (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramFreq[0]));
bigramFreq[insertAt] = frequency;
outputTypes[insertAt] = Dictionary::KIND_PREDICTION;
- memmove((char*) bigramChars + (insertAt + 1) * MAX_WORD_LENGTH * sizeof(short),
- (char*) bigramChars + (insertAt ) * MAX_WORD_LENGTH * sizeof(short),
- (MAX_PREDICTIONS - insertAt - 1) * sizeof(short) * MAX_WORD_LENGTH);
- unsigned short *dest = bigramChars + (insertAt ) * MAX_WORD_LENGTH;
+ memmove(bigramChars + (insertAt + 1) * MAX_WORD_LENGTH,
+ bigramChars + insertAt * MAX_WORD_LENGTH,
+ (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramChars[0]) * MAX_WORD_LENGTH);
+ unsigned short *dest = bigramChars + insertAt * MAX_WORD_LENGTH;
while (length--) {
*dest++ = *word++;
}
diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h
index 2ee4077c1..4cabc8404 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/binary_format.h
@@ -52,6 +52,8 @@ class BinaryFormat {
// Mask for attribute frequency, stored on 4 bits inside the flags byte.
static const int MASK_ATTRIBUTE_FREQUENCY = 0x0F;
+ // The numeric value of the shortcut frequency that means 'whitelist'.
+ static const int WHITELIST_SHORTCUT_FREQUENCY = 15;
// Mask and flags for attribute address type selection.
static const int MASK_ATTRIBUTE_ADDRESS_TYPE = 0x30;
@@ -99,6 +101,7 @@ class BinaryFormat {
static bool hasChildrenInFlags(const uint8_t flags);
static int getAttributeAddressAndForwardPointer(const uint8_t *const dict, const uint8_t flags,
int *pos);
+ static int getAttributeFrequencyFromFlags(const int flags);
static int getTerminalPosition(const uint8_t *const root, const int32_t *const inWord,
const int length, const bool forceLowerCaseSearch);
static int getWordAtAddress(const uint8_t *const root, const int address, const int maxDepth,
@@ -340,6 +343,10 @@ inline int BinaryFormat::getAttributeAddressAndForwardPointer(const uint8_t *con
}
}
+inline int BinaryFormat::getAttributeFrequencyFromFlags(const int flags) {
+ return flags & MASK_ATTRIBUTE_FREQUENCY;
+}
+
// This function gets the byte position of the last chargroup of the exact matching word in the
// dictionary. If no match is found, it returns NOT_VALID_WORD.
inline int BinaryFormat::getTerminalPosition(const uint8_t *const root,
diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp
index 45d49b087..223291f60 100644
--- a/native/jni/src/char_utils.cpp
+++ b/native/jni/src/char_utils.cpp
@@ -885,16 +885,16 @@ static const struct LatinCapitalSmallPair SORTED_CHAR_MAP[] = {
};
static int compare_pair_capital(const void *a, const void *b) {
- return (int)(*(unsigned short *)a)
- - (int)((struct LatinCapitalSmallPair*)b)->capital;
+ return static_cast<int>(*static_cast<const unsigned short *>(a))
+ - static_cast<int>((static_cast<const struct LatinCapitalSmallPair *>(b))->capital);
}
unsigned short latin_tolower(unsigned short c) {
struct LatinCapitalSmallPair *p =
- (struct LatinCapitalSmallPair *)bsearch(&c, SORTED_CHAR_MAP,
+ static_cast<struct LatinCapitalSmallPair *>(bsearch(&c, SORTED_CHAR_MAP,
sizeof(SORTED_CHAR_MAP) / sizeof(SORTED_CHAR_MAP[0]),
sizeof(SORTED_CHAR_MAP[0]),
- compare_pair_capital);
+ compare_pair_capital));
return p ? p->small : c;
}
} // namespace latinime
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index ea4bddae2..e55da0113 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -154,11 +154,13 @@ void Correction::checkState() {
if (mSkipPos >= 0) ++inputCount;
if (mExcessivePos >= 0) ++inputCount;
if (mTransposedPos >= 0) ++inputCount;
- // TODO: remove this assert
- assert(inputCount <= 1);
}
}
+bool Correction::sameAsTyped() {
+ return mProximityInfoState.sameAsTyped(mWord, mOutputIndex);
+}
+
int Correction::getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray,
const int wordCount, const bool isSpaceProximity, const unsigned short *word) {
return Correction::RankingAlgorithm::calcFreqForSplitMultipleWords(freqArray, wordLengthArray,
@@ -1094,7 +1096,7 @@ int Correction::RankingAlgorithm::editDistance(const unsigned short *before,
// In dictionary.cpp, getSuggestion() method,
// suggestion scores are computed using the below formula.
// original score
-// := pow(mTypedLetterMultiplier (this is defined 2),
+// := powf(mTypedLetterMultiplier (this is defined 2),
// (the number of matched characters between typed word and suggested word))
// * (individual word's score which defined in the unigram dictionary,
// and this score is defined in range [0, 255].)
@@ -1106,11 +1108,11 @@ int Correction::RankingAlgorithm::editDistance(const unsigned short *before,
// capitalization, then treat it as if the score was 255.
// - If before.length() == after.length()
// => multiply by mFullWordMultiplier (this is defined 2))
-// So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2
+// So, maximum original score is powf(2, min(before.length(), after.length())) * 255 * 2 * 1.2
// For historical reasons we ignore the 1.2 modifier (because the measure for a good
// autocorrection threshold was done at a time when it didn't exist). This doesn't change
// the result.
-// So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2.
+// So, we can normalize original score by dividing powf(2, min(b.l(),a.l())) * 255 * 2.
/* static */
float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *before,
@@ -1132,7 +1134,7 @@ float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *be
}
const float maxScore = score >= S_INT_MAX ? S_INT_MAX : MAX_INITIAL_SCORE
- * pow(static_cast<float>(TYPED_LETTER_MULTIPLIER),
+ * powf(static_cast<float>(TYPED_LETTER_MULTIPLIER),
static_cast<float>(min(beforeLength, afterLength - spaceCount)))
* FULL_WORD_MULTIPLIER;
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 81623a46b..57e7b7189 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -105,6 +105,7 @@ class Correction {
const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance,
const bool doAutoCompletion, const int maxErrors);
void checkState();
+ bool sameAsTyped();
bool initProcessState(const int index);
int getInputIndex();
diff --git a/native/jni/src/debug.h b/native/jni/src/debug.h
index 2168d6672..4e2164014 100644
--- a/native/jni/src/debug.h
+++ b/native/jni/src/debug.h
@@ -58,11 +58,12 @@ static inline void LOGI_S16_PLUS(unsigned short *string, const unsigned int leng
}
static inline void printDebug(const char *tag, int *codes, int codesSize, int MAX_PROXIMITY_CHARS) {
- unsigned char *buf = (unsigned char*)malloc((1 + codesSize) * sizeof(*buf));
+ unsigned char *buf = static_cast<unsigned char *>(malloc((1 + codesSize) * sizeof(*buf)));
buf[codesSize] = 0;
- while (--codesSize >= 0)
- buf[codesSize] = (unsigned char)codes[codesSize * MAX_PROXIMITY_CHARS];
+ while (--codesSize >= 0) {
+ buf[codesSize] = static_cast<unsigned char>(codes[codesSize * MAX_PROXIMITY_CHARS]);
+ }
AKLOGI("%s, WORD = %s", tag, buf);
free(buf);
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 31dd61e30..484fc6bde 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -265,6 +265,9 @@ static inline void prof_out(void) {
// This must be equal to ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE in KeyDetector.java
#define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2
+// Assuming locale strings such as en_US, sr-Latn etc.
+#define MAX_LOCALE_STRING_LENGTH 10
+
// Word limit for sub queues used in WordsPriorityQueuePool. Sub queues are temporary queues used
// for better performance.
// Holds up to 1 candidate for each word
diff --git a/native/jni/src/dic_traverse_wrapper.cpp b/native/jni/src/dic_traverse_wrapper.cpp
new file mode 100644
index 000000000..1f7dcbfb2
--- /dev/null
+++ b/native/jni/src/dic_traverse_wrapper.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LatinIME: jni: Session"
+
+#include "dic_traverse_wrapper.h"
+
+namespace latinime {
+void *(*DicTraverseWrapper::sDicTraverseSessionFactoryMethod)(JNIEnv *env, jstring locale) = 0;
+void (*DicTraverseWrapper::sDicTraverseSessionReleaseMethod)(void *) = 0;
+void (*DicTraverseWrapper::sDicTraverseSessionInitMethod)(
+ void *, Dictionary *, const int *, const int) = 0;
+} // namespace latinime
diff --git a/native/jni/src/dic_traverse_wrapper.h b/native/jni/src/dic_traverse_wrapper.h
new file mode 100644
index 000000000..8396d0027
--- /dev/null
+++ b/native/jni/src/dic_traverse_wrapper.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DIC_TRAVERSE_WRAPPER_H
+#define LATINIME_DIC_TRAVERSE_WRAPPER_H
+
+#include <stdint.h>
+
+#include "defines.h"
+#include "jni.h"
+
+namespace latinime {
+class Dictionary;
+// TODO: Remove
+class DicTraverseWrapper {
+ public:
+ static void *getDicTraverseSession(JNIEnv *env, jstring locale) {
+ if (sDicTraverseSessionFactoryMethod) {
+ return sDicTraverseSessionFactoryMethod(env, locale);
+ }
+ return 0;
+ }
+ static void initDicTraverseSession(void *traverseSession,
+ Dictionary *dictionary, const int *prevWord, const int prevWordLength) {
+ if (sDicTraverseSessionInitMethod) {
+ sDicTraverseSessionInitMethod(traverseSession, dictionary, prevWord, prevWordLength);
+ }
+ }
+ static void releaseDicTraverseSession(void *traverseSession) {
+ if (sDicTraverseSessionReleaseMethod) {
+ sDicTraverseSessionReleaseMethod(traverseSession);
+ }
+ }
+ static void setTraverseSessionFactoryMethod(
+ void *(*factoryMethod)(JNIEnv *env, jstring locale)) {
+ sDicTraverseSessionFactoryMethod = factoryMethod;
+ }
+ static void setTraverseSessionInitMethod(
+ void (*initMethod)(void *, Dictionary *, const int *, const int)) {
+ sDicTraverseSessionInitMethod = initMethod;
+ }
+ static void setTraverseSessionReleaseMethod(void (*releaseMethod)(void *)) {
+ sDicTraverseSessionReleaseMethod = releaseMethod;
+ }
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseWrapper);
+ static void *(*sDicTraverseSessionFactoryMethod)(JNIEnv *, jstring);
+ static void (*sDicTraverseSessionInitMethod)(void *, Dictionary *, const int *, const int);
+ static void (*sDicTraverseSessionReleaseMethod)(void *);
+};
+int register_DicTraverseSession(JNIEnv *env);
+} // namespace latinime
+#endif // LATINIME_DIC_TRAVERSE_WRAPPER_H
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index ee55cfa60..158c3fb22 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -22,6 +22,7 @@
#include "binary_format.h"
#include "defines.h"
#include "dictionary.h"
+#include "dic_traverse_wrapper.h"
#include "gesture_decoder_wrapper.h"
#include "unigram_dictionary.h"
@@ -31,8 +32,9 @@ namespace latinime {
Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust,
int typedLetterMultiplier, int fullWordMultiplier,
int maxWordLength, int maxWords, int maxPredictions)
- : mDict((unsigned char*) dict), mDictSize(dictSize),
- mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust) {
+ : mDict(static_cast<unsigned char *>(dict)),
+ mOffsetDict((static_cast<unsigned char *>(dict)) + BinaryFormat::getHeaderSize(mDict)),
+ mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust) {
if (DEBUG_DICT) {
if (MAX_WORD_LENGTH_INTERNAL < maxWordLength) {
AKLOGI("Max word length (%d) is greater than %d",
@@ -40,14 +42,11 @@ Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust,
AKLOGI("IN NATIVE SUGGEST Version: %d", (mDict[0] & 0xFF));
}
}
- const unsigned int headerSize = BinaryFormat::getHeaderSize(mDict);
const unsigned int options = BinaryFormat::getFlags(mDict);
- mUnigramDictionary = new UnigramDictionary(mDict + headerSize, typedLetterMultiplier,
+ mUnigramDictionary = new UnigramDictionary(mOffsetDict, typedLetterMultiplier,
fullWordMultiplier, maxWordLength, maxWords, options);
- mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength, maxPredictions);
+ mBigramDictionary = new BigramDictionary(mOffsetDict, maxWordLength, maxPredictions);
mGestureDecoder = new GestureDecoderWrapper(maxWordLength, maxWords);
- mGestureDecoder->setDict(mUnigramDictionary, mBigramDictionary,
- mDict + headerSize /* dict root */, 0 /* root pos */);
}
Dictionary::~Dictionary() {
@@ -56,16 +55,18 @@ Dictionary::~Dictionary() {
delete mGestureDecoder;
}
-int Dictionary::getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
- int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars,
+int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession,
+ int *xcoordinates, int *ycoordinates, int *times, int *pointerIds,
+ int *codes, int codesSize, int *prevWordChars,
int prevWordLength, int commitPoint, bool isGesture,
bool useFullEditDistance, unsigned short *outWords,
int *frequencies, int *spaceIndices, int *outputTypes) {
int result = 0;
if (isGesture) {
- mGestureDecoder->setPrevWord(prevWordChars, prevWordLength);
- result = mGestureDecoder->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
- times, pointerIds, codes, codesSize, commitPoint,
+ DicTraverseWrapper::initDicTraverseSession(
+ traverseSession, this, prevWordChars, prevWordLength);
+ result = mGestureDecoder->getSuggestions(proximityInfo, traverseSession,
+ xcoordinates, ycoordinates, times, pointerIds, codes, codesSize, commitPoint,
outWords, frequencies, spaceIndices, outputTypes);
if (DEBUG_DICT) {
DUMP_RESULT(outWords, frequencies, 18 /* MAX_WORDS */, MAX_WORD_LENGTH_INTERNAL);
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index ab238c824..fd9e77011 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -44,9 +44,9 @@ class Dictionary {
Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler,
int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions);
- int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
- int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars,
- int prevWordLength, int commitPoint, bool isGesture,
+ int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates,
+ int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize,
+ int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture,
bool useFullEditDistance, unsigned short *outWords,
int *frequencies, int *spaceIndices, int *outputTypes);
@@ -55,7 +55,12 @@ class Dictionary {
int getFrequency(const int32_t *word, int length) const;
bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const;
- void *getDict() const { return (void *)mDict; }
+ const uint8_t *getDict() const { // required to release dictionary buffer
+ return mDict;
+ }
+ const uint8_t *getOffsetDict() const {
+ return mOffsetDict;
+ }
int getDictSize() const { return mDictSize; }
int getMmapFd() const { return mMmapFd; }
int getDictBufAdjust() const { return mDictBufAdjust; }
@@ -67,7 +72,8 @@ class Dictionary {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
- const unsigned char *mDict;
+ const uint8_t *mDict;
+ const uint8_t *mOffsetDict;
// Used only for the mmap version of dictionary loading, but we use these as dummy variables
// also for the malloc version.
@@ -85,8 +91,9 @@ class Dictionary {
inline int Dictionary::wideStrLen(unsigned short *str) {
if (!str) return 0;
unsigned short *end = str;
- while (*end)
+ while (*end) {
end++;
+ }
return end - str;
}
} // namespace latinime
diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h
new file mode 100644
index 000000000..146eb8055
--- /dev/null
+++ b/native/jni/src/geometry_utils.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_GEOMETRY_UTILS_H
+#define LATINIME_GEOMETRY_UTILS_H
+
+#include <cmath>
+
+#define MAX_DISTANCE 10000000
+#define MAX_PATHS 2
+
+#define DEBUG_DECODER false
+
+#define M_PI_F 3.14159265f
+
+namespace latinime {
+
+static inline float squareFloat(float x) {
+ return x * x;
+}
+
+static inline float getSquaredDistanceFloat(float x1, float y1, float x2, float y2) {
+ return squareFloat(x1 - x2) + squareFloat(y1 - y2);
+}
+
+static inline float getDistanceFloat(float x1, float y1, float x2, float y2) {
+ return hypotf(x1 - x2, y1 - y2);
+}
+
+static inline int getDistanceInt(int x1, int y1, int x2, int y2) {
+ return static_cast<int>(getDistanceFloat(static_cast<float>(x1), static_cast<float>(y1),
+ static_cast<float>(x2), static_cast<float>(y2)));
+}
+
+static inline float getAngle(int x1, int y1, int x2, int y2) {
+ const int dx = x1 - x2;
+ const int dy = y1 - y2;
+ if (dx == 0 && dy == 0) return 0;
+ return atan2f(static_cast<float>(dy), static_cast<float>(dx));
+}
+
+static inline float getAngleDiff(float a1, float a2) {
+ const float diff = fabsf(a1 - a2);
+ if (diff > M_PI_F) {
+ return 2.0f * M_PI_F - diff;
+ }
+ return diff;
+}
+
+// static float pointToLineSegSquaredDistanceFloat(
+// float x, float y, float x1, float y1, float x2, float y2) {
+// float A = x - x1;
+// float B = y - y1;
+// float C = x2 - x1;
+// float D = y2 - y1;
+// return fabsf(A * D - C * B) / sqrtf(C * C + D * D);
+// }
+
+static inline float pointToLineSegSquaredDistanceFloat(
+ float x, float y, float x1, float y1, float x2, float y2) {
+ const float ray1x = x - x1;
+ const float ray1y = y - y1;
+ const float ray2x = x2 - x1;
+ const float ray2y = y2 - y1;
+
+ const float dotProduct = ray1x * ray2x + ray1y * ray2y;
+ const float lineLengthSqr = squareFloat(ray2x) + squareFloat(ray2y);
+ const float projectionLengthSqr = dotProduct / lineLengthSqr;
+
+ float projectionX;
+ float projectionY;
+ if (projectionLengthSqr < 0.0f) {
+ projectionX = x1;
+ projectionY = y1;
+ } else if (projectionLengthSqr > 1.0f) {
+ projectionX = x2;
+ projectionY = y2;
+ } else {
+ projectionX = x1 + projectionLengthSqr * ray2x;
+ projectionY = y1 + projectionLengthSqr * ray2y;
+ }
+ return getSquaredDistanceFloat(x, y, projectionX, projectionY);
+}
+} // namespace latinime
+#endif // LATINIME_GEOMETRY_UTILS_H
diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h
index 03c84b5fd..f8bfe7c79 100644
--- a/native/jni/src/gesture/gesture_decoder_wrapper.h
+++ b/native/jni/src/gesture/gesture_decoder_wrapper.h
@@ -37,37 +37,15 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface {
delete mIncrementalDecoderInterface;
}
- int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times,
- int *pointerIds, int *codes, int inputSize, int commitPoint,
+ int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
+ int *times, int *pointerIds, int *codes, int inputSize, int commitPoint,
unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) {
if (!mIncrementalDecoderInterface) {
return 0;
}
return mIncrementalDecoderInterface->getSuggestions(
- pInfo, inputXs, inputYs, times, pointerIds, codes, inputSize, commitPoint,
- outWords, frequencies, outputIndices, outputTypes);
- }
-
- void reset() {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->reset();
- }
-
- void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram,
- const uint8_t *dictRoot, int rootPos) {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->setDict(dict, bigram, dictRoot, rootPos);
- }
-
- void setPrevWord(const int32_t *prevWord, int prevWordLength) {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->setPrevWord(prevWord, prevWordLength);
+ pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes,
+ inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes);
}
static void setGestureDecoderFactoryMethod(
@@ -76,7 +54,7 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface {
}
private:
- DISALLOW_COPY_AND_ASSIGN(GestureDecoderWrapper);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(GestureDecoderWrapper);
static IncrementalDecoderInterface *getGestureDecoderInstance(int maxWordLength, int maxWords) {
if (sGestureDecoderFactoryMethod) {
return sGestureDecoderFactoryMethod(maxWordLength, maxWords);
diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h
index 6d2e273da..04f0095e0 100644
--- a/native/jni/src/gesture/incremental_decoder_interface.h
+++ b/native/jni/src/gesture/incremental_decoder_interface.h
@@ -28,14 +28,14 @@ class ProximityInfo;
class IncrementalDecoderInterface {
public:
- virtual int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times,
- int *pointerIds, int *codes, int inputSize, int commitPoint,
- unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) = 0;
- virtual void reset() = 0;
- virtual void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram,
- const uint8_t *dictRoot, int rootPos) = 0;
- virtual void setPrevWord(const int32_t *prevWord, int prevWordLength) = 0;
+ virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession,
+ int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes,
+ int inputSize, int commitPoint, unsigned short *outWords, int *frequencies,
+ int *outputIndices, int *outputTypes) = 0;
+ IncrementalDecoderInterface() { };
virtual ~IncrementalDecoderInterface() { };
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IncrementalDecoderInterface);
};
} // namespace latinime
#endif // LATINIME_INCREMENTAL_DECODER_INTERFACE_H
diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.h b/native/jni/src/gesture/incremental_decoder_wrapper.h
index 698061548..5cb2ee368 100644
--- a/native/jni/src/gesture/incremental_decoder_wrapper.h
+++ b/native/jni/src/gesture/incremental_decoder_wrapper.h
@@ -37,37 +37,15 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface {
delete mIncrementalDecoderInterface;
}
- int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times,
- int *pointerIds, int *codes, int inputSize, int commitPoint,
+ int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
+ int *times, int *pointerIds, int *codes, int inputSize, int commitPoint,
unsigned short *outWords, int *frequencies, int *outputIndices, int *outputTypes) {
if (!mIncrementalDecoderInterface) {
return 0;
}
return mIncrementalDecoderInterface->getSuggestions(
- pInfo, inputXs, inputYs, times, pointerIds, codes, inputSize, commitPoint,
- outWords, frequencies, outputIndices, outputTypes);
- }
-
- void reset() {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->reset();
- }
-
- void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram,
- const uint8_t *dictRoot, int rootPos) {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->setDict(dict, bigram, dictRoot, rootPos);
- }
-
- void setPrevWord(const int32_t *prevWord, int prevWordLength) {
- if (!mIncrementalDecoderInterface) {
- return;
- }
- mIncrementalDecoderInterface->setPrevWord(prevWord, prevWordLength);
+ pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes,
+ inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes);
}
static void setIncrementalDecoderFactoryMethod(
@@ -76,7 +54,7 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface {
}
private:
- DISALLOW_COPY_AND_ASSIGN(IncrementalDecoderWrapper);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalDecoderWrapper);
static IncrementalDecoderInterface *getIncrementalDecoderInstance(int maxWordLength,
int maxWords) {
if (sIncrementalDecoderFactoryMethod) {
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index cee408d46..1b9bac0f0 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -17,62 +17,76 @@
#include <cassert>
#include <cmath>
#include <cstring>
-#include <string>
#define LOG_TAG "LatinIME: proximity_info.cpp"
#include "additional_proximity_chars.h"
#include "char_utils.h"
#include "defines.h"
+#include "geometry_utils.h"
+#include "jni.h"
#include "proximity_info.h"
namespace latinime {
-inline void copyOrFillZero(void *to, const void *from, size_t size) {
- if (from) {
- memcpy(to, from, size);
- } else {
- memset(to, 0, size);
+static inline void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray, jsize len,
+ jint *buffer) {
+ if (jArray && buffer) {
+ env->GetIntArrayRegion(jArray, 0, len, buffer);
+ } else if (buffer) {
+ memset(buffer, 0, len * sizeof(jint));
}
}
-ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
+static inline void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray, jsize len,
+ jfloat *buffer) {
+ if (jArray && buffer) {
+ env->GetFloatArrayRegion(jArray, 0, len, buffer);
+ } else if (buffer) {
+ memset(buffer, 0, len * sizeof(jfloat));
+ }
+}
+
+ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize,
const int keyboardWidth, const int keyboardHeight, const int gridWidth,
- const int gridHeight, const int mostCommonKeyWidth,
- const int32_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)
+ const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars,
+ const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates,
+ const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes,
+ const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs,
+ const jfloatArray sweetSpotRadii)
: MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth),
KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight),
+ MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth),
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)),
HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
&& keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
- && sweetSpotCenterYs && sweetSpotRadii),
- mLocaleStr(localeStr) {
+ && sweetSpotCenterYs && sweetSpotRadii) {
const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
if (DEBUG_PROXIMITY_INFO) {
AKLOGI("Create proximity info array %d", proximityGridLength);
}
+ const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
+ if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
+ AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
+ assert(false);
+ }
+ memset(mLocaleStr, 0, sizeof(mLocaleStr));
+ env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
mProximityCharsArray = new int32_t[proximityGridLength];
- memcpy(mProximityCharsArray, proximityCharsArray,
- proximityGridLength * sizeof(mProximityCharsArray[0]));
-
- copyOrFillZero(mKeyXCoordinates, keyXCoordinates, KEY_COUNT * sizeof(mKeyXCoordinates[0]));
- copyOrFillZero(mKeyYCoordinates, keyYCoordinates, KEY_COUNT * sizeof(mKeyYCoordinates[0]));
- copyOrFillZero(mKeyWidths, keyWidths, KEY_COUNT * sizeof(mKeyWidths[0]));
- copyOrFillZero(mKeyHeights, keyHeights, KEY_COUNT * sizeof(mKeyHeights[0]));
- copyOrFillZero(mKeyCharCodes, keyCharCodes, KEY_COUNT * sizeof(mKeyCharCodes[0]));
- copyOrFillZero(mSweetSpotCenterXs, sweetSpotCenterXs,
- KEY_COUNT * sizeof(mSweetSpotCenterXs[0]));
- copyOrFillZero(mSweetSpotCenterYs, sweetSpotCenterYs,
- KEY_COUNT * sizeof(mSweetSpotCenterYs[0]));
- copyOrFillZero(mSweetSpotRadii, sweetSpotRadii, KEY_COUNT * sizeof(mSweetSpotRadii[0]));
-
+ safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityGridLength, mProximityCharsArray);
+ safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates);
+ safeGetOrFillZeroIntArrayRegion(env, keyYCoordinates, KEY_COUNT, mKeyYCoordinates);
+ safeGetOrFillZeroIntArrayRegion(env, keyWidths, KEY_COUNT, mKeyWidths);
+ safeGetOrFillZeroIntArrayRegion(env, keyHeights, KEY_COUNT, mKeyHeights);
+ safeGetOrFillZeroIntArrayRegion(env, keyCharCodes, KEY_COUNT, mKeyCharCodes);
+ safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterXs, KEY_COUNT, mSweetSpotCenterXs);
+ safeGetOrFillZeroFloatArrayRegion(env, sweetSpotCenterYs, KEY_COUNT, mSweetSpotCenterYs);
+ safeGetOrFillZeroFloatArrayRegion(env, sweetSpotRadii, KEY_COUNT, mSweetSpotRadii);
initializeCodeToKeyIndex();
+ initializeG();
}
// Build the reversed look up table from the char code to the index in mKeyXCoordinates,
@@ -121,6 +135,21 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
return false;
}
+static inline float getNormalizedSquaredDistanceFloat(float x1, float y1, float x2, float y2,
+ float scale) {
+ return squareFloat((x1 - x2) / scale) + squareFloat((y1 - y2) / scale);
+}
+
+float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloat(
+ const int keyId, const int x, const int y) const {
+ const float centerX = static_cast<float>(getKeyCenterXOfIdG(keyId));
+ const float centerY = static_cast<float>(getKeyCenterYOfIdG(keyId));
+ const float touchX = static_cast<float>(x);
+ const float touchY = static_cast<float>(y);
+ const float keyWidth = static_cast<float>(getMostCommonKeyWidth());
+ return getNormalizedSquaredDistanceFloat(centerX, centerY, touchX, touchY, keyWidth);
+}
+
int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) const {
if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
const int left = mKeyXCoordinates[keyId];
@@ -160,7 +189,7 @@ void ProximityInfo::calculateNearbyKeyCodes(
}
}
const int additionalProximitySize =
- AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey);
+ AdditionalProximityChars::getAdditionalCharsSize(mLocaleStr, primaryKey);
if (additionalProximitySize > 0) {
inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
@@ -171,7 +200,7 @@ void ProximityInfo::calculateNearbyKeyCodes(
}
const int32_t *additionalProximityChars =
- AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey);
+ AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey);
for (int j = 0; j < additionalProximitySize; ++j) {
const int32_t ac = additionalProximityChars[j];
int k = 0;
@@ -211,24 +240,65 @@ int ProximityInfo::getKeyIndex(const int c) const {
return mCodeToKeyIndex[baseLowerC];
}
-// TODO: [Staging] Optimize
-void ProximityInfo::getCenters(int *centerXs, int *centerYs, int *codeToKeyIndex,
- int *keyToCodeIndex, int *keyCount, int *keyWidth) const {
- *keyCount = KEY_COUNT;
- *keyWidth = sqrt(static_cast<float>(MOST_COMMON_KEY_WIDTH_SQUARE));
+int ProximityInfo::getKeyCode(const int keyIndex) const {
+ if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
+ return NOT_AN_INDEX;
+ }
+ return mKeyToCodeIndexG[keyIndex];
+}
+void ProximityInfo::initializeG() {
+ // TODO: Optimize
for (int i = 0; i < KEY_COUNT; ++i) {
const int code = mKeyCharCodes[i];
const int lowerCode = toBaseLowerCase(code);
- centerXs[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
- centerYs[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
- codeToKeyIndex[code] = i;
+ mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
+ mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
if (code != lowerCode && lowerCode >= 0 && lowerCode <= MAX_CHAR_CODE) {
- codeToKeyIndex[lowerCode] = i;
- keyToCodeIndex[i] = lowerCode;
+ mCodeToKeyIndex[lowerCode] = i;
+ mKeyToCodeIndexG[i] = lowerCode;
} else {
- keyToCodeIndex[i] = code;
+ mKeyToCodeIndexG[i] = code;
+ }
+ }
+ for (int i = 0; i < KEY_COUNT; i++) {
+ mKeyKeyDistancesG[i][i] = 0;
+ for (int j = i + 1; j < KEY_COUNT; j++) {
+ mKeyKeyDistancesG[i][j] = getDistanceInt(
+ mCenterXsG[i], mCenterYsG[i], mCenterXsG[j], mCenterYsG[j]);
+ mKeyKeyDistancesG[j][i] = mKeyKeyDistancesG[i][j];
}
}
}
+
+float ProximityInfo::getKeyCenterXOfCharG(int charCode) const {
+ return getKeyCenterXOfIdG(getKeyIndex(charCode));
+}
+
+float ProximityInfo::getKeyCenterYOfCharG(int charCode) const {
+ return getKeyCenterYOfIdG(getKeyIndex(charCode));
+}
+
+float ProximityInfo::getKeyCenterXOfIdG(int keyId) const {
+ if (keyId >= 0) {
+ return mCenterXsG[keyId];
+ }
+ return 0;
+}
+
+float ProximityInfo::getKeyCenterYOfIdG(int keyId) const {
+ if (keyId >= 0) {
+ return mCenterYsG[keyId];
+ }
+ return 0;
+}
+
+int ProximityInfo::getKeyKeyDistanceG(int key0, int key1) const {
+ const int keyId0 = getKeyIndex(key0);
+ const int keyId1 = getKeyIndex(key1);
+ if (keyId0 >= 0 && keyId1 >= 0) {
+ return mKeyKeyDistancesG[keyId0][keyId1];
+ }
+ return 0;
+}
} // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index abd07dd3e..8a407e71a 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -18,9 +18,9 @@
#define LATINIME_PROXIMITY_INFO_H
#include <stdint.h>
-#include <string>
#include "defines.h"
+#include "jni.h"
namespace latinime {
@@ -28,16 +28,18 @@ class Correction;
class ProximityInfo {
public:
- ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
+ ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize,
const int keyboardWidth, const int keyboardHeight, const int gridWidth,
- const int gridHeight, const int mostCommonkeyWidth,
- const int32_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);
+ const int gridHeight, const int mostCommonKeyWidth, const jintArray proximityChars,
+ const int keyCount, const jintArray keyXCoordinates, const jintArray keyYCoordinates,
+ const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes,
+ const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs,
+ const jfloatArray sweetSpotRadii);
~ProximityInfo();
bool hasSpaceProximity(const int x, const int y) const;
int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
+ float getNormalizedSquaredDistanceFromCenterFloat(
+ const int keyId, const int x, const int y) const;
bool sameAsTyped(const unsigned short *word, int length) const;
int squaredDistanceToEdge(const int keyId, const int x, const int y) const;
bool isOnKey(const int keyId, const int x, const int y) const {
@@ -49,6 +51,7 @@ class ProximityInfo {
return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
}
int getKeyIndex(const int c) const;
+ int getKeyCode(const int keyIndex) const;
bool hasSweetSpotData(const int keyIndex) const {
// When there are no calibration data for a key,
// the radius of the key is assigned to zero.
@@ -70,11 +73,15 @@ class ProximityInfo {
return HAS_TOUCH_POSITION_CORRECTION_DATA;
}
+ int getMostCommonKeyWidth() const {
+ return MOST_COMMON_KEY_WIDTH;
+ }
+
int getMostCommonKeyWidthSquare() const {
return MOST_COMMON_KEY_WIDTH_SQUARE;
}
- std::string getLocaleStr() const {
+ const char *getLocaleStr() const {
return mLocaleStr;
}
@@ -98,6 +105,12 @@ class ProximityInfo {
return GRID_HEIGHT;
}
+ float getKeyCenterXOfCharG(int charCode) const;
+ float getKeyCenterYOfCharG(int charCode) const;
+ float getKeyCenterXOfIdG(int keyId) const;
+ float getKeyCenterYOfIdG(int keyId) const;
+ int getKeyKeyDistanceG(int key0, int key1) const;
+
// Returns the keyboard key-center information.
void getCenters(int *centersX, int *centersY, int *codeToKeyIndex, int *keyToCodeIndex,
int *keyCount, int *keyWidth) const;
@@ -113,6 +126,7 @@ class ProximityInfo {
int getStartIndexFromCoordinates(const int x, const int y) const;
void initializeCodeToKeyIndex();
+ void initializeG();
float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
float calculateSquaredDistanceFromSweetSpotCenter(
const int keyIndex, const int inputIndex) const;
@@ -123,12 +137,13 @@ class ProximityInfo {
const int KEYBOARD_HEIGHT;
const int GRID_WIDTH;
const int GRID_HEIGHT;
+ const int MOST_COMMON_KEY_WIDTH;
const int MOST_COMMON_KEY_WIDTH_SQUARE;
const int CELL_WIDTH;
const int CELL_HEIGHT;
const int KEY_COUNT;
const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
- const std::string mLocaleStr;
+ char mLocaleStr[MAX_LOCALE_STRING_LENGTH];
int32_t *mProximityCharsArray;
int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
@@ -139,6 +154,11 @@ class ProximityInfo {
float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
+
+ int mKeyToCodeIndexG[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ int mCenterXsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ int mCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ int mKeyKeyDistancesG[MAX_KEY_COUNT_IN_A_KEYBOARD][MAX_KEY_COUNT_IN_A_KEYBOARD];
// TODO: move to correction.h
};
} // namespace latinime
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 76d45516e..474c40757 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -160,6 +160,21 @@ class ProximityInfoState {
return mTouchPositionCorrectionEnabled;
}
+ inline bool sameAsTyped(const unsigned short *word, int length) const {
+ if (length != mInputLength) {
+ return false;
+ }
+ const int *inputCodes = mInputCodes;
+ while (length--) {
+ if (static_cast<unsigned int>(*inputCodes) != static_cast<unsigned int>(*word)) {
+ return false;
+ }
+ inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
+ word++;
+ }
+ return true;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
/////////////////////////////////////////
@@ -179,21 +194,6 @@ class ProximityInfoState {
return mInputXCoordinates && mInputYCoordinates;
}
- bool sameAsTyped(const unsigned short *word, int length) const {
- if (length != mInputLength) {
- return false;
- }
- const int *inputCodes = mInputCodes;
- while (length--) {
- if ((unsigned int) *inputCodes != (unsigned int) *word) {
- return false;
- }
- inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
- word++;
- }
- return true;
- }
-
// const
const ProximityInfo *mProximityInfo;
bool mHasTouchPositionCorrectionData;
diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h
index d63364514..1ae9c7cbb 100644
--- a/native/jni/src/terminal_attributes.h
+++ b/native/jni/src/terminal_attributes.h
@@ -46,7 +46,7 @@ class TerminalAttributes {
// Gets the shortcut target itself as a uint16_t string. For parameters and return value
// see BinaryFormat::getWordAtAddress.
// TODO: make the output an uint32_t* to handle the whole unicode range.
- inline int getNextShortcutTarget(const int maxDepth, uint16_t *outWord) {
+ inline int getNextShortcutTarget(const int maxDepth, uint16_t *outWord, int *outFreq) {
const int shortcutFlags = BinaryFormat::getFlagsAndForwardPointer(mDict, &mPos);
mHasNextShortcutTarget =
0 != (shortcutFlags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT);
@@ -56,6 +56,7 @@ class TerminalAttributes {
if (NOT_A_CHARACTER == charCode) break;
outWord[i] = (uint16_t)charCode;
}
+ *outFreq = BinaryFormat::getAttributeFrequencyFromFlags(shortcutFlags);
mPos += BinaryFormat::CHARACTER_ARRAY_TERMINATOR_SIZE;
return i;
}
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index b6b0210cc..cc6d39a29 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -63,8 +63,8 @@ static inline unsigned int getCodesBufferSize(const int *codes, const int codesS
// TODO: This needs to take a const unsigned short* and not tinker with its contents
static inline void addWord(
- unsigned short *word, int length, int frequency, WordsPriorityQueue *queue) {
- queue->push(frequency, word, length);
+ unsigned short *word, int length, int frequency, WordsPriorityQueue *queue, int type) {
+ queue->push(frequency, word, length, type);
}
// Return the replacement code point for a digraph, or 0 if none.
@@ -213,8 +213,8 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo,
AKLOGI("Max normalized score = %f", ns);
}
const int suggestedWordsCount =
- queuePool.getMasterQueue()->outputSuggestions(
- masterCorrection.getPrimaryInputWord(), codesSize, frequencies, outWords);
+ queuePool.getMasterQueue()->outputSuggestions(masterCorrection.getPrimaryInputWord(),
+ codesSize, frequencies, outWords, outputTypes);
if (DEBUG_DICT) {
float ns = queuePool.getMasterQueue()->getHighestNormalizedScore(
@@ -391,7 +391,12 @@ inline void UnigramDictionary::onTerminal(const int probability,
const int finalProbability =
correction->getFinalProbability(probability, &wordPointer, &wordLength);
if (finalProbability != NOT_A_PROBABILITY) {
- addWord(wordPointer, wordLength, finalProbability, masterQueue);
+ if (0 != finalProbability) {
+ // If the probability is 0, we don't want to add this word. However we still
+ // want to add its shortcuts (including a possible whitelist entry) if any.
+ addWord(wordPointer, wordLength, finalProbability, masterQueue,
+ Dictionary::KIND_CORRECTION);
+ }
const int shortcutProbability = finalProbability > 0 ? finalProbability - 1 : 0;
// Please note that the shortcut candidates will be added to the master queue only.
@@ -406,10 +411,21 @@ inline void UnigramDictionary::onTerminal(const int probability,
// with the same score. For the moment we use -1 to make sure the shortcut will
// never be in front of the word.
uint16_t shortcutTarget[MAX_WORD_LENGTH_INTERNAL];
+ int shortcutFrequency;
const int shortcutTargetStringLength = iterator.getNextShortcutTarget(
- MAX_WORD_LENGTH_INTERNAL, shortcutTarget);
- addWord(shortcutTarget, shortcutTargetStringLength, shortcutProbability,
- masterQueue);
+ MAX_WORD_LENGTH_INTERNAL, shortcutTarget, &shortcutFrequency);
+ int shortcutScore;
+ int kind;
+ if (shortcutFrequency == BinaryFormat::WHITELIST_SHORTCUT_FREQUENCY
+ && correction->sameAsTyped()) {
+ shortcutScore = S_INT_MAX;
+ kind = Dictionary::KIND_WHITELIST;
+ } else {
+ shortcutScore = shortcutProbability;
+ kind = Dictionary::KIND_CORRECTION;
+ }
+ addWord(shortcutTarget, shortcutTargetStringLength, shortcutScore,
+ masterQueue, kind);
}
}
}
@@ -424,7 +440,7 @@ inline void UnigramDictionary::onTerminal(const int probability,
}
const int finalProbability = correction->getFinalProbabilityForSubQueue(
probability, &wordPointer, &wordLength, inputIndex);
- addWord(wordPointer, wordLength, finalProbability, subQueue);
+ addWord(wordPointer, wordLength, finalProbability, subQueue, Dictionary::KIND_CORRECTION);
}
}
@@ -572,7 +588,8 @@ int UnigramDictionary::getSubStringSuggestion(
AKLOGI("Split two words: freq = %d, length = %d, %d, isSpace ? %d", pairFreq,
inputLength, tempOutputWordLength, isSpaceProximity);
}
- addWord(outputWord, tempOutputWordLength, pairFreq, queuePool->getMasterQueue());
+ addWord(outputWord, tempOutputWordLength, pairFreq, queuePool->getMasterQueue(),
+ Dictionary::KIND_CORRECTION);
}
return FLAG_MULTIPLE_SUGGEST_CONTINUE;
}
diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h
index c0dedb59d..1e4e00a23 100644
--- a/native/jni/src/words_priority_queue.h
+++ b/native/jni/src/words_priority_queue.h
@@ -33,12 +33,14 @@ class WordsPriorityQueue {
unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];
int mWordLength;
bool mUsed;
+ int mType;
- void setParams(int score, unsigned short *word, int wordLength) {
+ void setParams(int score, unsigned short *word, int wordLength, int type) {
mScore = score;
mWordLength = wordLength;
memcpy(mWord, word, sizeof(unsigned short) * wordLength);
mUsed = true;
+ mType = type;
}
};
@@ -56,7 +58,7 @@ class WordsPriorityQueue {
delete[] mSuggestedWords;
}
- void push(int score, unsigned short *word, int wordLength) {
+ void push(int score, unsigned short *word, int wordLength, int type) {
SuggestedWord *sw = 0;
if (mSuggestions.size() >= MAX_WORDS) {
sw = mSuggestions.top();
@@ -69,9 +71,9 @@ class WordsPriorityQueue {
}
}
if (sw == 0) {
- sw = getFreeSuggestedWord(score, word, wordLength);
+ sw = getFreeSuggestedWord(score, word, wordLength, type);
} else {
- sw->setParams(score, word, wordLength);
+ sw->setParams(score, word, wordLength, type);
}
if (sw == 0) {
AKLOGE("SuggestedWord is accidentally null.");
@@ -94,7 +96,7 @@ class WordsPriorityQueue {
}
int outputSuggestions(const unsigned short *before, const int beforeLength,
- int *frequencies, unsigned short *outputChars) {
+ int *frequencies, unsigned short *outputChars, int* outputTypes) {
mHighestSuggestedWord = 0;
const unsigned int size = min(
MAX_WORDS, static_cast<unsigned int>(mSuggestions.size()));
@@ -127,7 +129,7 @@ class WordsPriorityQueue {
}
}
if (maxIndex > 0 && nsMaxSw) {
- memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(SuggestedWord*));
+ memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(SuggestedWord *));
swBuffer[0] = nsMaxSw;
}
}
@@ -138,11 +140,12 @@ class WordsPriorityQueue {
continue;
}
const unsigned int wordLength = sw->mWordLength;
- char *targetAdr = (char*) outputChars + i * MAX_WORD_LENGTH * sizeof(short);
+ unsigned short *targetAddress = outputChars + i * MAX_WORD_LENGTH;
frequencies[i] = sw->mScore;
- memcpy(targetAdr, sw->mWord, (wordLength) * sizeof(short));
+ outputTypes[i] = sw->mType;
+ memcpy(targetAddress, sw->mWord, wordLength * sizeof(unsigned short));
if (wordLength < MAX_WORD_LENGTH) {
- ((unsigned short*) targetAdr)[wordLength] = 0;
+ targetAddress[wordLength] = 0;
}
sw->mUsed = false;
}
@@ -191,10 +194,10 @@ class WordsPriorityQueue {
};
SuggestedWord *getFreeSuggestedWord(int score, unsigned short *word,
- int wordLength) {
+ int wordLength, int type) {
for (unsigned int i = 0; i < MAX_WORD_LENGTH; ++i) {
if (!mSuggestedWords[i].mUsed) {
- mSuggestedWords[i].setParams(score, word, wordLength);
+ mSuggestedWords[i].setParams(score, word, wordLength, type);
return &mSuggestedWords[i];
}
}
@@ -219,7 +222,7 @@ class WordsPriorityQueue {
before, beforeLength, word, wordLength, score);
}
- typedef std::priority_queue<SuggestedWord*, std::vector<SuggestedWord*>,
+ typedef std::priority_queue<SuggestedWord *, std::vector<SuggestedWord *>,
wordComparator> Suggestions;
Suggestions mSuggestions;
const unsigned int MAX_WORDS;