diff options
13 files changed, 490 insertions, 403 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 8246c924b..03425ef1f 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -60,7 +60,7 @@ import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.settings.DebugSettings; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; -import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; +import com.android.inputmethod.latin.utils.SpacebarLanguageUtils; import com.android.inputmethod.latin.utils.TypefaceUtils; import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils; import com.android.inputmethod.research.ResearchLogger; @@ -918,14 +918,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // Layout language name on spacebar. private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype, final int width) { - // Choose appropriate language name to fit into the width. - final String fullText = SubtypeLocaleUtils.getFullDisplayName(subtype); + final String fullText = SpacebarLanguageUtils.getFullDisplayName(subtype); if (fitsTextIntoWidth(width, fullText, paint)) { return fullText; } - final String middleText = SubtypeLocaleUtils.getMiddleDisplayName(subtype); + final String middleText = SpacebarLanguageUtils.getMiddleDisplayName(subtype); if (fitsTextIntoWidth(width, middleText, paint)) { return middleText; } diff --git a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java new file mode 100644 index 000000000..89837c641 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014 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.utils; + +import android.view.inputmethod.InputMethodSubtype; + +import java.util.Locale; + +public final class SpacebarLanguageUtils { + private SpacebarLanguageUtils() { + // Intentional empty constructor for utility class. + } + + // InputMethodSubtype's display name for spacebar text in its locale. + // isAdditionalSubtype (T=true, F=false) + // locale layout | Middle Full + // ------ ------- - --------- ---------------------- + // en_US qwerty F English English (US) exception + // en_GB qwerty F English English (UK) exception + // es_US spanish F Español Español (EE.UU.) exception + // fr azerty F Français Français + // fr_CA qwerty F Français Français (Canada) + // fr_CH swiss F Français Français (Suisse) + // de qwertz F Deutsch Deutsch + // de_CH swiss T Deutsch Deutsch (Schweiz) + // zz qwerty F QWERTY QWERTY + // fr qwertz T Français Français + // de qwerty T Deutsch Deutsch + // en_US azerty T English English (US) + // zz azerty T AZERTY AZERTY + // Get InputMethodSubtype's full display name in its locale. + public static String getFullDisplayName(final InputMethodSubtype subtype) { + if (SubtypeLocaleUtils.isNoLanguage(subtype)) { + return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype); + } + return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale()); + } + + // Get InputMethodSubtype's middle display name in its locale. + public static String getMiddleDisplayName(final InputMethodSubtype subtype) { + if (SubtypeLocaleUtils.isNoLanguage(subtype)) { + return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype); + } + final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()); + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java index 4f556f972..2452864d5 100644 --- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java @@ -292,41 +292,6 @@ public final class SubtypeLocaleUtils { return keyboardLayoutSet; } - // InputMethodSubtype's display name for spacebar text in its locale. - // isAdditionalSubtype (T=true, F=false) - // locale layout | Middle Full - // ------ ------- - --------- ---------------------- - // en_US qwerty F English English (US) exception - // en_GB qwerty F English English (UK) exception - // es_US spanish F Español Español (EE.UU.) exception - // fr azerty F Français Français - // fr_CA qwerty F Français Français (Canada) - // fr_CH swiss F Français Français (Suisse) - // de qwertz F Deutsch Deutsch - // de_CH swiss T Deutsch Deutsch (Schweiz) - // zz qwerty F QWERTY QWERTY - // fr qwertz T Français Français - // de qwerty T Deutsch Deutsch - // en_US azerty T English English (US) - // zz azerty T AZERTY AZERTY - - // Get InputMethodSubtype's full display name in its locale. - public static String getFullDisplayName(final InputMethodSubtype subtype) { - if (isNoLanguage(subtype)) { - return getKeyboardLayoutSetDisplayName(subtype); - } - return getSubtypeLocaleDisplayName(subtype.getLocale()); - } - - // Get InputMethodSubtype's middle display name in its locale. - public static String getMiddleDisplayName(final InputMethodSubtype subtype) { - if (isNoLanguage(subtype)) { - return getKeyboardLayoutSetDisplayName(subtype); - } - final Locale locale = getSubtypeLocale(subtype); - return getSubtypeLocaleDisplayName(locale.getLanguage()); - } - // TODO: Get this information from the framework instead of maintaining here by ourselves. // Sorted list of known Right-To-Left language codes. private static final String[] SORTED_RTL_LANGUAGES = { diff --git a/native/jni/Android.mk b/native/jni/Android.mk index afb32d1da..c1372bd70 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -34,9 +34,6 @@ LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-ali # To suppress compiler warnings for unused variables/functions used for debug features etc. LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function -# For C++11 -LOCAL_CFLAGS += -std=c++11 - include $(LOCAL_PATH)/NativeFileList.mk LOCAL_SRC_FILES := \ diff --git a/native/jni/src/suggest/core/dicnode/dic_node.cpp b/native/jni/src/suggest/core/dicnode/dic_node.cpp index 73855977e..414dc3b1e 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node.cpp +++ b/native/jni/src/suggest/core/dicnode/dic_node.cpp @@ -24,8 +24,7 @@ DicNode::DicNode(const DicNode &dicNode) mProfiler(dicNode.mProfiler), #endif mDicNodeProperties(dicNode.mDicNodeProperties), mDicNodeState(dicNode.mDicNodeState), - mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion), mIsUsed(dicNode.mIsUsed), - mReleaseListener(nullptr) { + mIsCachedForNextSuggestion(dicNode.mIsCachedForNextSuggestion) { /* empty */ } @@ -36,8 +35,6 @@ DicNode &DicNode::operator=(const DicNode &dicNode) { mDicNodeProperties = dicNode.mDicNodeProperties; mDicNodeState = dicNode.mDicNodeState; mIsCachedForNextSuggestion = dicNode.mIsCachedForNextSuggestion; - mIsUsed = dicNode.mIsUsed; - mReleaseListener = dicNode.mReleaseListener; return *this; } diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h index 258aa9ce3..47f5ec0d7 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node.h +++ b/native/jni/src/suggest/core/dicnode/dic_node.h @@ -19,7 +19,6 @@ #include "defines.h" #include "suggest/core/dicnode/dic_node_profiler.h" -#include "suggest/core/dicnode/dic_node_release_listener.h" #include "suggest/core/dicnode/dic_node_utils.h" #include "suggest/core/dicnode/internal/dic_node_state.h" #include "suggest/core/dicnode/internal/dic_node_properties.h" @@ -45,7 +44,8 @@ + mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(), \ charBuf, NELEMS(charBuf)); \ AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %d, %5f,", header, \ - getSpatialDistanceForScoring(), getLanguageDistanceForScoring(), \ + getSpatialDistanceForScoring(), \ + mDicNodeState.mDicNodeStateScoring.getLanguageDistance(), \ getNormalizedCompoundDistance(), getRawLength(), charBuf, \ getInputIndex(0), getNormalizedCompoundDistanceAfterFirstWord()); \ } while (0) @@ -89,8 +89,7 @@ class DicNode { #if DEBUG_DICT mProfiler(), #endif - mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false), - mIsUsed(false), mReleaseListener(nullptr) {} + mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {} DicNode(const DicNode &dicNode); DicNode &operator=(const DicNode &dicNode); @@ -98,7 +97,6 @@ class DicNode { // Init for copy void initByCopy(const DicNode *const dicNode) { - mIsUsed = true; mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties); mDicNodeState.initByCopy(&dicNode->mDicNodeState); @@ -107,7 +105,6 @@ class DicNode { // Init for root with prevWordPtNodePos which is used for bigram void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) { - mIsUsed = true; mIsCachedForNextSuggestion = false; mDicNodeProperties.init(rootPtNodeArrayPos, prevWordPtNodePos); mDicNodeState.init(); @@ -116,7 +113,6 @@ class DicNode { // Init for root with previous word void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) { - mIsUsed = true; mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; mDicNodeProperties.init(rootPtNodeArrayPos, dicNode->mDicNodeProperties.getPtNodePos()); mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState, @@ -125,10 +121,11 @@ class DicNode { } void initAsPassingChild(DicNode *parentDicNode) { - mIsUsed = true; mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion; - const int parentCodePoint = parentDicNode->getNodeTypedCodePoint(); - mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint); + const int codePoint = + parentDicNode->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt( + parentDicNode->getNodeCodePointCount()); + mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, codePoint); mDicNodeState.initByCopy(&parentDicNode->mDicNodeState); PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler); } @@ -137,7 +134,6 @@ class DicNode { const int childrenPtNodeArrayPos, const int probability, const bool isTerminal, const bool hasChildren, const bool isBlacklistedOrNotAWord, const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) { - mIsUsed = true; uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1); mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; const uint16_t newLeavingDepth = static_cast<uint16_t>( @@ -150,17 +146,6 @@ class DicNode { PROF_NODE_COPY(&dicNode->mProfiler, mProfiler); } - AK_FORCE_INLINE void finalize() { - mIsUsed = false; - if (mReleaseListener) { - mReleaseListener->onReleased(this); - } - } - - bool isUsed() const { - return mIsUsed; - } - bool isRoot() const { return getNodeCodePointCount() == 0; } @@ -186,11 +171,6 @@ class DicNode { mIsCachedForNextSuggestion = true; } - // Used to expand the node in DicNodeUtils - int getNodeTypedCodePoint() const { - return mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(getNodeCodePointCount()); - } - // Check if the current word and the previous word can be considered as a valid multiple word // suggestion. bool isValidMultipleWordSuggestion() const { @@ -261,17 +241,13 @@ class DicNode { } bool isTotalInputSizeExceedingLimit() const { - const int prevWordsLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(); - const int currentWordDepth = getNodeCodePointCount(); // TODO: 3 can be 2? Needs to be investigated. // TODO: Have a const variable for 3 (or 2) - return prevWordsLen + currentWordDepth > MAX_WORD_LENGTH - 3; + return getTotalNodeCodePointCount() > MAX_WORD_LENGTH - 3; } void outputResult(int *dest) const { - const uint16_t prevWordLength = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(); - const uint16_t currentDepth = getNodeCodePointCount(); - memmove(dest, getOutputWordBuf(), (prevWordLength + currentDepth) * sizeof(dest[0])); + memmove(dest, getOutputWordBuf(), getTotalNodeCodePointCount() * sizeof(dest[0])); DUMP_WORD_AND_SCORE("OUTPUT"); } @@ -329,11 +305,6 @@ class DicNode { return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight); } - // Used to commit input partially - int getPrevWordPtNodePos() const { - return mDicNodeProperties.getPrevWordTerminalPtNodePos(); - } - AK_FORCE_INLINE const int *getOutputWordBuf() const { return mDicNodeState.mDicNodeStateOutput.getCodePointBuf(); } @@ -396,10 +367,6 @@ class DicNode { return mDicNodeState.mDicNodeStateScoring.getSpatialDistance(); } - float getLanguageDistanceForScoring() const { - return mDicNodeState.mDicNodeStateScoring.getLanguageDistance(); - } - // For space-aware gestures, we store the normalized distance at the char index // that ends the first word of the suggestion. We call this the distance after // first word. @@ -407,22 +374,10 @@ class DicNode { return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistanceAfterFirstWord(); } - float getLanguageDistanceRatePerWordForScoring() const { - const float langDist = getLanguageDistanceForScoring(); - const float totalWordCount = - static_cast<float>(mDicNodeState.mDicNodeStateOutput.getPrevWordCount() + 1); - return langDist / totalWordCount; - } - float getRawLength() const { return mDicNodeState.mDicNodeStateScoring.getRawLength(); } - bool isLessThanOneErrorForScoring() const { - return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount() - + mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount() <= 1; - } - DoubleLetterLevel getDoubleLetterLevel() const { return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel(); } @@ -466,10 +421,6 @@ class DicNode { #endif } - void setReleaseListener(DicNodeReleaseListener *releaseListener) { - mReleaseListener = releaseListener; - } - AK_FORCE_INLINE bool compare(const DicNode *right) const { // Promote exact matches to prevent them from being pruned. const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes()); @@ -507,8 +458,6 @@ class DicNode { DicNodeState mDicNodeState; // TODO: Remove bool mIsCachedForNextSuggestion; - bool mIsUsed; - DicNodeReleaseListener *mReleaseListener; AK_FORCE_INLINE int getTotalInputIndex() const { int index = 0; diff --git a/native/jni/src/suggest/core/dicnode/dic_node_pool.h b/native/jni/src/suggest/core/dicnode/dic_node_pool.h new file mode 100644 index 000000000..a660b744f --- /dev/null +++ b/native/jni/src/suggest/core/dicnode/dic_node_pool.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 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_NODE_POOL_H +#define LATINIME_DIC_NODE_POOL_H + +#include <deque> +#include <unordered_set> +#include <vector> + +#include "defines.h" +#include "suggest/core/dicnode/dic_node.h" + +namespace latinime { + +class DicNodePool { + public: + explicit DicNodePool(const int capacity) : mDicNodes(), mPooledDicNodes() { + reset(capacity); + } + + void reset(const int capacity) { + if (capacity == static_cast<int>(mDicNodes.size()) + && capacity == static_cast<int>(mPooledDicNodes.size())) { + // No need to reset. + return; + } + mDicNodes.resize(capacity); + mDicNodes.shrink_to_fit(); + mPooledDicNodes.clear(); + for (auto &dicNode : mDicNodes) { + mPooledDicNodes.emplace_back(&dicNode); + } + } + + // Get a DicNode instance from the pool. The instance has to be returned by returnInstance(). + DicNode *getInstance() { + if (mPooledDicNodes.empty()) { + return nullptr; + } + DicNode *const dicNode = mPooledDicNodes.back(); + mPooledDicNodes.pop_back(); + return dicNode; + } + + // Return an instance that has been removed from the pool by getInstance() to the pool. The + // instance must not be used after returning without getInstance(). + void placeBackInstance(DicNode *dicNode) { + mPooledDicNodes.emplace_back(dicNode); + } + + void dump() const { + AKLOGI("\n\n\n\n\n==========================="); + std::unordered_set<const DicNode*> usedDicNodes; + for (const auto &dicNode : mDicNodes) { + usedDicNodes.insert(&dicNode); + } + for (const auto &dicNodePtr : mPooledDicNodes) { + usedDicNodes.erase(dicNodePtr); + } + for (const auto &usedDicNodePtr : usedDicNodes) { + usedDicNodePtr->dump("DIC_NODE_POOL: "); + } + AKLOGI("===========================\n\n\n\n\n"); + } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePool); + + std::vector<DicNode> mDicNodes; + std::deque<DicNode*> mPooledDicNodes; +}; +} // namespace latinime +#endif // LATINIME_DIC_NODE_POOL_H diff --git a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h index 213b1b968..7b753f2e4 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h +++ b/native/jni/src/suggest/core/dicnode/dic_node_priority_queue.h @@ -23,38 +23,30 @@ #include "defines.h" #include "suggest/core/dicnode/dic_node.h" -#include "suggest/core/dicnode/dic_node_release_listener.h" +#include "suggest/core/dicnode/dic_node_pool.h" namespace latinime { -class DicNodePriorityQueue : public DicNodeReleaseListener { +class DicNodePriorityQueue { public: AK_FORCE_INLINE explicit DicNodePriorityQueue(const int capacity) - : mCapacity(capacity), mMaxSize(capacity), mDicNodesBuf(), - mUnusedNodeIndices(), mNextUnusedNodeId(0), mDicNodesQueue() { - mDicNodesBuf.resize(mCapacity + 1); - mUnusedNodeIndices.resize(mCapacity + 1); - clearAndResizeToCapacity(); + : mMaxSize(capacity), mDicNodesQueue(), mDicNodePool(capacity) { + clear(); } // Non virtual inline destructor -- never inherit this class AK_FORCE_INLINE ~DicNodePriorityQueue() {} - int getSize() const { + AK_FORCE_INLINE int getSize() const { return static_cast<int>(mDicNodesQueue.size()); } - int getMaxSize() const { + AK_FORCE_INLINE int getMaxSize() const { return mMaxSize; } AK_FORCE_INLINE void setMaxSize(const int maxSize) { - ASSERT(maxSize <= mCapacity); - mMaxSize = std::min(maxSize, mCapacity); - } - - AK_FORCE_INLINE void clearAndResizeToCapacity() { - clearAndResize(mCapacity); + mMaxSize = maxSize; } AK_FORCE_INLINE void clear() { @@ -62,25 +54,32 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { } AK_FORCE_INLINE void clearAndResize(const int maxSize) { - ASSERT(maxSize <= mCapacity); + mMaxSize = maxSize; while (!mDicNodesQueue.empty()) { mDicNodesQueue.pop(); } - setMaxSize(maxSize); - for (int i = 0; i < mCapacity + 1; ++i) { - mDicNodesBuf[i].finalize(); - mDicNodesBuf[i].setReleaseListener(this); - mUnusedNodeIndices[i] = (i == mCapacity) ? NOT_A_NODE_ID : (i + 1); - } - mNextUnusedNodeId = 0; + mDicNodePool.reset(mMaxSize + 1); } - // Copy - AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode) { - return copyPush(dicNode, mMaxSize); + AK_FORCE_INLINE void copyPush(const DicNode *const dicNode) { + DicNode *const pooledDicNode = newDicNode(dicNode); + if (!pooledDicNode) { + return; + } + if (getSize() < mMaxSize) { + mDicNodesQueue.push(pooledDicNode); + return; + } + if (betterThanWorstDicNode(pooledDicNode)) { + mDicNodePool.placeBackInstance(mDicNodesQueue.top()); + mDicNodesQueue.pop(); + mDicNodesQueue.push(pooledDicNode); + return; + } + mDicNodePool.placeBackInstance(pooledDicNode); } - AK_FORCE_INLINE void copyPop(DicNode *dest) { + AK_FORCE_INLINE void copyPop(DicNode *const dest) { if (mDicNodesQueue.empty()) { ASSERT(false); return; @@ -89,34 +88,16 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { if (dest) { DicNodeUtils::initByCopy(node, dest); } - node->finalize(); + mDicNodePool.placeBackInstance(node); mDicNodesQueue.pop(); } - void onReleased(const DicNode *dicNode) { - const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]); - if (mUnusedNodeIndices[index] != NOT_A_NODE_ID) { - // it's already released - return; - } - mUnusedNodeIndices[index] = mNextUnusedNodeId; - mNextUnusedNodeId = index; - ASSERT(index >= 0 && index < (mCapacity + 1)); - } - - AK_FORCE_INLINE void dump() const { - AKLOGI("\n\n\n\n\n==========================="); - for (int i = 0; i < mCapacity + 1; ++i) { - if (mDicNodesBuf[i].isUsed()) { - mDicNodesBuf[i].dump("QUEUE: "); - } - } - AKLOGI("===========================\n\n\n\n\n"); + AK_FORCE_INLINE void dump() { + mDicNodePool.dump(); } private: DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodePriorityQueue); - static const int NOT_A_NODE_ID = -1; AK_FORCE_INLINE static bool compareDicNode(const DicNode *const left, const DicNode *const right) { @@ -124,26 +105,15 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { } struct DicNodeComparator { - bool operator ()(DicNode *left, DicNode *right) { + bool operator ()(const DicNode *left, const DicNode *right) const { return compareDicNode(left, right); } }; typedef std::priority_queue<DicNode *, std::vector<DicNode *>, DicNodeComparator> DicNodesQueue; - const int mCapacity; int mMaxSize; - std::vector<DicNode> mDicNodesBuf; // of each element of mDicNodesBuf respectively - std::vector<int> mUnusedNodeIndices; - int mNextUnusedNodeId; DicNodesQueue mDicNodesQueue; - - inline bool isFull(const int maxSize) const { - return getSize() >= maxSize; - } - - AK_FORCE_INLINE void pop() { - copyPop(nullptr); - } + DicNodePool mDicNodePool; AK_FORCE_INLINE bool betterThanWorstDicNode(const DicNode *const dicNode) const { DicNode *worstNode = mDicNodesQueue.top(); @@ -153,61 +123,13 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { return compareDicNode(dicNode, worstNode); } - AK_FORCE_INLINE DicNode *searchEmptyDicNode() { - if (mCapacity == 0) { - return nullptr; - } - if (mNextUnusedNodeId == NOT_A_NODE_ID) { - AKLOGI("No unused node found."); - for (int i = 0; i < mCapacity + 1; ++i) { - AKLOGI("Dump node availability, %d, %d, %d", - i, mDicNodesBuf[i].isUsed(), mUnusedNodeIndices[i]); - } - ASSERT(false); - return nullptr; - } - DicNode *dicNode = &mDicNodesBuf[mNextUnusedNodeId]; - markNodeAsUsed(dicNode); - return dicNode; - } - - AK_FORCE_INLINE void markNodeAsUsed(DicNode *dicNode) { - const int index = static_cast<int>(dicNode - &mDicNodesBuf[0]); - mNextUnusedNodeId = mUnusedNodeIndices[index]; - mUnusedNodeIndices[index] = NOT_A_NODE_ID; - ASSERT(index >= 0 && index < (mCapacity + 1)); - } - - AK_FORCE_INLINE DicNode *pushPoolNodeWithMaxSize(DicNode *dicNode, const int maxSize) { - if (!dicNode) { - return nullptr; - } - if (!isFull(maxSize)) { - mDicNodesQueue.push(dicNode); - return dicNode; - } - if (betterThanWorstDicNode(dicNode)) { - pop(); - mDicNodesQueue.push(dicNode); - return dicNode; - } - dicNode->finalize(); - return nullptr; - } - - // Copy - AK_FORCE_INLINE DicNode *copyPush(const DicNode *const dicNode, const int maxSize) { - return pushPoolNodeWithMaxSize(newDicNode(dicNode), maxSize); - } - AK_FORCE_INLINE DicNode *newDicNode(const DicNode *const dicNode) { - DicNode *newNode = searchEmptyDicNode(); + DicNode *newNode = mDicNodePool.getInstance(); if (newNode) { DicNodeUtils::initByCopy(dicNode, newNode); } return newNode; } - }; } // namespace latinime #endif // LATINIME_DIC_NODE_PRIORITY_QUEUE_H diff --git a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h b/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h deleted file mode 100644 index c3f432951..000000000 --- a/native/jni/src/suggest/core/dicnode/dic_node_release_listener.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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_NODE_RELEASE_LISTENER_H -#define LATINIME_DIC_NODE_RELEASE_LISTENER_H - -#include "defines.h" - -namespace latinime { - -class DicNode; - -class DicNodeReleaseListener { - public: - DicNodeReleaseListener() {} - virtual ~DicNodeReleaseListener() {} - virtual void onReleased(const DicNode *dicNode) = 0; - private: - DISALLOW_COPY_AND_ASSIGN(DicNodeReleaseListener); -}; -} // namespace latinime -#endif // LATINIME_DIC_NODE_RELEASE_LISTENER_H diff --git a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h index 6b8dc8c96..089d4467f 100644 --- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h +++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h @@ -49,15 +49,14 @@ class DicNodesCache { AK_FORCE_INLINE void reset(const int nextActiveSize, const int terminalSize) { mInputIndex = 0; mLastCachedInputIndex = 0; - // We want to use the max capacity for the current active dic node queue. - mActiveDicNodes->clearAndResizeToCapacity(); - // nextActiveSize is used to limit the next iteration's active dic node size. + // The size of current active DicNode queue doesn't have to be changed. + mActiveDicNodes->clear(); + // nextActiveSize is used to limit the next iteration's active DicNode size. const int nextActiveSizeFittingToTheCapacity = std::min(nextActiveSize, getCacheCapacity()); mNextActiveDicNodes->clearAndResize(nextActiveSizeFittingToTheCapacity); mTerminalDicNodes->clearAndResize(terminalSize); - // We want to use the max capacity for the cached dic nodes that will be used for the - // continuous suggestion. - mCachedDicNodesForContinuousSuggestion->clearAndResizeToCapacity(); + // The size of cached DicNode queue doesn't have to be changed. + mCachedDicNodesForContinuousSuggestion->clear(); } AK_FORCE_INLINE void continueSearch() { @@ -95,8 +94,8 @@ class DicNodesCache { mActiveDicNodes->copyPush(dicNode); } - AK_FORCE_INLINE bool copyPushContinue(DicNode *dicNode) { - return mCachedDicNodesForContinuousSuggestion->copyPush(dicNode); + AK_FORCE_INLINE void copyPushContinue(DicNode *dicNode) { + mCachedDicNodesForContinuousSuggestion->copyPush(dicNode); } AK_FORCE_INLINE void copyPushNextActive(DicNode *dicNode) { diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp index 7b332064c..c4c57169b 100644 --- a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp +++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp @@ -37,8 +37,8 @@ const float ScoringParams::DISTANCE_WEIGHT_LENGTH = 0.1524f; const float ScoringParams::PROXIMITY_COST = 0.0694f; const float ScoringParams::FIRST_CHAR_PROXIMITY_COST = 0.072f; const float ScoringParams::FIRST_PROXIMITY_COST = 0.07788f; -const float ScoringParams::OMISSION_COST = 0.4676f; -const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.399f; +const float ScoringParams::OMISSION_COST = 0.467f; +const float ScoringParams::OMISSION_COST_SAME_CHAR = 0.345f; const float ScoringParams::OMISSION_COST_FIRST_CHAR = 0.5256f; const float ScoringParams::INSERTION_COST = 0.7248f; const float ScoringParams::TERMINAL_INSERTION_COST = 0.8128f; @@ -46,18 +46,18 @@ const float ScoringParams::INSERTION_COST_SAME_CHAR = 0.5508f; const float ScoringParams::INSERTION_COST_PROXIMITY_CHAR = 0.674f; const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.639f; const float ScoringParams::TRANSPOSITION_COST = 0.5608f; -const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.339f; +const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.334f; const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.4576f; const float ScoringParams::SUBSTITUTION_COST = 0.3806f; -const float ScoringParams::COST_NEW_WORD = 0.0312f; +const float ScoringParams::COST_NEW_WORD = 0.0314f; const float ScoringParams::COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE = 0.3224f; const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.1214f; const float ScoringParams::COST_FIRST_LOOKAHEAD = 0.4836f; const float ScoringParams::COST_LOOKAHEAD = 0.00624f; -const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.06836f; +const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.0683f; const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.0362f; const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.4182f; const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f; const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f; -const float ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT = 0.045f; +const float ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT = 0.095f; } // namespace latinime diff --git a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java new file mode 100644 index 000000000..ff1103e4f --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2011 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.utils; + +import android.content.Context; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.RichInputMethodManager; + +import java.util.ArrayList; +import java.util.Locale; + +@SmallTest +public class SpacebarLanguagetUtilsTests extends AndroidTestCase { + // All input method subtypes of LatinIME. + private final ArrayList<InputMethodSubtype> mSubtypesList = CollectionUtils.newArrayList(); + + private RichInputMethodManager mRichImm; + private Resources mRes; + + InputMethodSubtype EN_US; + InputMethodSubtype EN_GB; + InputMethodSubtype ES_US; + InputMethodSubtype FR; + InputMethodSubtype FR_CA; + InputMethodSubtype FR_CH; + InputMethodSubtype DE; + InputMethodSubtype DE_CH; + InputMethodSubtype ZZ; + InputMethodSubtype DE_QWERTY; + InputMethodSubtype FR_QWERTZ; + InputMethodSubtype EN_US_AZERTY; + InputMethodSubtype EN_UK_DVORAK; + InputMethodSubtype ES_US_COLEMAK; + InputMethodSubtype ZZ_AZERTY; + InputMethodSubtype ZZ_PC; + + @Override + protected void setUp() throws Exception { + super.setUp(); + final Context context = getContext(); + RichInputMethodManager.init(context); + mRichImm = RichInputMethodManager.getInstance(); + mRes = context.getResources(); + SubtypeLocaleUtils.init(context); + + final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme(); + final int subtypeCount = imi.getSubtypeCount(); + for (int index = 0; index < subtypeCount; index++) { + final InputMethodSubtype subtype = imi.getSubtypeAt(index); + mSubtypesList.add(subtype); + } + + EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.US.toString(), "qwerty"); + EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.UK.toString(), "qwerty"); + ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "es_US", "spanish"); + FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.FRENCH.toString(), "azerty"); + FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.CANADA_FRENCH.toString(), "qwerty"); + FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "fr_CH", "swiss"); + DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.GERMAN.toString(), "qwertz"); + DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "de_CH", "swiss"); + ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); + DE_QWERTY = AdditionalSubtypeUtils.createAdditionalSubtype( + Locale.GERMAN.toString(), "qwerty", null); + FR_QWERTZ = AdditionalSubtypeUtils.createAdditionalSubtype( + Locale.FRENCH.toString(), "qwertz", null); + EN_US_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype( + Locale.US.toString(), "azerty", null); + EN_UK_DVORAK = AdditionalSubtypeUtils.createAdditionalSubtype( + Locale.UK.toString(), "dvorak", null); + ES_US_COLEMAK = AdditionalSubtypeUtils.createAdditionalSubtype( + "es_US", "colemak", null); + ZZ_AZERTY = AdditionalSubtypeUtils.createAdditionalSubtype( + SubtypeLocaleUtils.NO_LANGUAGE, "azerty", null); + ZZ_PC = AdditionalSubtypeUtils.createAdditionalSubtype( + SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty", null); + } + + public void testAllFullDisplayNameForSpacebar() { + for (final InputMethodSubtype subtype : mSubtypesList) { + final String subtypeName = SubtypeLocaleUtils + .getSubtypeDisplayNameInSystemLocale(subtype); + final String spacebarText = SpacebarLanguageUtils.getFullDisplayName(subtype); + final String languageName = SubtypeLocaleUtils + .getSubtypeLocaleDisplayName(subtype.getLocale()); + if (SubtypeLocaleUtils.isNoLanguage(subtype)) { + assertFalse(subtypeName, spacebarText.contains(languageName)); + } else { + assertTrue(subtypeName, spacebarText.contains(languageName)); + } + } + } + + public void testAllMiddleDisplayNameForSpacebar() { + for (final InputMethodSubtype subtype : mSubtypesList) { + final String subtypeName = SubtypeLocaleUtils + .getSubtypeDisplayNameInSystemLocale(subtype); + final String spacebarText = SpacebarLanguageUtils.getMiddleDisplayName(subtype); + if (SubtypeLocaleUtils.isNoLanguage(subtype)) { + assertEquals(subtypeName, + SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText); + } else { + final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + assertEquals(subtypeName, + SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()), + spacebarText); + } + } + } + + // InputMethodSubtype's display name for spacebar text in its locale. + // isAdditionalSubtype (T=true, F=false) + // locale layout | Middle Full + // ------ ------- - --------- ---------------------- + // en_US qwerty F English English (US) exception + // en_GB qwerty F English English (UK) exception + // es_US spanish F Español Español (EE.UU.) exception + // fr azerty F Français Français + // fr_CA qwerty F Français Français (Canada) + // fr_CH swiss F Français Français (Suisse) + // de qwertz F Deutsch Deutsch + // de_CH swiss F Deutsch Deutsch (Schweiz) + // zz qwerty F QWERTY QWERTY + // fr qwertz T Français Français + // de qwerty T Deutsch Deutsch + // en_US azerty T English English (US) + // zz azerty T AZERTY AZERTY + + private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("en_US", "English (US)", + SpacebarLanguageUtils.getFullDisplayName(EN_US)); + assertEquals("en_GB", "English (UK)", + SpacebarLanguageUtils.getFullDisplayName(EN_GB)); + assertEquals("es_US", "Español (EE.UU.)", + SpacebarLanguageUtils.getFullDisplayName(ES_US)); + assertEquals("fr", "Français", + SpacebarLanguageUtils.getFullDisplayName(FR)); + assertEquals("fr_CA", "Français (Canada)", + SpacebarLanguageUtils.getFullDisplayName(FR_CA)); + assertEquals("fr_CH", "Français (Suisse)", + SpacebarLanguageUtils.getFullDisplayName(FR_CH)); + assertEquals("de", "Deutsch", + SpacebarLanguageUtils.getFullDisplayName(DE)); + assertEquals("de_CH", "Deutsch (Schweiz)", + SpacebarLanguageUtils.getFullDisplayName(DE_CH)); + assertEquals("zz", "QWERTY", + SpacebarLanguageUtils.getFullDisplayName(ZZ)); + + assertEquals("en_US", "English", + SpacebarLanguageUtils.getMiddleDisplayName(EN_US)); + assertEquals("en_GB", "English", + SpacebarLanguageUtils.getMiddleDisplayName(EN_GB)); + assertEquals("es_US", "Español", + SpacebarLanguageUtils.getMiddleDisplayName(ES_US)); + assertEquals("fr", "Français", + SpacebarLanguageUtils.getMiddleDisplayName(FR)); + assertEquals("fr_CA", "Français", + SpacebarLanguageUtils.getMiddleDisplayName(FR_CA)); + assertEquals("fr_CH", "Français", + SpacebarLanguageUtils.getMiddleDisplayName(FR_CH)); + assertEquals("de", "Deutsch", + SpacebarLanguageUtils.getMiddleDisplayName(DE)); + assertEquals("de_CH", "Deutsch", + SpacebarLanguageUtils.getMiddleDisplayName(DE_CH)); + assertEquals("zz", "QWERTY", + SpacebarLanguageUtils.getMiddleDisplayName(ZZ)); + return null; + } + }; + + private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("fr qwertz", "Français", + SpacebarLanguageUtils.getFullDisplayName(FR_QWERTZ)); + assertEquals("de qwerty", "Deutsch", + SpacebarLanguageUtils.getFullDisplayName(DE_QWERTY)); + assertEquals("en_US azerty", "English (US)", + SpacebarLanguageUtils.getFullDisplayName(EN_US_AZERTY)); + assertEquals("en_UK dvorak", "English (UK)", + SpacebarLanguageUtils.getFullDisplayName(EN_UK_DVORAK)); + assertEquals("es_US colemak", "Español (EE.UU.)", + SpacebarLanguageUtils.getFullDisplayName(ES_US_COLEMAK)); + assertEquals("zz azerty", "AZERTY", + SpacebarLanguageUtils.getFullDisplayName(ZZ_AZERTY)); + assertEquals("zz pc", "PC", + SpacebarLanguageUtils.getFullDisplayName(ZZ_PC)); + + assertEquals("fr qwertz", "Français", + SpacebarLanguageUtils.getMiddleDisplayName(FR_QWERTZ)); + assertEquals("de qwerty", "Deutsch", + SpacebarLanguageUtils.getMiddleDisplayName(DE_QWERTY)); + assertEquals("en_US azerty", "English", + SpacebarLanguageUtils.getMiddleDisplayName(EN_US_AZERTY)); + assertEquals("en_UK dvorak", "English", + SpacebarLanguageUtils.getMiddleDisplayName(EN_UK_DVORAK)); + assertEquals("es_US colemak", "Español", + SpacebarLanguageUtils.getMiddleDisplayName(ES_US_COLEMAK)); + assertEquals("zz azerty", "AZERTY", + SpacebarLanguageUtils.getMiddleDisplayName(ZZ_AZERTY)); + assertEquals("zz pc", "PC", + SpacebarLanguageUtils.getMiddleDisplayName(ZZ_PC)); + return null; + } + }; + + public void testPredefinedSubtypesForSpacebarInEnglish() { + testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH); + } + + public void testAdditionalSubtypeForSpacebarInEnglish() { + testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH); + } + + public void testPredefinedSubtypesForSpacebarInFrench() { + testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH); + } + + public void testAdditionalSubtypeForSpacebarInFrench() { + testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH); + } +} diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java index eb8a61a16..ee345905c 100644 --- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java @@ -123,12 +123,23 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { assertEquals("en_US", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US)); assertEquals("en_GB", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_GB)); assertEquals("es_US", "spanish", SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US)); - assertEquals("fr ", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR)); + assertEquals("fr", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR)); assertEquals("fr_CA", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CA)); assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH)); - assertEquals("de ", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE)); + assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE)); assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH)); - assertEquals("zz ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ)); + assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ)); + + assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY)); + assertEquals("fr qwertz", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_QWERTZ)); + assertEquals("en_US azerty", "azerty", + SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US_AZERTY)); + assertEquals("en_UK dvorak", "dvorak", + SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_UK_DVORAK)); + assertEquals("es_US colemak", "colemak", + SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US_COLEMAK)); + assertEquals("zz azerty", "azerty", + SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ_AZERTY)); } // InputMethodSubtype's display name in system locale (en_US). @@ -161,17 +172,17 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB)); assertEquals("es_US", "Spanish (US)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US)); - assertEquals("fr ", "French", + assertEquals("fr", "French", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR)); assertEquals("fr_CA", "French (Canada)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA)); assertEquals("fr_CH", "French (Switzerland)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH)); - assertEquals("de ", "German", + assertEquals("de", "German", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); assertEquals("de_CH", "German (Switzerland)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); - assertEquals("zz ", "Alphabet (QWERTY)", + assertEquals("zz", "Alphabet (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); return null; } @@ -183,17 +194,19 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { final RunInLocale<Void> tests = new RunInLocale<Void>() { @Override protected Void job(final Resources res) { - assertEquals("fr qwertz", "French (QWERTZ)", + assertEquals("fr qwertz", "French (QWERTZ)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ)); - assertEquals("de qwerty", "German (QWERTY)", + assertEquals("de qwerty", "German (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY)); assertEquals("en_US azerty", "English (US) (AZERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY)); - assertEquals("en_UK dvorak", "English (UK) (Dvorak)", + assertEquals("en_UK dvorak","English (UK) (Dvorak)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK)); - assertEquals("es_US colemak","Spanish (US) (Colemak)", + assertEquals("es_US colemak", "Spanish (US) (Colemak)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK)); - assertEquals("zz pc", "Alphabet (PC)", + assertEquals("zz azerty", "Alphabet (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY)); + assertEquals("zz pc", "Alphabet (PC)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC)); return null; } @@ -231,17 +244,17 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB)); assertEquals("es_US", "Espagnol (États-Unis)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US)); - assertEquals("fr ", "Français", + assertEquals("fr", "Français", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR)); assertEquals("fr_CA", "Français (Canada)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA)); assertEquals("fr_CH", "Français (Suisse)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH)); - assertEquals("de ", "Allemand", + assertEquals("de", "Allemand", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); assertEquals("de_CH", "Allemand (Suisse)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); - assertEquals("zz ", "Alphabet latin (QWERTY)", + assertEquals("zz", "Alphabet latin (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); return null; } @@ -253,17 +266,19 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { final RunInLocale<Void> tests = new RunInLocale<Void>() { @Override protected Void job(final Resources res) { - assertEquals("fr qwertz", "Français (QWERTZ)", + assertEquals("fr qwertz", "Français (QWERTZ)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ)); - assertEquals("de qwerty", "Allemand (QWERTY)", + assertEquals("de qwerty", "Allemand (QWERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY)); assertEquals("en_US azerty", "Anglais (États-Unis) (AZERTY)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY)); assertEquals("en_UK dvorak", "Anglais (Royaume-Uni) (Dvorak)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK)); - assertEquals("es_US colemak","Espagnol (États-Unis) (Colemak)", + assertEquals("es_US colemak", "Espagnol (États-Unis) (Colemak)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK)); - assertEquals("zz pc", "Alphabet latin (PC)", + assertEquals("zz azerty", "Alphabet latin (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY)); + assertEquals("zz pc", "Alphabet latin (PC)", SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC)); return null; } @@ -271,126 +286,6 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase { tests.runInLocale(mRes, Locale.FRENCH); } - public void testAllFullDisplayNameForSpacebar() { - for (final InputMethodSubtype subtype : mSubtypesList) { - final String subtypeName = SubtypeLocaleUtils - .getSubtypeDisplayNameInSystemLocale(subtype); - final String spacebarText = SubtypeLocaleUtils.getFullDisplayName(subtype); - final String languageName = SubtypeLocaleUtils - .getSubtypeLocaleDisplayName(subtype.getLocale()); - if (SubtypeLocaleUtils.isNoLanguage(subtype)) { - assertFalse(subtypeName, spacebarText.contains(languageName)); - } else { - assertTrue(subtypeName, spacebarText.contains(languageName)); - } - } - } - - public void testAllMiddleDisplayNameForSpacebar() { - for (final InputMethodSubtype subtype : mSubtypesList) { - final String subtypeName = SubtypeLocaleUtils - .getSubtypeDisplayNameInSystemLocale(subtype); - final String spacebarText = SubtypeLocaleUtils.getMiddleDisplayName(subtype); - if (SubtypeLocaleUtils.isNoLanguage(subtype)) { - assertEquals(subtypeName, - SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText); - } else { - final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); - assertEquals(subtypeName, - SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()), - spacebarText); - } - } - } - - // InputMethodSubtype's display name for spacebar text in its locale. - // isAdditionalSubtype (T=true, F=false) - // locale layout | Middle Full - // ------ ------- - --------- ---------------------- - // en_US qwerty F English English (US) exception - // en_GB qwerty F English English (UK) exception - // es_US spanish F Español Español (EE.UU.) exception - // fr azerty F Français Français - // fr_CA qwerty F Français Français (Canada) - // fr_CH swiss F Français Français (Suisse) - // de qwertz F Deutsch Deutsch - // de_CH swiss F Deutsch Deutsch (Schweiz) - // zz qwerty F QWERTY QWERTY - // fr qwertz T Français Français - // de qwerty T Deutsch Deutsch - // en_US azerty T English English (US) - // zz azerty T AZERTY AZERTY - - private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() { - @Override - protected Void job(final Resources res) { - assertEquals("en_US", "English (US)", SubtypeLocaleUtils.getFullDisplayName(EN_US)); - assertEquals("en_GB", "English (UK)", SubtypeLocaleUtils.getFullDisplayName(EN_GB)); - assertEquals("es_US", "Español (EE.UU.)", - SubtypeLocaleUtils.getFullDisplayName(ES_US)); - assertEquals("fr ", "Français", SubtypeLocaleUtils.getFullDisplayName(FR)); - assertEquals("fr_CA", "Français (Canada)", - SubtypeLocaleUtils.getFullDisplayName(FR_CA)); - assertEquals("fr_CH", "Français (Suisse)", - SubtypeLocaleUtils.getFullDisplayName(FR_CH)); - assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getFullDisplayName(DE)); - assertEquals("de_CH", "Deutsch (Schweiz)", - SubtypeLocaleUtils.getFullDisplayName(DE_CH)); - assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getFullDisplayName(ZZ)); - - assertEquals("en_US", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_US)); - assertEquals("en_GB", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_GB)); - assertEquals("es_US", "Español", SubtypeLocaleUtils.getMiddleDisplayName(ES_US)); - assertEquals("fr ", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR)); - assertEquals("fr_CA", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CA)); - assertEquals("fr_CH", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CH)); - assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE)); - assertEquals("de_CH", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE_CH)); - assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ)); - return null; - } - }; - - private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() { - @Override - protected Void job(final Resources res) { - assertEquals("fr qwertz", "Français", - SubtypeLocaleUtils.getFullDisplayName(FR_QWERTZ)); - assertEquals("de qwerty", "Deutsch", - SubtypeLocaleUtils.getFullDisplayName(DE_QWERTY)); - assertEquals("en_US azerty", "English (US)", - SubtypeLocaleUtils.getFullDisplayName(EN_US_AZERTY)); - assertEquals("zz azerty", "AZERTY", - SubtypeLocaleUtils.getFullDisplayName(ZZ_AZERTY)); - - assertEquals("fr qwertz", "Français", - SubtypeLocaleUtils.getMiddleDisplayName(FR_QWERTZ)); - assertEquals("de qwerty", "Deutsch", - SubtypeLocaleUtils.getMiddleDisplayName(DE_QWERTY)); - assertEquals("en_US azerty", "English", - SubtypeLocaleUtils.getMiddleDisplayName(EN_US_AZERTY)); - assertEquals("zz azerty", "AZERTY", - SubtypeLocaleUtils.getMiddleDisplayName(ZZ_AZERTY)); - return null; - } - }; - - public void testPredefinedSubtypesForSpacebarInEnglish() { - testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH); - } - - public void testAdditionalSubtypeForSpacebarInEnglish() { - testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH); - } - - public void testPredefinedSubtypesForSpacebarInFrench() { - testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH); - } - - public void testAdditionalSubtypeForSpacebarInFrench() { - testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH); - } - public void testIsRtlLanguage() { // Known Right-to-Left language subtypes. final InputMethodSubtype ARABIC = mRichImm |