1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.inputmethod.keyboard.internal; 18 19 import android.graphics.drawable.Drawable; 20 21 import com.android.inputmethod.keyboard.Key; 22 import com.android.inputmethod.keyboard.Keyboard; 23 import com.android.inputmethod.keyboard.KeyboardId; 24 import com.android.inputmethod.latin.LatinImeLogger; 25 26 import java.util.ArrayList; 27 import java.util.HashMap; 28 import java.util.HashSet; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 33 public class KeyboardParams { 34 public KeyboardId mId; 35 public int mThemeId; 36 37 /** Total height and width of the keyboard, including the paddings and keys */ 38 public int mOccupiedHeight; 39 public int mOccupiedWidth; 40 41 /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */ 42 public int mBaseHeight; 43 public int mBaseWidth; 44 45 public int mTopPadding; 46 public int mBottomPadding; 47 public int mHorizontalEdgesPadding; 48 public int mHorizontalCenterPadding; 49 50 public int mDefaultRowHeight; 51 public int mDefaultKeyWidth; 52 public int mHorizontalGap; 53 public int mVerticalGap; 54 55 public boolean mIsRtlKeyboard; 56 public int mMoreKeysTemplate; 57 public int mMaxMiniKeyboardColumn; 58 59 public int GRID_WIDTH; 60 public int GRID_HEIGHT; 61 62 public final List<Key> mKeys = new ArrayList<Key>(); 63 public final List<Key> mShiftKeys = new ArrayList<Key>(); 64 public final Set<Key> mShiftLockKeys = new HashSet<Key>(); 65 public final Map<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>(); 66 public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>(); 67 public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); 68 69 public int mMostCommonKeyHeight = 0; 70 public int mMostCommonKeyWidth = 0; 71 72 public final TouchPositionCorrection mTouchPositionCorrection = new TouchPositionCorrection(); 73 74 public static class TouchPositionCorrection { 75 private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3; 76 77 public boolean mEnabled; 78 public float[] mXs; 79 public float[] mYs; 80 public float[] mRadii; 81 82 public void load(String[] data) { 83 final int dataLength = data.length; 84 if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) { 85 if (LatinImeLogger.sDBG) 86 throw new RuntimeException( 87 "the size of touch position correction data is invalid"); 88 return; 89 } 90 91 final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE; 92 mXs = new float[length]; 93 mYs = new float[length]; 94 mRadii = new float[length]; 95 try { 96 for (int i = 0; i < dataLength; ++i) { 97 final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE; 98 final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE; 99 final float value = Float.parseFloat(data[i]); 100 if (type == 0) { 101 mXs[index] = value; 102 } else if (type == 1) { 103 mYs[index] = value; 104 } else { 105 mRadii[index] = value; 106 } 107 } 108 } catch (NumberFormatException e) { 109 if (LatinImeLogger.sDBG) { 110 throw new RuntimeException( 111 "the number format for touch position correction data is invalid"); 112 } 113 mXs = null; 114 mYs = null; 115 mRadii = null; 116 } 117 } 118 119 public void setEnabled(boolean enabled) { 120 mEnabled = enabled; 121 } 122 123 public boolean isValid() { 124 return mEnabled && mXs != null && mYs != null && mRadii != null 125 && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0; 126 } 127 } 128 129 protected void clearKeys() { 130 mKeys.clear(); 131 mShiftKeys.clear(); 132 mShiftLockKeys.clear(); 133 mShiftedIcons.clear(); 134 mUnshiftedIcons.clear(); 135 clearHistogram(); 136 } 137 138 public void onAddKey(Key key) { 139 mKeys.add(key); 140 updateHistogram(key); 141 if (key.mCode == Keyboard.CODE_SHIFT) { 142 mShiftKeys.add(key); 143 if (key.isSticky()) { 144 mShiftLockKeys.add(key); 145 } 146 } 147 } 148 149 public void addShiftedIcon(Key key, Drawable icon) { 150 mUnshiftedIcons.put(key, key.getIcon()); 151 mShiftedIcons.put(key, icon); 152 } 153 154 private int mMaxHeightCount = 0; 155 private int mMaxWidthCount = 0; 156 private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); 157 private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); 158 159 private void clearHistogram() { 160 mMostCommonKeyHeight = 0; 161 mMaxHeightCount = 0; 162 mHeightHistogram.clear(); 163 164 mMaxWidthCount = 0; 165 mMostCommonKeyWidth = 0; 166 mWidthHistogram.clear(); 167 } 168 169 private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) { 170 final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; 171 histogram.put(key, count); 172 return count; 173 } 174 175 private void updateHistogram(Key key) { 176 final Integer height = key.mHeight + key.mVerticalGap; 177 final int heightCount = updateHistogramCounter(mHeightHistogram, height); 178 if (heightCount > mMaxHeightCount) { 179 mMaxHeightCount = heightCount; 180 mMostCommonKeyHeight = height; 181 } 182 183 final Integer width = key.mWidth + key.mHorizontalGap; 184 final int widthCount = updateHistogramCounter(mWidthHistogram, width); 185 if (widthCount > mMaxWidthCount) { 186 mMaxWidthCount = widthCount; 187 mMostCommonKeyWidth = width; 188 } 189 } 190 } 191