11516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka/* 21516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project 31516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * 41516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); you may not 51516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * use this file except in compliance with the License. You may obtain a copy of 61516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * the License at 71516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * 81516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 91516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * 101516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 111516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 121516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 131516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * License for the specific language governing permissions and limitations under 141516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka * the License. 151516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka */ 161516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 171516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokapackage com.android.inputmethod.keyboard.internal; 181516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 191516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport android.graphics.drawable.Drawable; 201516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 211516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Key; 228da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaokaimport com.android.inputmethod.keyboard.Keyboard; 231516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyboardId; 24294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojimaimport com.android.inputmethod.latin.LatinImeLogger; 251516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 261516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.ArrayList; 271516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.HashMap; 281516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.HashSet; 291516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.List; 301516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.Map; 311516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokaimport java.util.Set; 321516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 331516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaokapublic class KeyboardParams { 341516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public KeyboardId mId; 3563584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka public int mThemeId; 361516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 378fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka /** Total height and width of the keyboard, including the paddings and keys */ 388da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public int mOccupiedHeight; 398da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public int mOccupiedWidth; 401516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 418fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */ 428fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka public int mBaseHeight; 438fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka public int mBaseWidth; 441516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 451516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mTopPadding; 461516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mBottomPadding; 471516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mHorizontalEdgesPadding; 481516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mHorizontalCenterPadding; 491516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 501516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mDefaultRowHeight; 511516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mDefaultKeyWidth; 521516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mHorizontalGap; 531516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int mVerticalGap; 541516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 551516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public boolean mIsRtlKeyboard; 569d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka public int mMoreKeysTemplate; 579237a72634be821c22911633ef0848130e162d58Tadashi G. Takaoka public int mMaxMiniKeyboardColumn; 581516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 591516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int GRID_WIDTH; 601516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public int GRID_HEIGHT; 611516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 621516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final List<Key> mKeys = new ArrayList<Key>(); 631516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final List<Key> mShiftKeys = new ArrayList<Key>(); 641516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final Set<Key> mShiftLockKeys = new HashSet<Key>(); 651516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final Map<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>(); 661516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>(); 671516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); 681516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 698fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka public int mMostCommonKeyHeight = 0; 708da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public int mMostCommonKeyWidth = 0; 718da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka 72294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public final TouchPositionCorrection mTouchPositionCorrection = new TouchPositionCorrection(); 73294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 74294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public static class TouchPositionCorrection { 75294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3; 76294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 77294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public boolean mEnabled; 78294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public float[] mXs; 79294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public float[] mYs; 80294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public float[] mRadii; 81294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 82294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public void load(String[] data) { 83294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima final int dataLength = data.length; 84294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) { 85294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima if (LatinImeLogger.sDBG) 86294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima throw new RuntimeException( 87294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "the size of touch position correction data is invalid"); 88294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima return; 89294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 90294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 91294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE; 92294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mXs = new float[length]; 93294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mYs = new float[length]; 94294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mRadii = new float[length]; 95294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima try { 96294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima for (int i = 0; i < dataLength; ++i) { 97294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE; 98294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE; 99294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima final float value = Float.parseFloat(data[i]); 100294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima if (type == 0) { 101294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mXs[index] = value; 102294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } else if (type == 1) { 103294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mYs[index] = value; 104294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } else { 105294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mRadii[index] = value; 106294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 107294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 108294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } catch (NumberFormatException e) { 109294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima if (LatinImeLogger.sDBG) { 110294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima throw new RuntimeException( 111294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima "the number format for touch position correction data is invalid"); 112294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 113294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mXs = null; 114294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mYs = null; 115294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mRadii = null; 116294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 117294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 118294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 119294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public void setEnabled(boolean enabled) { 120294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima mEnabled = enabled; 121294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 122294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima 123294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima public boolean isValid() { 124294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima return mEnabled && mXs != null && mYs != null && mRadii != null 125294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0; 126294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 127294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima } 128d6339639c39cbe0a833361623bf6963cff526784Yusuke Nojima 129c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka protected void clearKeys() { 130c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mKeys.clear(); 131c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mShiftKeys.clear(); 132c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mShiftLockKeys.clear(); 133c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mShiftedIcons.clear(); 134c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mUnshiftedIcons.clear(); 135c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka clearHistogram(); 136c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka } 137c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka 1388da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public void onAddKey(Key key) { 1398da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mKeys.add(key); 1408da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka updateHistogram(key); 1418da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka if (key.mCode == Keyboard.CODE_SHIFT) { 1428da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mShiftKeys.add(key); 1435b0c124ca888ee4ecbde9a51f11c4e9887a96636Tadashi G. Takaoka if (key.isSticky()) { 1448da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mShiftLockKeys.add(key); 1458da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka } 1461516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka } 1471516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka } 1481516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 1491516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka public void addShiftedIcon(Key key, Drawable icon) { 1501516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka mUnshiftedIcons.put(key, key.getIcon()); 1511516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka mShiftedIcons.put(key, icon); 1521516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka } 1531516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka 1548fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka private int mMaxHeightCount = 0; 1558fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka private int mMaxWidthCount = 0; 1568fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); 1578fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); 1588da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka 159c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka private void clearHistogram() { 1608fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMostCommonKeyHeight = 0; 1618fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMaxHeightCount = 0; 1628fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mHeightHistogram.clear(); 1638fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka 1648fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMaxWidthCount = 0; 165c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka mMostCommonKeyWidth = 0; 1668fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mWidthHistogram.clear(); 1678fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka } 1688fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka 1698fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) { 1708fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; 1718fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka histogram.put(key, count); 1728fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka return count; 173c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka } 174c06d0ef01ddf286080fd421829a587741b1ebc1bTadashi G. Takaoka 1758da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka private void updateHistogram(Key key) { 1768fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka final Integer height = key.mHeight + key.mVerticalGap; 1778fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka final int heightCount = updateHistogramCounter(mHeightHistogram, height); 1788fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka if (heightCount > mMaxHeightCount) { 1798fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMaxHeightCount = heightCount; 1808fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMostCommonKeyHeight = height; 1818fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka } 1828fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka 1838da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka final Integer width = key.mWidth + key.mHorizontalGap; 1848fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka final int widthCount = updateHistogramCounter(mWidthHistogram, width); 1858fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka if (widthCount > mMaxWidthCount) { 1868fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMaxWidthCount = widthCount; 1878da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mMostCommonKeyWidth = width; 1881516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka } 1891516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka } 1901516d055df0d939c76ab8f2739f7fb1cdd3956d0Tadashi G. Takaoka} 191