diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/spellcheck')
7 files changed, 140 insertions, 27 deletions
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 503b18b1b..65ebcf5f1 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -33,10 +33,9 @@ import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary; -import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary; import com.android.inputmethod.latin.UserBinaryDictionary; import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; +import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -267,6 +266,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService // if it doesn't. See documentation for binarySearch. final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1; + // Weak <- insertIndex == 0, ..., insertIndex == mLength -> Strong if (insertIndex == 0 && mLength >= mMaxLength) { // In the future, we may want to keep track of the best suggestion score even if // we are asked for 0 suggestions. In this case, we can use the following @@ -284,11 +284,6 @@ public final class AndroidSpellCheckerService extends SpellCheckerService // } return true; } - if (insertIndex >= mMaxLength) { - // We found a suggestion, but its score is too weak to be kept considering - // the suggestion limit. - return true; - } final String wordString = new String(word, wordOffset, wordLength); if (mLength < mMaxLength) { @@ -296,12 +291,13 @@ public final class AndroidSpellCheckerService extends SpellCheckerService ++mLength; System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen); mSuggestions.add(insertIndex, wordString); + mScores[insertIndex] = score; } else { - System.arraycopy(mScores, 1, mScores, 0, insertIndex); + System.arraycopy(mScores, 1, mScores, 0, insertIndex - 1); mSuggestions.add(insertIndex, wordString); mSuggestions.remove(0); + mScores[insertIndex - 1] = score; } - mScores[insertIndex] = score; return true; } @@ -320,7 +316,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService hasRecommendedSuggestions = false; } else { gatheredSuggestions = EMPTY_STRING_ARRAY; - final float normalizedScore = BinaryDictionary.calcNormalizedScore( + final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore( mOriginalText, mBestSuggestion, mBestScore); hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold); } @@ -355,7 +351,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService final int bestScore = mScores[mLength - 1]; final String bestSuggestion = mSuggestions.get(0); final float normalizedScore = - BinaryDictionary.calcNormalizedScore( + BinaryDictionaryUtils.calcNormalizedScore( mOriginalText, bestSuggestion.toString(), bestScore); hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold); if (DBG) { @@ -383,6 +379,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService new Thread("spellchecker_close_dicts") { @Override public void run() { + // Contacts dictionary can be closed multiple times here. If the dictionary is + // already closed, extra closings are no-ops, so it's safe. for (DictionaryPool pool : oldPools.values()) { pool.close(); } @@ -428,7 +426,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService final String localeStr = locale.toString(); UserBinaryDictionary userDictionary = mUserDictionaries.get(localeStr); if (null == userDictionary) { - userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true); + userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, locale, true); mUserDictionaries.put(localeStr, userDictionary); } dictionaryCollection.addDictionary(userDictionary); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index d6e5b75ad..69d092751 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -28,11 +28,13 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer; +import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -312,16 +314,21 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { false /* reportAsTypo */); } final WordComposer composer = new WordComposer(); - final int length = text.length(); - for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { - final int codePoint = text.codePointAt(i); - composer.addKeyInfo(codePoint, dictInfo.getKeyboard(codePoint)); + final int[] codePoints = StringUtils.toCodePointArray(text); + final int[] coordinates; + if (null == dictInfo.mKeyboard) { + coordinates = CoordinateUtils.newCoordinateArray(codePoints.length, + Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + } else { + coordinates = dictInfo.mKeyboard.getCoordinates(codePoints); } + composer.setComposingWord(codePoints, coordinates, null /* previousWord */); // TODO: make a spell checker option to block offensive words or not final ArrayList<SuggestedWordInfo> suggestions = dictInfo.mDictionary.getSuggestions(composer, prevWord, dictInfo.getProximityInfo(), true /* blockOffensiveWords */, - null /* additionalFeaturesOptions */); + null /* additionalFeaturesOptions */, + null /* inOutLanguageWeight */); if (suggestions != null) { for (final SuggestedWordInfo suggestion : suggestions) { final String suggestionStr = suggestion.mWord; diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java b/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java index b77f3e2c5..1ffe50681 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictAndKeyboard.java @@ -27,7 +27,7 @@ import com.android.inputmethod.keyboard.ProximityInfo; */ public final class DictAndKeyboard { public final Dictionary mDictionary; - private final Keyboard mKeyboard; + public final Keyboard mKeyboard; private final Keyboard mManualShiftedKeyboard; public DictAndKeyboard( @@ -43,13 +43,6 @@ public final class DictAndKeyboard { keyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED); } - public Keyboard getKeyboard(final int codePoint) { - if (mKeyboard == null) { - return null; - } - return mKeyboard.getKey(codePoint) != null ? mKeyboard : mManualShiftedKeyboard; - } - public ProximityInfo getProximityInfo() { return mKeyboard == null ? null : mKeyboard.getProximityInfo(); } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java index a0aed2829..c99264347 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java @@ -49,10 +49,12 @@ public final class DictionaryPool extends LinkedBlockingQueue<DictAndKeyboard> { final static ArrayList<SuggestedWordInfo> noSuggestions = CollectionUtils.newArrayList(); private final static DictAndKeyboard dummyDict = new DictAndKeyboard( new Dictionary(Dictionary.TYPE_MAIN) { + // TODO: this dummy dictionary should be a singleton in the Dictionary class. @Override public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { + final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, + final float[] inOutLanguageWeight) { return noSuggestions; } @Override diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java index 999ca775b..186dafd29 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java @@ -39,7 +39,7 @@ public final class SpellCheckerSettingsFragment extends PreferenceFragment { addPreferencesFromResource(R.xml.spell_checker_settings); final PreferenceScreen preferenceScreen = getPreferenceScreen(); if (preferenceScreen != null) { - preferenceScreen.setTitle(ApplicationUtils.getAcitivityTitleResId( + preferenceScreen.setTitle(ApplicationUtils.getActivityTitleResId( getActivity(), SpellCheckerSettingsActivity.class)); } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java new file mode 100644 index 000000000..a694bf47d --- /dev/null +++ b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedContactsBinaryDictionary.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package com.android.inputmethod.latin.spellcheck; + +import android.content.Context; + +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.ContactsBinaryDictionary; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.WordComposer; + +import java.util.ArrayList; +import java.util.Locale; + +public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary { + private static final String NAME = "spellcheck_contacts"; + private final Object mLock = new Object(); + + public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) { + super(context, locale, null /* dictFile */, NAME); + } + + @Override + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes, + final String prevWordForBigrams, final ProximityInfo proximityInfo, + final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, + final float[] inOutLanguageWeight) { + synchronized (mLock) { + return super.getSuggestions(codes, prevWordForBigrams, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight); + } + } + + @Override + public boolean isValidWord(final String word) { + synchronized (mLock) { + return super.isValidWord(word); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java new file mode 100644 index 000000000..1a6dd5818 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/spellcheck/SynchronouslyLoadedUserBinaryDictionary.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package com.android.inputmethod.latin.spellcheck; + +import android.content.Context; + +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.UserBinaryDictionary; +import com.android.inputmethod.latin.WordComposer; + +import java.util.ArrayList; +import java.util.Locale; + +public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary { + private static final String NAME = "spellcheck_user"; + private final Object mLock = new Object(); + + public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale) { + this(context, locale, false /* alsoUseMoreRestrictiveLocales */); + } + + public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale, + final boolean alsoUseMoreRestrictiveLocales) { + super(context, locale, alsoUseMoreRestrictiveLocales, null /* dictFile */, NAME); + } + + @Override + public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes, + final String prevWordForBigrams, final ProximityInfo proximityInfo, + final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, + final float[] inOutLanguageWeight) { + synchronized (mLock) { + return super.getSuggestions(codes, prevWordForBigrams, proximityInfo, + blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight); + } + } + + @Override + public boolean isValidWord(final String word) { + synchronized (mLock) { + return super.isValidWord(word); + } + } +} |