diff options
34 files changed, 1187 insertions, 122 deletions
diff --git a/java/res/xml-sw600dp/key_azerty3_right.xml b/java/res/xml-sw600dp/key_azerty3_right.xml deleted file mode 100644 index 25b0e52b8..000000000 --- a/java/res/xml-sw600dp/key_azerty3_right.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Key - latin:keySpec=":" - latin:keyHintLabel=";" - latin:moreKeys=";" - latin:keyStyle="hasShiftedLetterHintStyle" /> -</merge> diff --git a/java/res/xml/key_azerty3_right.xml b/java/res/xml/key_azerty3_right.xml deleted file mode 100644 index 85a066613..000000000 --- a/java/res/xml/key_azerty3_right.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 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. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <switch> - <case - latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted" - > - <Key - latin:keySpec="\?" /> - </case> - <default> - <Key - latin:keySpec="\'" - latin:moreKeys="!text/more_keys_for_single_quote" /> - </default> - </switch> -</merge> diff --git a/java/res/xml/rowkeys_azerty3.xml b/java/res/xml/rowkeys_azerty3.xml index 0aa215305..c955e237c 100644 --- a/java/res/xml/rowkeys_azerty3.xml +++ b/java/res/xml/rowkeys_azerty3.xml @@ -37,6 +37,17 @@ <Key latin:keySpec="n" latin:moreKeys="!text/more_keys_for_n" /> - <include - latin:keyboardLayout="@xml/key_azerty3_right" /> + <switch> + <case + latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <Key + latin:keySpec="\?" /> + </case> + <default> + <Key + latin:keySpec="\'" + latin:moreKeys="!text/more_keys_for_single_quote" /> + </default> + </switch> </merge> diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index e7932b5a6..b9d526b5f 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -507,4 +507,44 @@ public final class StringUtils { return codePointCount(casedText) == 1 ? casedText.codePointAt(0) : CODE_UNSPECIFIED; } + + @UsedForTesting + public static class Stringizer<E> { + public String stringize(final E element) { + return element != null ? element.toString() : "null"; + } + + @UsedForTesting + public final String join(final E[] array) { + return joinStringArray(toStringArray(array), null /* delimiter */); + } + + @UsedForTesting + public final String join(final E[] array, final String delimiter) { + return joinStringArray(toStringArray(array), delimiter); + } + + protected String[] toStringArray(final E[] array) { + final String[] stringArray = new String[array.length]; + for (int index = 0; index < array.length; index++) { + stringArray[index] = stringize(array[index]); + } + return stringArray; + } + + protected String joinStringArray(final String[] stringArray, final String delimiter) { + if (stringArray == null) { + return "null"; + } + if (delimiter == null) { + return Arrays.toString(stringArray); + } + final StringBuilder sb = new StringBuilder(); + for (int index = 0; index < stringArray.length; index++) { + sb.append(index == 0 ? "[" : delimiter); + sb.append(stringArray[index]); + } + return sb + "]"; + } + } } diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 0715fbd70..4c57af0ba 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -344,9 +344,6 @@ static inline void prof_out(void) { #define MAX_POINTER_COUNT 1 #define MAX_POINTER_COUNT_G 2 -template<typename T> AK_FORCE_INLINE const T &min(const T &a, const T &b) { return a < b ? a : b; } -template<typename T> AK_FORCE_INLINE const T &max(const T &a, const T &b) { return a > b ? a : b; } - // DEBUG #define INPUTLENGTH_FOR_DEBUG (-1) #define MIN_OUTPUT_INDEX_FOR_DEBUG (-1) 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 7461f0cc6..1f02731a5 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 @@ -17,6 +17,7 @@ #ifndef LATINIME_DIC_NODE_PRIORITY_QUEUE_H #define LATINIME_DIC_NODE_PRIORITY_QUEUE_H +#include <algorithm> #include <queue> #include <vector> @@ -49,7 +50,7 @@ class DicNodePriorityQueue : public DicNodeReleaseListener { AK_FORCE_INLINE void setMaxSize(const int maxSize) { ASSERT(maxSize <= mCapacity); - mMaxSize = min(maxSize, mCapacity); + mMaxSize = std::min(maxSize, mCapacity); } AK_FORCE_INLINE void clearAndResizeToCapacity() { diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp index 71bcab6cb..a6ea68c29 100644 --- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp +++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp @@ -16,6 +16,7 @@ #include "suggest/core/dicnode/dic_node_utils.h" +#include <algorithm> #include <cstring> #include "suggest/core/dicnode/dic_node.h" @@ -117,7 +118,7 @@ namespace latinime { } actualLength0 = i + 1; } - actualLength0 = min(actualLength0, MAX_WORD_LENGTH); + actualLength0 = std::min(actualLength0, MAX_WORD_LENGTH); memmove(dest, src0, actualLength0 * sizeof(dest[0])); if (!src1 || length1 == 0) { return actualLength0; @@ -129,7 +130,7 @@ namespace latinime { } actualLength1 = i + 1; } - actualLength1 = min(actualLength1, MAX_WORD_LENGTH - actualLength0); + actualLength1 = std::min(actualLength1, MAX_WORD_LENGTH - actualLength0); memmove(&dest[actualLength0], src1, actualLength1 * sizeof(dest[0])); return actualLength0 + actualLength1; } 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 8493b6a8b..c31c056f5 100644 --- a/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h +++ b/native/jni/src/suggest/core/dicnode/dic_nodes_cache.h @@ -17,6 +17,7 @@ #ifndef LATINIME_DIC_NODES_CACHE_H #define LATINIME_DIC_NODES_CACHE_H +#include <algorithm> #include <stdint.h> #include "defines.h" @@ -51,7 +52,7 @@ class DicNodesCache { // 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. - const int nextActiveSizeFittingToTheCapacity = min(nextActiveSize, getCacheCapacity()); + 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 diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h index fc6851099..abafc0edf 100644 --- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h +++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_output.h @@ -17,6 +17,7 @@ #ifndef LATINIME_DIC_NODE_STATE_OUTPUT_H #define LATINIME_DIC_NODE_STATE_OUTPUT_H +#include <algorithm> #include <cstring> // for memmove() #include <stdint.h> @@ -49,7 +50,8 @@ class DicNodeStateOutput { void addMergedNodeCodePoints(const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) { if (mergedNodeCodePoints) { - const int additionalCodePointCount = min(static_cast<int>(mergedNodeCodePointCount), + const int additionalCodePointCount = std::min( + static_cast<int>(mergedNodeCodePointCount), MAX_WORD_LENGTH - mOutputtedCodePointCount); memmove(&mCodePointsBuf[mOutputtedCodePointCount], mergedNodeCodePoints, additionalCodePointCount * sizeof(mCodePointsBuf[0])); diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h index e7108d976..7868f7853 100644 --- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h +++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h @@ -17,6 +17,7 @@ #ifndef LATINIME_DIC_NODE_STATE_PREVWORD_H #define LATINIME_DIC_NODE_STATE_PREVWORD_H +#include <algorithm> #include <cstring> // for memset() and memmove() #include <stdint.h> @@ -69,7 +70,7 @@ class DicNodeStatePrevWord { const int prevWordNodePos, const int *const src0, const int16_t length0, const int *const src1, const int16_t length1, const int prevWordSecondWordFirstInputIndex, const int lastInputIndex) { - mPrevWordCount = min(prevWordCount, static_cast<int16_t>(MAX_RESULTS)); + mPrevWordCount = std::min(prevWordCount, static_cast<int16_t>(MAX_RESULTS)); mPrevWordProbability = prevWordProbability; mPrevWordPtNodePos = prevWordNodePos; int twoWordsLen = diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h index 11c201e52..18b7d736a 100644 --- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h +++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h @@ -17,6 +17,7 @@ #ifndef LATINIME_DIC_NODE_STATE_SCORING_H #define LATINIME_DIC_NODE_STATE_SCORING_H +#include <algorithm> #include <stdint.h> #include "defines.h" @@ -199,7 +200,7 @@ class DicNodeStateScoring { mNormalizedCompoundDistance = mSpatialDistance + mLanguageDistance; } else { mNormalizedCompoundDistance = (mSpatialDistance + mLanguageDistance) - / static_cast<float>(max(1, totalInputIndex)); + / static_cast<float>(std::max(1, totalInputIndex)); } } }; diff --git a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp index d0b96b0fe..0859df423 100644 --- a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp +++ b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp @@ -14,12 +14,13 @@ * limitations under the License. */ -#include <cstring> - #define LOG_TAG "LatinIME: bigram_dictionary.cpp" #include "bigram_dictionary.h" +#include <algorithm> +#include <cstring> + #include "defines.h" #include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h" #include "suggest/core/dictionary/dictionary.h" @@ -142,7 +143,7 @@ int BigramDictionary::getPredictions(const int *prevWord, const int prevWordLeng outBigramCodePoints, outputTypes); ++bigramCount; } - return min(bigramCount, MAX_RESULTS); + return std::min(bigramCount, MAX_RESULTS); } // Returns a pointer to the start of the bigram list. diff --git a/native/jni/src/suggest/core/layout/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp index ee8e59ef9..8b3ae4db8 100644 --- a/native/jni/src/suggest/core/layout/proximity_info.cpp +++ b/native/jni/src/suggest/core/layout/proximity_info.cpp @@ -18,6 +18,7 @@ #include "suggest/core/layout/proximity_info.h" +#include <algorithm> #include <cstring> #include <cmath> @@ -63,7 +64,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, static_cast<float>(mostCommonKeyWidth))), CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth), CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight), - KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), + KEY_COUNT(std::min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight), KEYBOARD_HYPOTENUSE(hypotf(KEYBOARD_WIDTH, KEYBOARD_HEIGHT)), HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp index 40c3448ef..2919904e5 100644 --- a/native/jni/src/suggest/core/layout/proximity_info_state.cpp +++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp @@ -18,6 +18,7 @@ #include "suggest/core/layout/proximity_info_state.h" +#include <algorithm> #include <cstring> // for memset() and memmove() #include <sstream> // for debug prints #include <vector> @@ -171,7 +172,7 @@ float ProximityInfoState::getPointToKeyLength( const int keyId = mProximityInfo->getKeyIndexOf(codePoint); if (keyId != NOT_AN_INDEX) { const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; - return min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength); + return std::min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength); } if (CharUtils::isIntentionalOmissionCodePoint(codePoint)) { return 0.0f; diff --git a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp index f84615487..867f59843 100644 --- a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp +++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp @@ -241,7 +241,7 @@ namespace latinime { // Calculate velocity by using distances and durations of // ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and // backward. - const int forwardNumPoints = min(inputSize - 1, + const int forwardNumPoints = std::min(inputSize - 1, index + ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION); for (int j = index; j < forwardNumPoints; ++j) { if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) { @@ -251,7 +251,7 @@ namespace latinime { xCoordinates[j + 1], yCoordinates[j + 1]); duration += times[j + 1] - times[j]; } - const int backwardNumPoints = max(0, + const int backwardNumPoints = std::max(0, index - ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION); for (int j = index - 1; j >= backwardNumPoints; --j) { if (i > 0 && j < (*sampledInputIndice)[i - 1]) { @@ -273,7 +273,7 @@ namespace latinime { // Direction calculation. sampledDirections->resize(sampledInputSize - 1); - for (int i = max(0, lastSavedInputSize - 1); i < sampledInputSize - 1; ++i) { + for (int i = std::max(0, lastSavedInputSize - 1); i < sampledInputSize - 1; ++i) { (*sampledDirections)[i] = getDirection(sampledInputXs, sampledInputYs, i, i + 1); } return averageSpeed; @@ -610,7 +610,7 @@ namespace latinime { const int inputIndex, const int keyId) { if (keyId != NOT_AN_INDEX) { const int index = inputIndex * keyCount + keyId; - return min((*sampledNormalizedSquaredLengthCache)[index], maxPointToKeyLength); + return std::min((*sampledNormalizedSquaredLengthCache)[index], maxPointToKeyLength); } // If the char is not a key on the keyboard then return the max length. return static_cast<float>(MAX_VALUE_FOR_WEIGHTING); @@ -651,13 +651,13 @@ namespace latinime { } if (i == 0) { - skipProbability *= min(1.0f, + skipProbability *= std::min(1.0f, nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT + ProximityInfoParams::NEAREST_DISTANCE_BIAS); // Promote the first point skipProbability *= ProximityInfoParams::SKIP_FIRST_POINT_PROBABILITY; } else if (i == sampledInputSize - 1) { - skipProbability *= min(1.0f, + skipProbability *= std::min(1.0f, nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT_FOR_LAST + ProximityInfoParams::NEAREST_DISTANCE_BIAS_FOR_LAST); // Promote the last point @@ -668,17 +668,17 @@ namespace latinime { && speedRate < (*sampledSpeedRates)[i + 1] - ProximityInfoParams::SPEED_MARGIN) { if (currentAngle < ProximityInfoParams::CORNER_ANGLE_THRESHOLD) { - skipProbability *= min(1.0f, speedRate + skipProbability *= std::min(1.0f, speedRate * ProximityInfoParams::SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY); } else { // If the angle is small enough, we promote this point more. (e.g. pit vs put) - skipProbability *= min(1.0f, + skipProbability *= std::min(1.0f, speedRate * ProximityInfoParams::SPEED_WEIGHT_FOR_SKIP_PROBABILITY + ProximityInfoParams::MIN_SPEED_RATE_FOR_SKIP_PROBABILITY); } } - skipProbability *= min(1.0f, + skipProbability *= std::min(1.0f, speedRate * nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT + ProximityInfoParams::NEAREST_DISTANCE_BIAS); @@ -708,10 +708,10 @@ namespace latinime { // (1.0f - skipProbability). const float inputCharProbability = 1.0f - skipProbability; - const float speedxAngleRate = min(speedRate * currentAngle / M_PI_F + const float speedxAngleRate = std::min(speedRate * currentAngle / M_PI_F * ProximityInfoParams::SPEEDxANGLE_WEIGHT_FOR_STANDARD_DEVIATION, ProximityInfoParams::MAX_SPEEDxANGLE_RATE_FOR_STANDARD_DEVIATION); - const float speedxNearestKeyDistanceRate = min(speedRate * nearestKeyDistance + const float speedxNearestKeyDistanceRate = std::min(speedRate * nearestKeyDistance * ProximityInfoParams::SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DEVIATION, ProximityInfoParams::MAX_SPEEDxNEAREST_RATE_FOR_STANDARD_DEVIATION); const float sigma = speedxAngleRate + speedxNearestKeyDistanceRate @@ -828,7 +828,7 @@ namespace latinime { // Decrease key probabilities of points which don't have the highest probability of that key // among nearby points. Probabilities of the first point and the last point are not suppressed. - for (int i = max(start, 1); i < sampledInputSize; ++i) { + for (int i = std::max(start, 1); i < sampledInputSize; ++i) { for (int j = i + 1; j < sampledInputSize; ++j) { if (!suppressCharProbabilities( mostCommonKeyWidth, sampledInputSize, sampledLengthCache, i, j, @@ -836,7 +836,7 @@ namespace latinime { break; } } - for (int j = i - 1; j >= max(start, 0); --j) { + for (int j = i - 1; j >= std::max(start, 0); --j) { if (!suppressCharProbabilities( mostCommonKeyWidth, sampledInputSize, sampledLengthCache, i, j, charProbabilities)) { @@ -879,7 +879,7 @@ namespace latinime { if (i >= lastSavedInputSize) { (*sampledSearchKeySets)[i].reset(); } - for (int j = max(i, lastSavedInputSize); j < sampledInputSize; ++j) { + for (int j = std::max(i, lastSavedInputSize); j < sampledInputSize; ++j) { // TODO: Investigate if this is required. This may not fail. if ((*sampledLengthCache)[j] - (*sampledLengthCache)[i] >= readForwordLength) { break; @@ -930,7 +930,7 @@ namespace latinime { (*charProbabilities)[index0][NOT_AN_INDEX] += suppression; // Add the probability of the same key nearby index1 - const float probabilityGain = min(suppression + const float probabilityGain = std::min(suppression * ProximityInfoParams::SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN, (*charProbabilities)[index1][NOT_AN_INDEX] * ProximityInfoParams::SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN); diff --git a/native/jni/src/suggest/core/layout/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h index 6d2c11b09..310bbdb62 100644 --- a/native/jni/src/suggest/core/layout/proximity_info_utils.h +++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h @@ -100,6 +100,10 @@ class ProximityInfoUtils { const float dotProduct = ray1x * ray2x + ray1y * ray2y; const float lineLengthSqr = GeometryUtils::SQUARE_FLOAT(ray2x) + GeometryUtils::SQUARE_FLOAT(ray2y); + if (lineLengthSqr <= 0.0f) { + // Return point to the point distance. + return getSquaredDistanceFloat(x, y, x1, y1); + } const float projectionLengthSqr = dotProduct / lineLengthSqr; float projectionX; @@ -125,7 +129,7 @@ class ProximityInfoUtils { struct NormalDistribution { public: NormalDistribution(const float u, const float sigma) - : mU(u), mSigma(sigma), + : mU(u), mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * GeometryUtils::SQUARE_FLOAT(sigma))), mPreComputedExponentPart(-1.0f / (2.0f * GeometryUtils::SQUARE_FLOAT(sigma))) {} @@ -139,7 +143,6 @@ class ProximityInfoUtils { private: DISALLOW_IMPLICIT_CONSTRUCTORS(NormalDistribution); const float mU; // mean value - const float mSigma; // standard deviation const float mPreComputedNonExpPart; // = 1 / sqrt(2 * PI * sigma^2) const float mPreComputedExponentPart; // = -1 / (2 * sigma^2) }; // struct NormalDistribution diff --git a/native/jni/src/suggest/core/layout/touch_position_correction_utils.h b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h index 9130e87d3..14074c13d 100644 --- a/native/jni/src/suggest/core/layout/touch_position_correction_utils.h +++ b/native/jni/src/suggest/core/layout/touch_position_correction_utils.h @@ -17,6 +17,8 @@ #ifndef LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H #define LATINIME_TOUCH_POSITION_CORRECTION_UTILS_H +#include <algorithm> + #include "defines.h" #include "suggest/core/layout/proximity_info_params.h" @@ -34,7 +36,7 @@ class TouchPositionCorrectionUtils { static const float R2 = 1.0f; const float x = normalizedSquaredDistance; if (!isTouchPositionCorrectionEnabled) { - return min(C, x); + return std::min(C, x); } // factor is a piecewise linear function like: diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp index e9fb3b885..19912f2ac 100644 --- a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp +++ b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp @@ -16,6 +16,8 @@ #include "suggest/core/result/suggestions_output_utils.h" +#include <algorithm> + #include "suggest/core/dicnode/dic_node.h" #include "suggest/core/dicnode/dic_node_utils.h" #include "suggest/core/dictionary/binary_dictionary_shortcut_iterator.h" @@ -36,7 +38,7 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; #if DEBUG_EVALUATE_MOST_PROBABLE_STRING const int terminalSize = 0; #else - const int terminalSize = min(MAX_RESULTS, + const int terminalSize = std::min(MAX_RESULTS, static_cast<int>(traverseSession->getDicTraverseCache()->terminalSize())); #endif DicNode terminals[MAX_RESULTS]; // Avoiding non-POD variable length array @@ -245,12 +247,12 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; // shortcut entry's score == its base entry's score - 1 shortcutScore = finalScore; // Protection against int underflow - shortcutScore = max(S_INT_MIN + 1, shortcutScore) - 1; + shortcutScore = std::max(S_INT_MIN + 1, shortcutScore) - 1; kind = Dictionary::KIND_SHORTCUT; } outputTypes[outputWordIndex] = kind; outputScores[outputWordIndex] = shortcutScore; - outputScores[outputWordIndex] = max(S_INT_MIN + 1, shortcutScore) - 1; + outputScores[outputWordIndex] = std::max(S_INT_MIN + 1, shortcutScore) - 1; const int startIndex2 = outputWordIndex * MAX_WORD_LENGTH; DicNodeUtils::appendTwoWords(0, 0, shortcutTarget, shortcutTargetStringLength, &outputCodePoints[startIndex2]); diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp index 7c7b05ca8..ecc9fdab1 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp @@ -16,6 +16,8 @@ #include "suggest/policyimpl/dictionary/header/header_policy.h" +#include <algorithm> + namespace latinime { // Note that these are corresponding definitions in Java side in DictionaryHeader. @@ -72,7 +74,7 @@ void HeaderPolicy::readHeaderValueOrQuestionMark(const char *const key, int *out outValue[1] = '\0'; return; } - const int terminalIndex = min(static_cast<int>(it->second.size()), outValueSize - 1); + const int terminalIndex = std::min(static_cast<int>(it->second.size()), outValueSize - 1); for (int i = 0; i < terminalIndex; ++i) { outValue[i] = it->second[i]; } diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h index ae863af57..f2fa5b75b 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h @@ -31,8 +31,7 @@ class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy { public: Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent, const TerminalPositionLookupTable *const terminalPositionLookupTable) - : mShortcutDictContent(shortcutDictContent), - mTerminalPositionLookupTable(terminalPositionLookupTable) {} + : mShortcutDictContent(shortcutDictContent) {} ~Ver4ShortcutListPolicy() {} @@ -104,7 +103,6 @@ class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy { DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy); ShortcutDictContent *const mShortcutDictContent; - const TerminalPositionLookupTable *const mTerminalPositionLookupTable; }; } // namespace latinime #endif // LATINIME_VER4_SHORTCUT_LIST_POLICY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp index 35e05d77a..bac4d4eba 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp @@ -16,6 +16,7 @@ #include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h" +#include <algorithm> #include <cmath> #include <stdlib.h> @@ -72,7 +73,7 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT headerPolicy->getForgettingCurveDurationToLevelDown()); return sProbabilityTable.getProbability( headerPolicy->getForgettingCurveProbabilityValuesTableId(), historicalInfo->getLevel(), - min(max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT)); + std::min(std::max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT)); } /* static */ int ForgettingCurveUtils::getProbability(const int unigramProbability, @@ -80,11 +81,11 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT if (unigramProbability == NOT_A_PROBABILITY) { return NOT_A_PROBABILITY; } else if (bigramProbability == NOT_A_PROBABILITY) { - return min(backoff(unigramProbability), MAX_PROBABILITY); + return std::min(backoff(unigramProbability), MAX_PROBABILITY); } else { // TODO: Investigate better way to handle bigram probability. - return min(max(unigramProbability, bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE), - MAX_PROBABILITY); + return std::min(std::max(unigramProbability, + bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE), MAX_PROBABILITY); } } @@ -183,7 +184,7 @@ ForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTables() { -1.0f * static_cast<float>(timeStepCount) / static_cast<float>(MAX_ELAPSED_TIME_STEP_COUNT + 1)); mTables[tableId][level][timeStepCount] = - min(max(static_cast<int>(probability), 1), MAX_PROBABILITY); + std::min(std::max(static_cast<int>(probability), 1), MAX_PROBABILITY); } } } diff --git a/native/jni/src/suggest/policyimpl/utils/edit_distance.h b/native/jni/src/suggest/policyimpl/utils/edit_distance.h index 0871c37ce..4cfd0b3f3 100644 --- a/native/jni/src/suggest/policyimpl/utils/edit_distance.h +++ b/native/jni/src/suggest/policyimpl/utils/edit_distance.h @@ -17,6 +17,8 @@ #ifndef LATINIME_EDIT_DISTANCE_H #define LATINIME_EDIT_DISTANCE_H +#include <algorithm> + #include "defines.h" #include "suggest/policyimpl/utils/edit_distance_policy.h" @@ -38,13 +40,13 @@ class EditDistance { for (int i = 0; i < beforeLength; ++i) { for (int j = 0; j < afterLength; ++j) { - dp[(afterLength + 1) * (i + 1) + (j + 1)] = min( + dp[(afterLength + 1) * (i + 1) + (j + 1)] = std::min( dp[(afterLength + 1) * i + (j + 1)] + policy->getInsertionCost(i, j), - min(dp[(afterLength + 1) * (i + 1) + j] + policy->getDeletionCost(i, j), - dp[(afterLength + 1) * i + j] - + policy->getSubstitutionCost(i, j))); + std::min( + dp[(afterLength + 1) * (i + 1) + j] + policy->getDeletionCost(i, j), + dp[(afterLength + 1) * i + j] + policy->getSubstitutionCost(i, j))); if (policy->allowTransposition(i, j)) { - dp[(afterLength + 1) * (i + 1) + (j + 1)] = min( + dp[(afterLength + 1) * (i + 1) + (j + 1)] = std::min( dp[(afterLength + 1) * (i + 1) + (j + 1)], dp[(afterLength + 1) * (i - 1) + (j - 1)] + policy->getTranspositionCost(i, j)); diff --git a/native/jni/src/utils/autocorrection_threshold_utils.cpp b/native/jni/src/utils/autocorrection_threshold_utils.cpp index 1f8ee0814..349786a27 100644 --- a/native/jni/src/utils/autocorrection_threshold_utils.cpp +++ b/native/jni/src/utils/autocorrection_threshold_utils.cpp @@ -16,6 +16,7 @@ #include "utils/autocorrection_threshold_utils.h" +#include <algorithm> #include <cmath> #include "defines.h" @@ -99,7 +100,7 @@ const int AutocorrectionThresholdUtils::FULL_WORD_MULTIPLIER = 2; const float maxScore = score >= S_INT_MAX ? static_cast<float>(S_INT_MAX) : static_cast<float>(MAX_INITIAL_SCORE) * powf(static_cast<float>(TYPED_LETTER_MULTIPLIER), - static_cast<float>(min(beforeLength, afterLength - spaceCount))) + static_cast<float>(std::min(beforeLength, afterLength - spaceCount))) * static_cast<float>(FULL_WORD_MULTIPLIER); return (static_cast<float>(score) / maxScore) * weight; diff --git a/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java new file mode 100644 index 000000000..be3ed12de --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/AlphabetShifted.java @@ -0,0 +1,46 @@ +/* + * 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.keyboard.layout; + +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.LayoutBase; +import com.android.inputmethod.latin.Constants; + +import java.util.Locale; + +/** + * The generic upper case alphabet keyboard layout. + */ +public final class AlphabetShifted extends LayoutBase { + public static ExpectedKey[][] getAlphabet(final ExpectedKey[][] lowerCaseKeyboard, + final Locale locale) { + final ExpectedKey[][] upperCaseKeyboard = ExpectedKeyboardBuilder.toUpperCase( + lowerCaseKeyboard, locale); + return new ExpectedKeyboardBuilder(upperCaseKeyboard) + .replaceKeyOfAll(SHIFT_KEY, SHIFTED_SHIFT_KEY) + .build(); + } + + // Icon id. + private static final int ICON_SHIFTED_SHIFT = KeyboardIconsSet.getIconId("shift_key_shifted"); + + // Functional key. + private static final ExpectedKey SHIFTED_SHIFT_KEY = key( + ICON_SHIFTED_SHIFT, Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY); +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java new file mode 100644 index 000000000..f7179b739 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java @@ -0,0 +1,46 @@ +/* + * 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.keyboard.layout; + +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.LayoutBase; + +/** + * The QWERTY alphabet keyboard. + */ +public final class Qwerty extends LayoutBase { + public static ExpectedKey[][] getAlphabet(final boolean isPhone) { + return toCommonAlphabet(ALPHABET_COMMON, isPhone); + } + + private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 3) + .setLabelsOfRow(1, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p") + .setMoreKeysOf("q", "1") + .setMoreKeysOf("w", "2") + .setMoreKeysOf("e", "3") + .setMoreKeysOf("r", "4") + .setMoreKeysOf("t", "5") + .setMoreKeysOf("y", "6") + .setMoreKeysOf("u", "7") + .setMoreKeysOf("i", "8") + .setMoreKeysOf("o", "9") + .setMoreKeysOf("p", "0") + .setLabelsOfRow(2, "a", "s", "d", "f", "g", "h", "j", "k", "l") + .setLabelsOfRow(3, "z", "x", "c", "v", "b", "n", "m") + .build(); +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java new file mode 100644 index 000000000..03d7f07e9 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java @@ -0,0 +1,187 @@ +/* + * 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.keyboard.layout; + +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.LayoutBase; +import com.android.inputmethod.latin.Constants; + +/** + * The symbols keyboard layout. + */ +public final class Symbols extends LayoutBase { + public static ExpectedKey[][] getSymbols(final boolean isPhone) { + return isPhone ? toPhoneSymbol(SYMBOLS_COMMON) : toTabletSymbols(SYMBOLS_COMMON); + } + + // Functional keys. + public static final ExpectedKey ALPHABET_KEY = key("ABC", Constants.CODE_SWITCH_ALPHA_SYMBOL); + public static final ExpectedKey SYMBOLS_SHIFT_KEY = key("= \\ <", Constants.CODE_SHIFT); + public static final ExpectedKey TABLET_SYMBOLS_SHIFT_KEY = key("~ [ <", Constants.CODE_SHIFT); + + // Common symbols keyboard layout. + public static final ExpectedKey[][] SYMBOLS_COMMON = new ExpectedKeyboardBuilder(10, 9, 7, 5) + .setLabelsOfRow(1, "1", "2", "3", "4", "5", "6", "7", "8", "9", "0") + // U+00B9: "¹" SUPERSCRIPT ONE + // U+00BD: "½" VULGAR FRACTION ONE HALF + // U+2153: "⅓" VULGAR FRACTION ONE THIRD + // U+00BC: "¼" VULGAR FRACTION ONE QUARTER + // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH + .setMoreKeysOf("1", "\u00B9", "\u00BD", "\u2153", "\u00BC", "\u215B") + // U+00B2: "²" SUPERSCRIPT TWO + // U+2154: "⅔" VULGAR FRACTION TWO THIRDS + .setMoreKeysOf("2", "\u00B2", "\u2154") + // U+00B3: "³" SUPERSCRIPT THREE + // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS + // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS + .setMoreKeysOf("3", "\u00B3", "\u00BE", "\u215C") + // U+2074: "⁴" SUPERSCRIPT FOUR + .setMoreKeysOf("4", "\u2074") + // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS + .setMoreKeysOf("5", "\u215D") + // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS + .setMoreKeysOf("7", "\u215E") + // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N + // U+2205: "∅" EMPTY SET + .setMoreKeysOf("0", "\u207F", "\u2205") + .setLabelsOfRow(2, "@", "#", "$", "%", "&", "-", "+", "(", ")") + // U+00A2: "¢" CENT SIGN + // U+00A3: "£" POUND SIGN + // U+20AC: "€" EURO SIGN + // U+00A5: "¥" YEN SIGN + // U+20B1: "₱" PESO SIGN + .setMoreKeysOf("$", "\u00A2", "\u00A3", "\u20AC", "\u00A5", "\u20B1") + // U+2030: "‰" PER MILLE SIGN + .setMoreKeysOf("%", "\u2030") + // U+2013: "–" EN DASH + // U+2014: "—" EM DASH + // U+00B7: "·" MIDDLE DOT + .setMoreKeysOf("-", "_", "\u2013", "\u2014", "\u00B7") + // U+00B1: "±" PLUS-MINUS SIGN + .setMoreKeysOf("+", "\u00B1") + .setMoreKeysOf("(", "<", "{", "[") + .setMoreKeysOf(")", ">", "}", "]") + .setLabelsOfRow(3, "*", "\"", "'", ":", ";", "!", "?") + // U+2020: "†" DAGGER + // U+2021: "‡" DOUBLE DAGGER + // U+2605: "★" BLACK STAR + .setMoreKeysOf("*", "\u2020", "\u2021", "\u2605") + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + .setMoreKeysOf("\"", "\u201E", "\u201C", "\u201D", "\u00AB", "\u00BB") + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + .setMoreKeysOf("'", "\u201A", "\u2018", "\u2019", "\u2039", "\u203A") + // U+00A1: "¡" INVERTED EXCLAMATION MARK + .setMoreKeysOf("!", "\u00A1") + // U+00BF: "¿" INVERTED QUESTION MARK + .setMoreKeysOf("?", "\u00BF") + .setLabelsOfRow(4, "_", "/", " ", ",", ".") + // U+2026: "…" HORIZONTAL ELLIPSIS + .setMoreKeysOf(".", "\u2026") + .build(); + + private static ExpectedKey[][] toPhoneSymbol(final ExpectedKey[][] common) { + return new ExpectedKeyboardBuilder(common) + .addKeysOnTheLeftOfRow(3, Symbols.SYMBOLS_SHIFT_KEY) + .addKeysOnTheRightOfRow(3, DELETE_KEY) + .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY) + .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY)) + .build(); + } + + private static ExpectedKey[][] toTabletSymbols(final ExpectedKey[][] common) { + return new ExpectedKeyboardBuilder(common) + .addKeysOnTheLeftOfRow(3, + key("\\"), key("=")) + .addKeysOnTheRightOfRow(1, DELETE_KEY) + .addKeysOnTheRightOfRow(2, ENTER_KEY) + .addKeysOnTheLeftOfRow(3, Symbols.TABLET_SYMBOLS_SHIFT_KEY) + .addKeysOnTheRightOfRow(3, Symbols.TABLET_SYMBOLS_SHIFT_KEY) + .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY) + .addKeysOnTheRightOfRow(4, EMOJI_KEY) + .build(); + } + + // Helper method to add currency symbols for Euro. + public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) { + return builder + // U+20AC: "€" EURO SIGN + // U+00A2: "¢" CENT SIGN + // U+00A3: "£" POUND SIGN + // U+00A5: "¥" YEN SIGN + // U+20B1: "₱" PESO SIGN + .replaceKeyOfLabel("$", key("\u20AC", + moreKey("\u00A2"), moreKey("\u00A3"), moreKey("$"), + moreKey("\u00A5"), moreKey("\u20B1"))); + } + + // Helper method to add single quotes "more keys". + // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks". + public static ExpectedKeyboardBuilder singleQuotes9LLR(final ExpectedKeyboardBuilder builder) { + return builder + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u2039", "\u203A"); + } + + // Helper method to add single quotes "more keys". + // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks". + public static ExpectedKeyboardBuilder singleQuotes9LRL(final ExpectedKeyboardBuilder builder) { + return builder + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + .setMoreKeysOf("'", "\u2019", "\u201A", "\u2018", "\u203A", "\u2039"); + } + + // Helper method to add double quotes "more keys". + // "9LLR" means "9-low/Left quotation marks, Left/Right-pointing angle quotation marks". + public static ExpectedKeyboardBuilder doubleQuotes9LLR(final ExpectedKeyboardBuilder builder) { + return builder + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00AB", "\u00BB"); + } + + // Helper method to add double quotes "more keys". + // "9LLR" means "9-low/Left quotation marks, Right/Left-pointing angle quotation marks". + public static ExpectedKeyboardBuilder doubleQuotes9LRL(final ExpectedKeyboardBuilder builder) { + return builder + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + .setMoreKeysOf("\"", "\u201D", "\u201E", "\u201C", "\u00BB", "\u00AB"); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java new file mode 100644 index 000000000..368f9db46 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java @@ -0,0 +1,142 @@ +/* + * 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.keyboard.layout; + +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.LayoutBase; +import com.android.inputmethod.latin.Constants; + +/** + * The symbols shifted keyboard layout. + */ +public final class SymbolsShifted extends LayoutBase { + public static ExpectedKey[][] getSymbolsShifted(final boolean isPhone) { + return isPhone ? toPhoneSymbolsShifted(SYMBOLS_SHIFTED_COMMON) + : toTabletSymbolsShifted(SYMBOLS_SHIFTED_COMMON); + } + + // Functional key. + public static final ExpectedKey BACK_TO_SYMBOLS_KEY = key("?123", Constants.CODE_SHIFT); + + // Common symbols shifted keyboard layout. + public static final ExpectedKey[][] SYMBOLS_SHIFTED_COMMON = + new ExpectedKeyboardBuilder(10, 9, 7, 5) + // U+0060: "`" GRAVE ACCENT + // U+2022: "•" BULLET + // U+221A: "√" SQUARE ROOT + // U+03C0: "π" GREEK SMALL LETTER PI + // U+00F7: "÷" DIVISION SIGN + // U+00D7: "×" MULTIPLICATION SIGN + // U+00B6: "¶" PILCROW SIGN + // U+2206: "∆" INCREMENT + .setLabelsOfRow(1, + "~", "\u0060", "|", "\u2022", "\u221A", + "\u03C0", "\u00F7", "\u00D7", "\u00B6", "\u2206") + // U+2022: "•" BULLET + // U+266A: "♪" EIGHTH NOTE + // U+2665: "♥" BLACK HEART SUIT + // U+2660: "♠" BLACK SPADE SUIT + // U+2666: "♦" BLACK DIAMOND SUIT + // U+2663: "♣" BLACK CLUB SUIT + .setMoreKeysOf("\u2022", "\u266A", "\u2665", "\u2660", "\u2666", "\u2663") + // U+03C0: "π" GREEK SMALL LETTER PI + // U+03A0: "Π" GREEK CAPITAL LETTER PI + .setMoreKeysOf("\u03C0", "\u03A0") + // U+00B6: "¶" PILCROW SIGN + // U+00A7: "§" SECTION SIGN + .setMoreKeysOf("\u00B6", "\u00A7") + // U+00A3: "£" POUND SIGN + // U+00A2: "¢" CENT SIGN + // U+20AC: "€" EURO SIGN + // U+00A5: "¥" YEN SIGN + // U+00B0: "°" DEGREE SIGN + .setLabelsOfRow(2, + "\u00A3", "\u00A2", "\u20AC", "\u00A5", "^", + "\u00B0", "=", "{", "}") + // U+2191: "↑" UPWARDS ARROW + // U+2193: "↓" DOWNWARDS ARROW + // U+2190: "←" LEFTWARDS ARROW + // U+2192: "→" RIGHTWARDS ARROW + .setMoreKeysOf("^", "\u2191", "\u2193", "\u2190", "\u2192") + // U+00B0: "°" DEGREE SIGN + // U+2032: "′" PRIME + // U+2033: "″" DOUBLE PRIME + .setMoreKeysOf("\u00B0", "\u2032", "\u2033") + // U+2260: "≠" NOT EQUAL TO + // U+2248: "≈" ALMOST EQUAL TO + // U+221E: "∞" INFINITY + .setMoreKeysOf("=", "\u2260", "\u2248", "\u221E") + // U+00A9: "©" COPYRIGHT SIGN + // U+00AE: "®" REGISTERED SIGN + // U+2122: "™" TRADE MARK SIGN + // U+2105: "℅" CARE OF + .setLabelsOfRow(3, + "\\", "\u00A9", "\u00AE", "\u2122", "\u2105", + "[", "]") + .setLabelsOfRow(4, + "<", ">", " ", ",", ".") + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+2264: "≤" LESS-THAN OR EQUAL TO + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + .setMoreKeysOf("<", "\u2039", "\u2264", "\u00AB") + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // U+2265: "≥" GREATER-THAN EQUAL TO + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + .setMoreKeysOf(">", "\u203A", "\u2265", "\u00BB") + // U+2026: "…" HORIZONTAL ELLIPSIS + .setMoreKeysOf(".", "\u2026") + .build(); + + private static ExpectedKey[][] toPhoneSymbolsShifted(final ExpectedKey[][] common) { + return new ExpectedKeyboardBuilder(common) + .addKeysOnTheLeftOfRow(3, BACK_TO_SYMBOLS_KEY) + .addKeysOnTheRightOfRow(3, DELETE_KEY) + .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY) + .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY)) + .build(); + } + + private static ExpectedKey[][] toTabletSymbolsShifted(final ExpectedKey[][] common) { + return new ExpectedKeyboardBuilder(common) + // U+00BF: "¿" INVERTED QUESTION MARK + // U+00A1: "¡" INVERTED EXCLAMATION MARK + .addKeysOnTheRightOfRow(3, + key("\u00A1"), key("\u00BF")) + .addKeysOnTheRightOfRow(1, DELETE_KEY) + .addKeysOnTheRightOfRow(2, ENTER_KEY) + .addKeysOnTheLeftOfRow(3, BACK_TO_SYMBOLS_KEY) + .addKeysOnTheRightOfRow(3, BACK_TO_SYMBOLS_KEY) + .addKeysOnTheLeftOfRow(4, Symbols.ALPHABET_KEY) + .addKeysOnTheRightOfRow(4, EMOJI_KEY) + .build(); + } + + // Helper method to add currency symbols for Euro. + public static ExpectedKeyboardBuilder euro(final ExpectedKeyboardBuilder builder) { + return builder + // U+00A5: "¥" YEN SIGN + // U+00A2: "¢" CENT SIGN + .replaceKeyOfLabel("\u00A5", key("\u00A2")) + // U+20AC: "€" EURO SIGN + // U+00A2: "¢" CENT SIGN + .replaceKeyOfLabel("\u20AC", key("$", moreKey("\u00A2"))) + // U+00A2: "¢" CENT SIGN + // U+00A5: "¥" YEN SIGN + .replaceKeyOfLabel("\u00A2", key("\u00A5")); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java new file mode 100644 index 000000000..b918d47f8 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java @@ -0,0 +1,189 @@ +/* + * 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.keyboard.layout.expected; + +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.keyboard.internal.MoreKeySpec; +import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +/** + * This class builds an actual keyboard for unit test. + */ +public final class ActualKeyboardBuilder extends AbstractKeyboardBuilder<Key> { + // Comparator to sort {@link Key}s from top-left to bottom-right order. + private static final Comparator<Key> ROW_COLUMN_COMPARATOR = new Comparator<Key>() { + @Override + public int compare(final Key lhs, final Key rhs) { + if (lhs.getY() < rhs.getY()) return -1; + if (lhs.getY() > rhs.getY()) return 1; + if (lhs.getX() < rhs.getX()) return -1; + if (lhs.getX() > rhs.getX()) return 1; + return 0; + } + }; + + /** + * Create the keyboard that consists of the array of rows of the actual keyboard's keys. + * @param keys the array of keys of the actual keyboard. + * @return the actual keyboard grouped with rows. + */ + public static Key[][] buildKeyboard(final Key[] keys) { + // Sort keys from top-left to bottom-right order to prepare to create rows. + final ArrayList<Key> sortedKeys = CollectionUtils.newArrayList(Arrays.asList(keys)); + Collections.sort(sortedKeys, ROW_COLUMN_COMPARATOR); + + // Grouping keys into rows. + final ArrayList<ArrayList<Key>> rows = CollectionUtils.newArrayList(); + ArrayList<Key> elements = CollectionUtils.newArrayList(); + int lastY = sortedKeys.get(0).getY(); + for (final Key key : sortedKeys) { + if (lastY != key.getY()) { + // A new row is starting. + lastY = key.getY(); + rows.add(elements); + elements = CollectionUtils.newArrayList(); + } + elements.add(key); + } + rows.add(elements); // Add the last row. + + // Calculate each dimension of rows and create a builder. + final int[] dimensions = new int[rows.size()]; + for (int rowIndex = 0; rowIndex < dimensions.length; rowIndex++) { + dimensions[rowIndex] = rows.get(rowIndex).size(); + } + final ActualKeyboardBuilder builder = new ActualKeyboardBuilder(dimensions); + + for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) { + final int row = rowIndex + 1; + final ArrayList<Key> rowKeys = rows.get(rowIndex); + builder.setRowAt(row, rowKeys.toArray(new Key[rowKeys.size()])); + } + return builder.build(); + } + + private ActualKeyboardBuilder(final int ... dimensions) { + super(dimensions); + } + + @Override + Key defaultElement() { return null; } + + @Override + Key[] newArray(final int size) { return new Key[size]; } + + @Override + Key[][] newArrayOfArray(final int size) { return new Key[size][]; } + + // Helper class to create concise representation from the key specification. + static class MoreKeySpecStringizer extends StringUtils.Stringizer<MoreKeySpec> { + static final MoreKeySpecStringizer STRINGIZER = new MoreKeySpecStringizer(); + + @Override + public String stringize(final MoreKeySpec spec) { + return toString(spec.mLabel, spec.mIconId, spec.mOutputText, spec.mCode); + } + + static String toString(final String label, final int iconId, final String outputText, + final int code) { + final String visual = (iconId != KeyboardIconsSet.ICON_UNDEFINED) + ? KeyboardIconsSet.getIconName(iconId) : label; + final String output; + if (code == Constants.CODE_OUTPUT_TEXT) { + output = outputText; + } else if (code < Constants.CODE_SPACE) { + output = Constants.printableCode(code); + } else { + output = StringUtils.newSingleCodePointString(code); + } + if (visual.equals(output)) { + return visual; + } + return visual + "|" + output; + } + } + + // Helper class to create concise representation from the key. + static class KeyStringizer extends StringUtils.Stringizer<Key> { + static final KeyStringizer STRINGIZER = new KeyStringizer(); + + @Override + public String stringize(final Key key) { + if (key == null) { + return "NULL"; + } + if (key.isSpacer()) { + return "SPACER"; + } + final StringBuilder sb = new StringBuilder(); + sb.append(MoreKeySpecStringizer.toString( + key.getLabel(), key.getIconId(), key.getOutputText(), key.getCode())); + final MoreKeySpec[] moreKeys = key.getMoreKeys(); + if (moreKeys == null) { + return sb.toString(); + } + sb.append("^"); + sb.append(MoreKeySpecStringizer.STRINGIZER.join(moreKeys)); + return sb.toString(); + } + } + + /** + * Convert the key to human readable string. + * @param key the key to be converted to string. + * @return the human readable representation of <code>key</code>. + */ + public static String toString(final Key key) { + return KeyStringizer.STRINGIZER.stringize(key); + } + + /** + * Convert the keyboard row to human readable string. + * @param keys the keyboard row to be converted to string. + * @return the human readable representation of <code>keys</code>. + */ + public static String toString(final Key[] keys) { + return KeyStringizer.STRINGIZER.join(keys); + } + + // Helper class to create concise representation from the array of the key. + static class KeyArrayStringizer extends StringUtils.Stringizer<Key[]> { + static final KeyArrayStringizer STRINGIZER = new KeyArrayStringizer(); + + @Override + public String stringize(final Key[] keyArray) { + return KeyStringizer.STRINGIZER.join(keyArray); + } + } + + /** + * Convert the keyboard to human readable string. + * @param rows the keyboard to be converted to string. + * @return the human readable representation of <code>rows</code>. + */ + public static String toString(final Key[][] rows) { + return KeyArrayStringizer.STRINGIZER.join(rows, "\n" /* delimiter */); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java new file mode 100644 index 000000000..1aeb8c0cd --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/LayoutBase.java @@ -0,0 +1,143 @@ +/* + * 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.keyboard.layout.expected; + +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.latin.Constants; + +/** + * Base class to create an expected keyboard for unit test. + */ +public class LayoutBase { + // Those helper methods have a lower case name to be readable when defining expected keyboard + // layouts. + + // Helper method to create {@link ExpectedKey} object that has the label. + public static ExpectedKey key(final String label, final ExpectedKey ... moreKeys) { + return ExpectedKey.newInstance(label, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object that has the label and the output text. + public static ExpectedKey key(final String label, final String outputText, + final ExpectedKey ... moreKeys) { + return ExpectedKey.newInstance(label, outputText, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object that has the label and the output code. + public static ExpectedKey key(final String label, final int code, + final ExpectedKey ... moreKeys) { + return ExpectedKey.newInstance(label, code, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object that has the icon and the output code. + public static ExpectedKey key(final int iconId, final int code, + final ExpectedKey ... moreKeys) { + return ExpectedKey.newInstance(iconId, code, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object that has new "more keys". + public static ExpectedKey key(final ExpectedKey key, final ExpectedKey ... moreKeys) { + return ExpectedKey.newInstance(key.getVisual(), key.getOutput(), moreKeys); + } + + // Helper method to create {@link ExpectedKey} object for "more key" that has the label. + public static ExpectedKey moreKey(final String label) { + return ExpectedKey.newInstance(label); + } + + // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the + // output text. + public static ExpectedKey moreKey(final String label, final String outputText) { + return ExpectedKey.newInstance(label, outputText); + } + + // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the + // output code. + public static ExpectedKey moreKey(final String label, final int code) { + return ExpectedKey.newInstance(label, code); + } + + // Icon ids. + private static final int ICON_SHIFT = KeyboardIconsSet.getIconId("shift_key"); + private static final int ICON_DELETE = KeyboardIconsSet.getIconId("delete_key"); + private static final int ICON_SETTINGS = KeyboardIconsSet.getIconId("settings_key"); + private static final int ICON_ENTER = KeyboardIconsSet.getIconId("enter_key"); + private static final int ICON_EMOJI = KeyboardIconsSet.getIconId("emoji_key"); + + // Functional keys. + public static final ExpectedKey CAPSLOCK_MORE_KEY = key(" ", Constants.CODE_CAPSLOCK); + public static final ExpectedKey SHIFT_KEY = key(ICON_SHIFT, Constants.CODE_SHIFT); + public static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE); + public static final ExpectedKey SYMBOLS_KEY = key("?123", Constants.CODE_SWITCH_ALPHA_SYMBOL); + public static final ExpectedKey SETTINGS_KEY = key(ICON_SETTINGS, Constants.CODE_SETTINGS); + public static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER); + public static final ExpectedKey EMOJI_KEY = key(ICON_EMOJI, Constants.CODE_EMOJI); + + // Punctuation more keys for phone form factor. + public static final String[] PHONE_PUNCTUATION_MORE_KEYS = { + ";", "/", "(", ")", "#", "!", ",", "?", + "&", "%", "+", "\"", "-", ":", "'", "@" + }; + + // Punctuation more keys for tablet form factor. + public static final String[] TABLET_PUNCTUATION_MORE_KEYS = { + ";", "/", "(", ")", "#", "'", ",", + "&", "%", "+", "\"", "-", ":", "@" + }; + + private static ExpectedKeyboardBuilder toPhoneAlphabet(final ExpectedKeyboardBuilder builder) { + return builder + .addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY)) + .addKeysOnTheRightOfRow(3, DELETE_KEY) + .setLabelsOfRow(4, ",", " ", ".") + .setMoreKeysOf(",", SETTINGS_KEY) + .setMoreKeysOf(".", PHONE_PUNCTUATION_MORE_KEYS) + .addKeysOnTheLeftOfRow(4, SYMBOLS_KEY) + .addKeysOnTheRightOfRow(4, key(ENTER_KEY, EMOJI_KEY)); + } + + // Helper method to create alphabet layout for tablet by adding special function keys except + // shift key. + public static ExpectedKeyboardBuilder toTabletAlphabetWithoutShiftKeys( + final ExpectedKeyboardBuilder builder) { + return builder + // U+00BF: "¿" INVERTED QUESTION MARK + // U+00A1: "¡" INVERTED EXCLAMATION MARK + .addKeysOnTheRightOfRow(3, + key("!", moreKey("\u00A1")), key("?", moreKey("\u00BF"))) + .addKeysOnTheRightOfRow(1, DELETE_KEY) + .addKeysOnTheRightOfRow(2, ENTER_KEY) + .setLabelsOfRow(4, "/", " ", ",", ".") + .setMoreKeysOf(".", TABLET_PUNCTUATION_MORE_KEYS) + .addKeysOnTheLeftOfRow(4, SYMBOLS_KEY, SETTINGS_KEY) + .addKeysOnTheRightOfRow(4, EMOJI_KEY); + } + + // Helper method to create alphabet layout by adding special function keys. + public static ExpectedKey[][] toCommonAlphabet(final ExpectedKey[][] common, + final boolean isPhone) { + final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(common); + if (isPhone) { + toPhoneAlphabet(builder); + } else { + toTabletAlphabetWithoutShiftKeys(builder); + builder.addKeysOnTheLeftOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY)) + .addKeysOnTheRightOfRow(3, key(SHIFT_KEY, CAPSLOCK_MORE_KEY)); + } + return builder.build(); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java new file mode 100644 index 000000000..427e7de49 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java @@ -0,0 +1,197 @@ +/* + * 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.keyboard.layout.tests; + +import android.util.Log; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.keyboard.KeyboardLayoutSet; +import com.android.inputmethod.keyboard.KeyboardLayoutSetTestsBase; +import com.android.inputmethod.keyboard.layout.AlphabetShifted; +import com.android.inputmethod.keyboard.layout.Symbols; +import com.android.inputmethod.keyboard.layout.SymbolsShifted; +import com.android.inputmethod.keyboard.layout.expected.ActualKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; +import com.android.inputmethod.keyboard.layout.expected.LayoutBase; +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +import java.util.Arrays; +import java.util.Locale; + +/** + * Base class for keyboard layout unit test. + */ +abstract class LayoutTestsBase extends KeyboardLayoutSetTestsBase { + private InputMethodSubtype mSubtype; + private String mLogTag; + private KeyboardLayoutSet mKeyboardLayoutSet; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mSubtype = getSubtype(getTestLocale(), getTestKeyboardLayout()); + mLogTag = SubtypeLocaleUtils.getSubtypeNameForLogging(mSubtype) + "/" + + (isPhone() ? "phone" : "tablet"); + mKeyboardLayoutSet = createKeyboardLayoutSet(mSubtype, null /* editorInfo */); + } + + // Those helper methods have a lower case name to be readable when defining expected keyboard + // layouts. + + // Helper method to create {@link ExpectedKey} object that has the label. + static ExpectedKey key(final String label, final ExpectedKey ... moreKeys) { + return LayoutBase.key(label, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object that has the label and the output text. + static ExpectedKey key(final String label, final String outputText, + final ExpectedKey ... moreKeys) { + return LayoutBase.key(label, outputText, moreKeys); + } + + // Helper method to create {@link ExpectedKey} object for "more key" that has the label. + static ExpectedKey moreKey(final String label) { + return LayoutBase.moreKey(label); + } + + // Helper method to create {@link ExpectedKey} object for "more key" that has the label and the + // output text. + static ExpectedKey moreKey(final String label, final String outputText) { + return LayoutBase.moreKey(label, outputText); + } + + // Locale for testing subtype. + abstract Locale getTestLocale(); + + // Keyboard layout name for testing subtype. + abstract String getTestKeyboardLayout(); + + // Alphabet keyboard for testing subtype. + abstract ExpectedKey[][] getAlphabet(final boolean isPhone); + + // Alphabet automatic shifted keyboard for testing subtype. + ExpectedKey[][] getAlphabetAutomaticShifted(final boolean isPhone) { + return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale()); + } + + // Alphabet manual shifted keyboard for testing subtype. + ExpectedKey[][] getAlphabetManualShifted(final boolean isPhone) { + return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale()); + } + + // Alphabet shift locked keyboard for testing subtype. + ExpectedKey[][] getAlphabetShiftLocked(final boolean isPhone) { + return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale()); + } + + // Alphabet shift lock shifted keyboard for testing subtype. + ExpectedKey[][] getAlphabetShiftLockShifted(final boolean isPhone) { + return AlphabetShifted.getAlphabet(getAlphabet(isPhone), getTestLocale()); + } + + // Symbols keyboard for testing subtype. + ExpectedKey[][] getSymbols(final boolean isPhone) { + return Symbols.getSymbols(isPhone); + } + + // Symbols shifted keyboard for testing subtype. + ExpectedKey[][] getSymbolsShifted(final boolean isPhone) { + return SymbolsShifted.getSymbolsShifted(isPhone); + } + + // TODO: Add phone, phone symbols, number, number password layout tests. + + public final void testAlphabet() { + final int elementId = KeyboardId.ELEMENT_ALPHABET; + doKeyboardTests(elementId, getAlphabet(isPhone())); + } + + public final void testAlphabetAutomaticShifted() { + final int elementId = KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED; + doKeyboardTests(elementId, getAlphabetAutomaticShifted(isPhone())); + } + + public final void testAlphabetManualShifted() { + final int elementId = KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED; + doKeyboardTests(elementId, getAlphabetManualShifted(isPhone())); + } + + public final void testAlphabetShiftLocked() { + final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED; + doKeyboardTests(elementId, getAlphabetShiftLocked(isPhone())); + } + + public final void testAlphabetShiftLockShifted() { + final int elementId = KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED; + doKeyboardTests(elementId, getAlphabetShiftLockShifted(isPhone())); + } + + public final void testSymbols() { + final int elementId = KeyboardId.ELEMENT_SYMBOLS; + doKeyboardTests(elementId, getSymbols(isPhone())); + } + + public final void testSymbolsShifted() { + final int elementId = KeyboardId.ELEMENT_SYMBOLS_SHIFTED; + doKeyboardTests(elementId, getSymbolsShifted(isPhone())); + } + + // Comparing expected keyboard and actual keyboard. + private void doKeyboardTests(final int elementId, final ExpectedKey[][] expectedKeyboard) { + // Skip test if no keyboard is defined. + if (expectedKeyboard == null) { + return; + } + final String tag = mLogTag + "/" + KeyboardId.elementIdToName(elementId); + // Create actual keyboard object. + final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(elementId); + // Create actual keyboard to be compared with the expected keyboard. + final Key[][] actualKeyboard = ActualKeyboardBuilder.buildKeyboard(keyboard.getKeys()); + + // Dump human readable definition of expected/actual keyboards. + Log.d(tag, "expected=\n" + ExpectedKeyboardBuilder.toString(expectedKeyboard)); + Log.d(tag, "actual =\n" + ActualKeyboardBuilder.toString(actualKeyboard)); + // Test both keyboards have the same number of rows. + assertEquals(tag + " labels" + + "\nexpected=" + Arrays.deepToString(expectedKeyboard) + + "\nactual =" + ActualKeyboardBuilder.toString(actualKeyboard), + expectedKeyboard.length, actualKeyboard.length); + for (int r = 0; r < actualKeyboard.length; r++) { + final int row = r + 1; + // Test both keyboards' rows have the same number of columns. + assertEquals(tag + " labels row=" + row + + "\nexpected=" + Arrays.toString(expectedKeyboard[r]) + + "\nactual =" + ActualKeyboardBuilder.toString(actualKeyboard[r]), + expectedKeyboard[r].length, actualKeyboard[r].length); + for (int c = 0; c < actualKeyboard[r].length; c++) { + final int column = c + 1; + final Key actualKey = actualKeyboard[r][c]; + final ExpectedKey expectedKey = expectedKeyboard[r][c]; + // Test both keyboards' keys have the same visual outlook and key output. + assertTrue(tag + " labels row,column=" + row + "," + column + + "\nexpected=" + expectedKey + + "\nactual =" + ActualKeyboardBuilder.toString(actualKey), + expectedKey.equalsTo(actualKey)); + } + } + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java new file mode 100644 index 000000000..0792a5789 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java @@ -0,0 +1,98 @@ +/* + * 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.keyboard.layout.tests; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.inputmethod.keyboard.layout.Qwerty; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; +import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; + +import java.util.Locale; + +/** + * en_US: English (United States)/qwerty + */ +@SmallTest +public final class TestsEnglishUS extends LayoutTestsBase { + @Override + Locale getTestLocale() { + return new Locale("en", "US"); + } + + @Override + String getTestKeyboardLayout() { + return "qwerty"; + } + + @Override + ExpectedKey[][] getAlphabet(final boolean isPhone) { + final ExpectedKey[][] keyboard = Qwerty.getAlphabet(isPhone); + final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(keyboard); + setAccentedLetters(builder); + return builder.build(); + } + + static ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) { + return builder + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + .setMoreKeysOf("e", "3", "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0113") + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + .setMoreKeysOf("u", "7", "\u00FB", "\u00FC", "\u00F9", "\u00FA", "\u016B") + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + .setMoreKeysOf("i", "8", "\u00EE", "\u00EF", "\u00ED", "\u012B", "\u00EC") + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + .setMoreKeysOf("o", + "9", "\u00F4", "\u00F6", "\u00F2", "\u00F3", "\u0153", "\u00F8", "\u014D", + "\u00F5") + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + .setMoreKeysOf("a", + "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5", + "\u0101") + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + .setMoreKeysOf("s", "\u00DF") + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + .setMoreKeysOf("c", "\u00E7") + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + .setMoreKeysOf("n", "\u00F1"); + } +} diff --git a/tools/Android.mk b/tools/Android.mk index dc1403337..91b2fbbb0 100644 --- a/tools/Android.mk +++ b/tools/Android.mk @@ -12,6 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Temporarily excluding dicttool -#include $(call all-subdir-makefiles) -include $(call all-named-subdir-makefiles, make-keyboard-text) +include $(call all-subdir-makefiles) diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk index b1dd7f653..c0a55626a 100644 --- a/tools/dicttool/Android.mk +++ b/tools/dicttool/Android.mk @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11. +LATINIME_HOST_OSNAME := $(shell uname -s) +ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this + LATINIME_DICTTOOL_AOSP_LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(LATINIME_DICTTOOL_AOSP_LOCAL_PATH) LATINIME_HOST_NATIVE_LIBNAME := liblatinime-aosp-dicttool-host @@ -74,10 +78,14 @@ LOCAL_JAVA_LIBRARIES := junit LOCAL_ADDITIONAL_DEPENDENCIES := $(LATINIME_HOST_NATIVE_LIBNAME) LOCAL_JAR_MANIFEST := etc/manifest.txt LOCAL_MODULE := dicttool_aosp +LOCAL_IS_HOST_MODULE := true include $(BUILD_HOST_JAVA_LIBRARY) include $(LOCAL_PATH)/etc/Android.mk +endif # Darwin - TODO: Remove this + # Clear our private variables LATINIME_DICTTOOL_AOSP_LOCAL_PATH := LATINIME_LOCAL_DIR := +LATINIME_HOST_OSNAME := diff --git a/tools/dicttool/NativeLib.mk b/tools/dicttool/NativeLib.mk index 26b677447..95f767dc9 100644 --- a/tools/dicttool/NativeLib.mk +++ b/tools/dicttool/NativeLib.mk @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11. +LATINIME_HOST_OSNAME := $(shell uname -s) +ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) @@ -49,9 +53,13 @@ LOCAL_SRC_FILES := \ $(addprefix $(LATINIME_NATIVE_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES)) LOCAL_MODULE := $(LATINIME_HOST_NATIVE_LIBNAME) +LOCAL_IS_HOST_MODULE := true include $(BUILD_HOST_SHARED_LIBRARY) +endif # Darwin - TODO: Remove this + # Clear our private variables include $(LOCAL_PATH)/$(LATINIME_NATIVE_JNI_DIR)/CleanupNativeFileList.mk LATINIME_DIR_RELATIVE_TO_DICTTOOL := ../.. +LATINIME_HOST_OSNAME := |