BinaryDictionary.java revision 6ba8de2a608dfe4865b0b59a753f2d2abbedeeff
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project
3e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa *
4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at
7e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa *
8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
9e90b333017c68e888a5e3d351f07ea29036457d0Ken Wakasa *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under
14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
19fa086c90760bc2bedf0b74eacb0fed3bf7ebc2b7Tadashi G. Takaokaimport android.content.Context;
20fa086c90760bc2bedf0b74eacb0fed3bf7ebc2b7Tadashi G. Takaoka
21ab72a97d7ce44230a0c824797d1675a5ca354a56Tadashi G. Takaokaimport com.android.inputmethod.keyboard.ProximityInfo;
22ab72a97d7ce44230a0c824797d1675a5ca354a56Tadashi G. Takaoka
23923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.Arrays;
24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/**
26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Implements a static, compacted, binary dictionary of standard words.
27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class BinaryDictionary extends Dictionary {
29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
30cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard    public static final String DICTIONARY_PACK_AUTHORITY =
31cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard            "com.android.inputmethod.latin.dictionarypack";
32cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard
33979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    /**
34cba93f50c3d46ada773ec49435689dc3e2094385Jean Chalard     * There is a difference between what java and native code can handle.
35979f8690967ff5409fe18f5085858ccdb8e0ccf1satok     * This value should only be used in BinaryDictionary.java
36979f8690967ff5409fe18f5085858ccdb8e0ccf1satok     * It is necessary to keep it at this value because some languages e.g. German have
37979f8690967ff5409fe18f5085858ccdb8e0ccf1satok     * really long words.
38979f8690967ff5409fe18f5085858ccdb8e0ccf1satok     */
398fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    public static final int MAX_WORD_LENGTH = 48;
402e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka    public static final int MAX_WORDS = 18;
41979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
42979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    private static final String TAG = "BinaryDictionary";
43979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    private static final int MAX_BIGRAMS = 60;
44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int TYPED_LETTER_MULTIPLIER = 2;
46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
47979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    private int mDicTypeId;
485fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private long mNativeDict;
496ba8de2a608dfe4865b0b59a753f2d2abbedeeffsatok    private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
5030088259480130e5bac5c2028e2c7c3e6d4c51a2satok    private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
5130088259480130e5bac5c2028e2c7c3e6d4c51a2satok    private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
52e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka    private final int[] mScores = new int[MAX_WORDS];
53e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka    private final int[] mBigramScores = new int[MAX_BIGRAMS];
54923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
55071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka    public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING =
56c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard            new Flag(R.bool.config_require_umlaut_processing, 0x1);
57cc78d03a62412e647d4c1373e88a4a2637244ed5Jean Chalard    public static final Flag FLAG_REQUIRES_FRENCH_LIGATURES_PROCESSING =
58cc78d03a62412e647d4c1373e88a4a2637244ed5Jean Chalard            new Flag(R.bool.config_require_ligatures_processing, 0x4);
59c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard
60673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // FULL_EDIT_DISTANCE is a flag that forces the dictionary to use full words
61673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // when computing edit distance, instead of the default behavior of stopping
62673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // the evaluation at the size the user typed.
6340a5f6fa4df529bf21813d54fc20ffe5b3cbe436satok    public static final Flag FLAG_USE_FULL_EDIT_DISTANCE = new Flag(0x2);
6440a5f6fa4df529bf21813d54fc20ffe5b3cbe436satok
65c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard    // Can create a new flag from extravalue :
66c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard    // public static final Flag FLAG_MYFLAG =
67c899038eee5c01d520a2707cca01ee093a674d05Jean Chalard    //         new Flag("my_flag", 0x02);
68071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka
69673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // ALL_CONFIG_FLAGS is a collection of flags that enable reading all flags from configuration.
70673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // This is but a mask - it does not mean the flags will be on, only that the configuration
71673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    // will be read for this particular flag.
72673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard    public static final Flag[] ALL_CONFIG_FLAGS = {
73071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka        // Here should reside all flags that trigger some special processing
74071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka        // These *must* match the definition in UnigramDictionary enum in
75071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka        // unigram_dictionary.h so please update both at the same time.
76673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard        // Please note that flags created with a resource are of type CONFIG while flags
77673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard        // created with a string are of type EXTRAVALUE. These behave like masks, and the
78673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard        // actual value will be read from the configuration/extra value at run time for
79673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard        // the configuration at dictionary creation time.
80071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka        FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING,
81cc78d03a62412e647d4c1373e88a4a2637244ed5Jean Chalard        FLAG_REQUIRES_FRENCH_LIGATURES_PROCESSING,
82071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka    };
83071f47140cec02197de5e163f45c77990b39457dTadashi G. Takaoka
84c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard    private int mFlags = 0;
85923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    /**
874250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * Constructor for the binary dictionary. This is supposed to be called from the
884250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * dictionary factory.
894250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * All implementations should pass null into flagArray, except for testing purposes.
904250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * @param context the context to access the environment from.
914250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * @param filename the name of the file to read through native code.
924250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * @param offset the offset of the dictionary data within the file.
934250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * @param length the length of the binary data.
944250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard     * @param flagArray the flags to limit the dictionary to, or null for default.
95923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project     */
964250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard    public BinaryDictionary(final Context context,
974250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard            final String filename, final long offset, final long length, Flag[] flagArray) {
984250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        // Note: at the moment a binary dictionary is always of the "main" type.
994250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        // Initializing this here will help transitioning out of the scheme where
1004250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        // the Suggest class knows everything about every single dictionary.
1014250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        mDicTypeId = Suggest.DIC_MAIN;
1024250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        // TODO: Stop relying on the state of SubtypeSwitcher, get it as a parameter
103673cebf9e97289b3b0cd343ff7193dff69684a48Jean Chalard        mFlags = Flag.initFlags(null == flagArray ? ALL_CONFIG_FLAGS : flagArray, context,
1044250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard                SubtypeSwitcher.getInstance());
1054250eb27f54f8fedc388fe4825b0646a88778744Jean Chalard        loadDictionary(filename, offset, length);
106979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
107979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
108eaef1c500703b4ee378821884c7b108815ed2983Ken Wakasa    static {
109cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka        JniUtils.loadNativeLibrary();
110eaef1c500703b4ee378821884c7b108815ed2983Ken Wakasa    }
111c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard
1125fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private native long openNative(String sourceDir, long dictOffset, long dictSize,
1136ba8de2a608dfe4865b0b59a753f2d2abbedeeffsatok            int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords);
1145fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private native void closeNative(long dict);
1155fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private native boolean isValidWordNative(long dict, char[] word, int wordLength);
1165fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
117c2bbc6a4499a6da979381fa0e8e6e855a5ac6aa4Jean Chalard            int[] yCoordinates, int[] inputCodes, int codesSize, int flags, char[] outputChars,
118e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka            int[] scores);
1195fdcd7d5cd9d39d41568aa1412a4b1a866c05d3aTadashi G. Takaoka    private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength,
120e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka            int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
1216ba8de2a608dfe4865b0b59a753f2d2abbedeeffsatok            int maxWordLength, int maxBigrams);
122be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    private static native double calcNormalizedScoreNative(
123be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok            char[] before, int beforeLength, char[] after, int afterLength, int score);
124be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    private static native int editDistanceNative(
125be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok            char[] before, int beforeLength, char[] after, int afterLength);
126979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
12733e0b1e79e464ac48a09433bbfcbb17ded620452Tadashi G. Takaoka    private final void loadDictionary(String path, long startOffset, long length) {
12833e0b1e79e464ac48a09433bbfcbb17ded620452Tadashi G. Takaoka        mNativeDict = openNative(path, startOffset, length,
1296ba8de2a608dfe4865b0b59a753f2d2abbedeeffsatok                TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS);
130979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    }
131979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
132979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    @Override
133979f8690967ff5409fe18f5085858ccdb8e0ccf1satok    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
134887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka            final WordCallback callback) {
135da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa        if (mNativeDict == 0) return;
136da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa
137979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        char[] chars = previousWord.toString().toCharArray();
138979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        Arrays.fill(mOutputChars_bigrams, (char) 0);
139e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka        Arrays.fill(mBigramScores, 0);
140979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
141979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        int codesSize = codes.size();
142979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        Arrays.fill(mInputCodes, -1);
143ad290d6505247171e1e8437446c6f5d148a01778Jean Chalard        if (codesSize > 0) {
14401ab7c8b59a7f12862fbd95fb252e56719f1757fsatok            mInputCodes[0] = codes.getCodeAt(0);
145ad290d6505247171e1e8437446c6f5d148a01778Jean Chalard        }
146979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
147979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize,
1486ba8de2a608dfe4865b0b59a753f2d2abbedeeffsatok                mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS);
1496ca3ac08ed536c415ac68913e23fde175b5e3f4dJean Chalard        if (count > MAX_BIGRAMS) {
1506ca3ac08ed536c415ac68913e23fde175b5e3f4dJean Chalard            count = MAX_BIGRAMS;
1516ca3ac08ed536c415ac68913e23fde175b5e3f4dJean Chalard        }
152979f8690967ff5409fe18f5085858ccdb8e0ccf1satok
153f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok        for (int j = 0; j < count; ++j) {
154ad290d6505247171e1e8437446c6f5d148a01778Jean Chalard            if (codesSize > 0 && mBigramScores[j] < 1) break;
155f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok            final int start = j * MAX_WORD_LENGTH;
156979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            int len = 0;
157f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok            while (len <  MAX_WORD_LENGTH && mOutputChars_bigrams[start + len] != 0) {
158f5cded1c6cf0f39df13750d4f9f5ba66c1b32964satok                ++len;
159979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            }
160979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            if (len > 0) {
161e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka                callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j],
1626e082cb30dbe1a8cc314b474dc1377b85fdb25c2Jean Chalard                        mDicTypeId, Dictionary.BIGRAM);
163979f8690967ff5409fe18f5085858ccdb8e0ccf1satok            }
164979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        }
165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
166923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
167043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard    // proximityInfo may not be null.
168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
169043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard    public void getWords(final WordComposer codes, final WordCallback callback,
170043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard            final ProximityInfo proximityInfo) {
171043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard        final int count = getSuggestions(codes, proximityInfo, mOutputChars, mScores);
1726f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka
1736f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        for (int j = 0; j < count; ++j) {
174e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka            if (mScores[j] < 1) break;
1756f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            final int start = j * MAX_WORD_LENGTH;
1766f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            int len = 0;
1776f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            while (len < MAX_WORD_LENGTH && mOutputChars[start + len] != 0) {
1786f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka                ++len;
1796f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            }
1806f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            if (len > 0) {
181e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka                callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId,
1826e082cb30dbe1a8cc314b474dc1377b85fdb25c2Jean Chalard                        Dictionary.UNIGRAM);
1836f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka            }
1846f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        }
1856f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka    }
1866f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka
1876f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka    /* package for test */ boolean isValidDictionary() {
1886f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        return mNativeDict != 0;
1896f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka    }
1906f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka
191043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard    // proximityInfo may not be null.
192043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard    /* package for test */ int getSuggestions(final WordComposer codes,
193043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard            final ProximityInfo proximityInfo, char[] outputChars, int[] scores) {
1946f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        if (!isValidDictionary()) return -1;
195da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa
196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        final int codesSize = codes.size();
197979f8690967ff5409fe18f5085858ccdb8e0ccf1satok        // Won't deal with really long words.
1986f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        if (codesSize > MAX_WORD_LENGTH - 1) return -1;
19930088259480130e5bac5c2028e2c7c3e6d4c51a2satok
200887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka        Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE);
201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        for (int i = 0; i < codesSize; i++) {
20201ab7c8b59a7f12862fbd95fb252e56719f1757fsatok            mInputCodes[i] = codes.getCodeAt(i);
203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
2042e04770adfc16344f69d316efd3ed0a617ede330Tadashi G. Takaoka        Arrays.fill(outputChars, (char) 0);
205e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka        Arrays.fill(scores, 0);
206c3df2d6fd27f3a5b84040b59aece3367769f0cb6Amith Yamasani
2076f4eba814a7f8426617db61f928a965209ebf359Tadashi G. Takaoka        return getSuggestionsNative(
208043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard                mNativeDict, proximityInfo.getNativeProximityInfo(),
2098fbd55229243cb66c03d5ea1f79dfb39f596590dsatok                codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize,
210e7a2512aa3666e1b891dc7dfc5a0cb28fd66bea9Tadashi G. Takaoka                mFlags, outputChars, scores);
211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
213be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    public static double calcNormalizedScore(String before, String after, int score) {
214be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok        return calcNormalizedScoreNative(before.toCharArray(), before.length(),
215be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok                after.toCharArray(), after.length(), score);
216be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    }
217be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok
218be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    public static int editDistance(String before, String after) {
219be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok        return editDistanceNative(
220be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok                before.toCharArray(), before.length(), after.toCharArray(), after.length());
221be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok    }
222be0cf72253f15bff6abdeaa79f60a56f06ab7b86satok
223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
224923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean isValidWord(CharSequence word) {
225923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (word == null) return false;
226f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani        char[] chars = word.toString().toCharArray();
227923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return isValidWordNative(mNativeDict, chars, chars.length);
228923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
229c3df2d6fd27f3a5b84040b59aece3367769f0cb6Amith Yamasani
23036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    @Override
231923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public synchronized void close() {
232da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa        closeInternal();
233da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa    }
234da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa
235da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa    private void closeInternal() {
236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mNativeDict != 0) {
237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            closeNative(mNativeDict);
238923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mNativeDict = 0;
239923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    protected void finalize() throws Throwable {
244da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa        try {
245da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa            closeInternal();
246da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa        } finally {
247da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa            super.finalize();
248da50e1e98dadc3733c615dfb8d87fe8b4688c782Ken Wakasa        }
249923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
250923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
251