Change JNI for Gesture

Change-Id: I774a0052038d16677f60f7efa11fd266cb5f3088
main
Satoshi Kataoka 2012-06-25 17:44:54 +09:00
parent 5a73d72265
commit 7368009799
10 changed files with 68 additions and 44 deletions

View File

@ -40,6 +40,7 @@ public class BinaryDictionary extends Dictionary {
*/ */
public static final int MAX_WORD_LENGTH = 48; public static final int MAX_WORD_LENGTH = 48;
public static final int MAX_WORDS = 18; public static final int MAX_WORDS = 18;
public static final int MAX_SPACES = 16;
private static final String TAG = "BinaryDictionary"; private static final String TAG = "BinaryDictionary";
private static final int MAX_BIGRAMS = 60; private static final int MAX_BIGRAMS = 60;
@ -51,6 +52,7 @@ public class BinaryDictionary extends Dictionary {
private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
private final int[] mSpaceIndices = new int[MAX_SPACES];
private final int[] mScores = new int[MAX_WORDS]; private final int[] mScores = new int[MAX_WORDS];
private final int[] mBigramScores = new int[MAX_BIGRAMS]; private final int[] mBigramScores = new int[MAX_BIGRAMS];
@ -65,14 +67,12 @@ public class BinaryDictionary extends Dictionary {
* @param offset the offset of the dictionary data within the file. * @param offset the offset of the dictionary data within the file.
* @param length the length of the binary data. * @param length the length of the binary data.
* @param useFullEditDistance whether to use the full edit distance in suggestions * @param useFullEditDistance whether to use the full edit distance in suggestions
* @param dicTypeId the dictionary type id of the dictionary
*/ */
public BinaryDictionary(final Context context, public BinaryDictionary(final Context context,
final String filename, final long offset, final long length, final String filename, final long offset, final long length,
final boolean useFullEditDistance, final Locale locale) { final boolean useFullEditDistance, final Locale locale, final int dicTypeId) {
// Note: at the moment a binary dictionary is always of the "main" type. mDicTypeId = dicTypeId;
// Initializing this here will help transitioning out of the scheme where
// the Suggest class knows everything about every single dictionary.
mDicTypeId = Suggest.DIC_MAIN;
mUseFullEditDistance = useFullEditDistance; mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length); loadDictionary(filename, offset, length);
} }
@ -87,8 +87,10 @@ public class BinaryDictionary extends Dictionary {
private native int getFrequencyNative(long dict, int[] word, int wordLength); private native int getFrequencyNative(long dict, int[] word, int wordLength);
private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams, int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize,
boolean useFullEditDistance, char[] outputChars, int[] scores); int commitPoint, boolean isGesture, int dicTypeId,
int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars,
int[] scores, int[] outputIndices);
private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength, private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength,
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
int maxWordLength, int maxBigrams); int maxWordLength, int maxBigrams);
@ -131,7 +133,7 @@ public class BinaryDictionary extends Dictionary {
++len; ++len;
} }
if (len > 0) { if (len > 0) {
callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j], callback.addWord(mOutputChars_bigrams, null, start, len, mBigramScores[j],
mDicTypeId, Dictionary.BIGRAM); mDicTypeId, Dictionary.BIGRAM);
} }
} }
@ -141,9 +143,9 @@ public class BinaryDictionary extends Dictionary {
@Override @Override
public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams, public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
final WordCallback callback, final ProximityInfo proximityInfo) { final WordCallback callback, final ProximityInfo proximityInfo) {
final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
mScores);
final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
mScores, mSpaceIndices);
for (int j = 0; j < count; ++j) { for (int j = 0; j < count; ++j) {
if (mScores[j] < 1) break; if (mScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH; final int start = j * MAX_WORD_LENGTH;
@ -152,7 +154,7 @@ public class BinaryDictionary extends Dictionary {
++len; ++len;
} }
if (len > 0) { if (len > 0) {
callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId, callback.addWord(mOutputChars, null, start, len, mScores[j], mDicTypeId,
Dictionary.UNIGRAM); Dictionary.UNIGRAM);
} }
} }
@ -165,7 +167,7 @@ public class BinaryDictionary extends Dictionary {
// proximityInfo may not be null. // proximityInfo may not be null.
/* package for test */ int getSuggestions(final WordComposer codes, /* package for test */ int getSuggestions(final WordComposer codes,
final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo, final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo,
char[] outputChars, int[] scores) { char[] outputChars, int[] scores, int[] spaceIndices) {
if (!isValidDictionary()) return -1; if (!isValidDictionary()) return -1;
final int codesSize = codes.size(); final int codesSize = codes.size();
@ -179,14 +181,21 @@ public class BinaryDictionary extends Dictionary {
Arrays.fill(outputChars, (char) 0); Arrays.fill(outputChars, (char) 0);
Arrays.fill(scores, 0); Arrays.fill(scores, 0);
final int[] prevWordCodePointArray = null == prevWordForBigrams // TODO: toLowerCase in the native code
final int[] prevWordCodePointArray = (null == prevWordForBigrams)
? null : StringUtils.toCodePointArray(prevWordForBigrams.toString()); ? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
// TODO: pass the previous word to native code int[] emptyArray = new int[codesSize];
return getSuggestionsNative( Arrays.fill(emptyArray, 0);
mNativeDict, proximityInfo.getNativeProximityInfo(),
codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize, //final int commitPoint = codes.getCommitPoint();
prevWordCodePointArray, mUseFullEditDistance, outputChars, scores); //codes.clearCommitPoint();
return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
codes.getXCoordinates(), codes.getYCoordinates(), emptyArray, emptyArray, mInputCodes,
codesSize, 0 /* unused */, false, mDicTypeId,
prevWordCodePointArray, mUseFullEditDistance,
outputChars, scores, spaceIndices);
} }
public static float calcNormalizedScore(String before, String after, int score) { public static float calcNormalizedScore(String before, String after, int score) {

View File

@ -41,6 +41,7 @@ public abstract class Dictionary {
* Adds a word to a list of suggestions. The word is expected to be ordered based on * Adds a word to a list of suggestions. The word is expected to be ordered based on
* the provided score. * the provided score.
* @param word the character array containing the word * @param word the character array containing the word
* @param spaceIndices the indices of inserted spaces
* @param wordOffset starting offset of the word in the character array * @param wordOffset starting offset of the word in the character array
* @param wordLength length of valid characters in the character array * @param wordLength length of valid characters in the character array
* @param score the score of occurrence. This is normalized between 1 and 255, but * @param score the score of occurrence. This is normalized between 1 and 255, but
@ -49,8 +50,8 @@ public abstract class Dictionary {
* @param dataType tells type of this data, either UNIGRAM or BIGRAM * @param dataType tells type of this data, either UNIGRAM or BIGRAM
* @return true if the word was added, false if no more words are required * @return true if the word was added, false if no more words are required
*/ */
boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId, boolean addWord(char[] word, int[] spaceIndices, int wordOffset, int wordLength, int score,
int dataType); int dicTypeId, int dataType);
} }
/** /**

View File

@ -59,7 +59,7 @@ public class DictionaryFactory {
for (final AssetFileAddress f : assetFileList) { for (final AssetFileAddress f : assetFileList) {
final BinaryDictionary binaryDictionary = final BinaryDictionary binaryDictionary =
new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength,
useFullEditDistance, locale); useFullEditDistance, locale, Suggest.DIC_MAIN);
if (binaryDictionary.isValidDictionary()) { if (binaryDictionary.isValidDictionary()) {
dictList.add(binaryDictionary); dictList.add(binaryDictionary);
} }
@ -112,7 +112,7 @@ public class DictionaryFactory {
return null; return null;
} }
return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(),
false /* useFullEditDistance */, locale); false /* useFullEditDistance */, locale, Suggest.DIC_MAIN);
} catch (android.content.res.Resources.NotFoundException e) { } catch (android.content.res.Resources.NotFoundException e) {
Log.e(TAG, "Could not find the resource"); Log.e(TAG, "Could not find the resource");
return null; return null;
@ -140,7 +140,7 @@ public class DictionaryFactory {
long startOffset, long length, final boolean useFullEditDistance, Locale locale) { long startOffset, long length, final boolean useFullEditDistance, Locale locale) {
if (dictionary.isFile()) { if (dictionary.isFile()) {
return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length, return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length,
useFullEditDistance, locale); useFullEditDistance, locale, Suggest.DIC_MAIN);
} else { } else {
Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath()); Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
return null; return null;

View File

@ -306,7 +306,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
// Build the new binary dictionary // Build the new binary dictionary
final BinaryDictionary newBinaryDictionary = final BinaryDictionary newBinaryDictionary =
new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */, new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */,
null); null, mDicTypeId);
if (mBinaryDictionary != null) { if (mBinaryDictionary != null) {
// Ensure all threads accessing the current dictionary have finished before swapping in // Ensure all threads accessing the current dictionary have finished before swapping in

View File

@ -660,8 +660,9 @@ public class ExpandableDictionary extends Dictionary {
} while (node != null); } while (node != null);
if (freq >= 0) { if (freq >= 0) {
callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index, callback.addWord(mLookedUpString, null, index,
freq, mDicTypeId, Dictionary.BIGRAM); BinaryDictionary.MAX_WORD_LENGTH - index, freq, mDicTypeId,
Dictionary.BIGRAM);
} }
} }
} }

View File

@ -439,8 +439,8 @@ public class Suggest implements Dictionary.WordCallback {
// TODO: Use codepoint instead of char // TODO: Use codepoint instead of char
@Override @Override
public boolean addWord(final char[] word, final int offset, final int length, int score, public boolean addWord(final char[] word, int[] indices, final int offset, final int length,
final int dicTypeId, final int dataType) { int score, final int dicTypeId, final int dataType) {
int dataTypeForLog = dataType; int dataTypeForLog = dataType;
final ArrayList<SuggestedWordInfo> suggestions; final ArrayList<SuggestedWordInfo> suggestions;
final int prefMaxSuggestions; final int prefMaxSuggestions;

View File

@ -537,7 +537,7 @@ public class Utils {
final Dictionary.WordCallback callback) { final Dictionary.WordCallback callback) {
for (SuggestedWordInfo suggestion : suggestions) { for (SuggestedWordInfo suggestion : suggestions) {
final String suggestionStr = suggestion.mWord.toString(); final String suggestionStr = suggestion.mWord.toString();
callback.addWord(suggestionStr.toCharArray(), 0, suggestionStr.length(), callback.addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(),
suggestion.mScore, dicTypeId, dataType); suggestion.mScore, dicTypeId, dataType);
} }
} }

View File

@ -238,8 +238,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
} }
@Override @Override
synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset,
int dicTypeId, int dataType) { int wordLength, int score, int dicTypeId, int dataType) {
final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score); final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score);
// binarySearch returns the index if the element exists, and -<insertion index> - 1 // binarySearch returns the index if the element exists, and -<insertion index> - 1
// if it doesn't. See documentation for binarySearch. // if it doesn't. See documentation for binarySearch.

View File

@ -128,28 +128,37 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict,
jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray,
jintArray inputArray, jint arraySize, jintArray prevWordForBigrams, jintArray timesArray, jintArray pointerIdArray, jintArray inputArray, jint arraySize,
jboolean useFullEditDistance, jcharArray outputArray, jintArray frequencyArray) { jint commitPoint, jboolean isGesture, jint dicTypeId,
Dictionary *dictionary = (Dictionary*)dict; jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray,
jintArray frequencyArray, jintArray spaceIndexArray) {
Dictionary *dictionary = (Dictionary*) dict;
if (!dictionary) return 0; if (!dictionary) return 0;
ProximityInfo *pInfo = (ProximityInfo*)proximityInfo; ProximityInfo *pInfo = (ProximityInfo*)proximityInfo;
int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0); int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0);
int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0); int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0);
int *times = env->GetIntArrayElements(timesArray, 0);
int *pointerIds = env->GetIntArrayElements(pointerIdArray, 0);
int *frequencies = env->GetIntArrayElements(frequencyArray, 0); int *frequencies = env->GetIntArrayElements(frequencyArray, 0);
int *inputCodes = env->GetIntArrayElements(inputArray, 0); int *inputCodes = env->GetIntArrayElements(inputArray, 0);
jchar *outputChars = env->GetCharArrayElements(outputArray, 0); jchar *outputChars = env->GetCharArrayElements(outputArray, 0);
int *spaceIndices = env->GetIntArrayElements(spaceIndexArray, 0);
jint *prevWordChars = prevWordForBigrams jint *prevWordChars = prevWordForBigrams
? env->GetIntArrayElements(prevWordForBigrams, 0) : 0; ? env->GetIntArrayElements(prevWordForBigrams, 0) : 0;
jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0; jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0;
int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, inputCodes, int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, times, pointerIds,
arraySize, prevWordChars, prevWordLength, useFullEditDistance, inputCodes, arraySize, prevWordChars, prevWordLength, commitPoint, isGesture,
(unsigned short*) outputChars, frequencies); dicTypeId, useFullEditDistance, (unsigned short*) outputChars,
frequencies, spaceIndices);
if (prevWordChars) { if (prevWordChars) {
env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT); env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT);
} }
env->ReleaseIntArrayElements(spaceIndexArray, spaceIndices, 0);
env->ReleaseCharArrayElements(outputArray, outputChars, 0); env->ReleaseCharArrayElements(outputArray, outputChars, 0);
env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT); env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
env->ReleaseIntArrayElements(frequencyArray, frequencies, 0); env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
env->ReleaseIntArrayElements(pointerIdArray, pointerIds, 0);
env->ReleaseIntArrayElements(timesArray, times, 0);
env->ReleaseIntArrayElements(yCoordinatesArray, yCoordinates, 0); env->ReleaseIntArrayElements(yCoordinatesArray, yCoordinates, 0);
env->ReleaseIntArrayElements(xCoordinatesArray, xCoordinates, 0); env->ReleaseIntArrayElements(xCoordinatesArray, xCoordinates, 0);
return count; return count;
@ -251,8 +260,8 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) {
static JNINativeMethod sMethods[] = { static JNINativeMethod sMethods[] = {
{"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open}, {"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open},
{"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close}, {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close},
{"getSuggestionsNative", "(JJ[I[I[II[IZ[C[I)I", {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZI[IZ[C[I[I)I",
(void*)latinime_BinaryDictionary_getSuggestions}, (void*) latinime_BinaryDictionary_getSuggestions},
{"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency}, {"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency},
{"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram}, {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram},
{"getBigramsNative", "(J[II[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams}, {"getBigramsNative", "(J[II[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams},

View File

@ -34,15 +34,19 @@ class Dictionary {
int fullWordMultiplier, int maxWordLength, int maxWords); int fullWordMultiplier, int maxWordLength, int maxWords);
int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
int *codes, int codesSize, const int32_t* prevWordChars, const int prevWordLength, int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars,
bool useFullEditDistance, unsigned short *outWords, int *frequencies) const { int prevWordLength, int commitPoint, bool isGesture, int dicTypeId,
bool useFullEditDistance, unsigned short *outWords,
int *frequencies, int *spaceIndices) {
int result = 0;
std::map<int, int> bigramMap; std::map<int, int> bigramMap;
uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE]; uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
mBigramDictionary->fillBigramAddressToFrequencyMapAndFilter(prevWordChars, mBigramDictionary->fillBigramAddressToFrequencyMapAndFilter(prevWordChars,
prevWordLength, &bigramMap, bigramFilter); prevWordLength, &bigramMap, bigramFilter);
return mUnigramDictionary->getSuggestions(proximityInfo, result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates,
xcoordinates, ycoordinates, codes, codesSize, &bigramMap, ycoordinates, codes, codesSize, &bigramMap, bigramFilter,
bigramFilter, useFullEditDistance, outWords, frequencies); useFullEditDistance, outWords, frequencies);
return result;
} }
int getBigrams(const int32_t *word, int length, int *codes, int codesSize, int getBigrams(const int32_t *word, int length, int *codes, int codesSize,