2011-02-22 08:28:55 +00:00
|
|
|
/*
|
2011-05-20 03:09:57 +00:00
|
|
|
* Copyright (C) 2011 The Android Open Source Project
|
2011-02-22 08:28:55 +00:00
|
|
|
*
|
|
|
|
* 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;
|
|
|
|
|
2011-02-25 09:21:02 +00:00
|
|
|
import com.android.inputmethod.latin.Utils;
|
2011-08-08 04:37:11 +00:00
|
|
|
import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;
|
2011-02-25 09:21:02 +00:00
|
|
|
|
2011-03-04 14:06:45 +00:00
|
|
|
import java.util.Arrays;
|
2011-08-04 03:08:22 +00:00
|
|
|
import java.util.Collections;
|
2011-03-04 14:06:45 +00:00
|
|
|
import java.util.List;
|
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
public class ProximityInfo {
|
|
|
|
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
|
2011-07-12 05:58:46 +00:00
|
|
|
/** Number of key widths from current touch point to search for nearest keys. */
|
|
|
|
private static float SEARCH_DISTANCE = 1.2f;
|
|
|
|
private static final int[] EMPTY_INT_ARRAY = new int[0];
|
2011-02-22 08:28:55 +00:00
|
|
|
|
|
|
|
private final int mGridWidth;
|
|
|
|
private final int mGridHeight;
|
|
|
|
private final int mGridSize;
|
2011-07-12 05:58:46 +00:00
|
|
|
private final int mCellWidth;
|
|
|
|
private final int mCellHeight;
|
|
|
|
// TODO: Find a proper name for mKeyboardMinWidth
|
|
|
|
private final int mKeyboardMinWidth;
|
|
|
|
private final int mKeyboardHeight;
|
|
|
|
private final int[][] mGridNeighbors;
|
2011-02-22 08:28:55 +00:00
|
|
|
|
2011-07-12 05:58:46 +00:00
|
|
|
ProximityInfo(
|
|
|
|
int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, List<Key> keys) {
|
2011-02-22 08:28:55 +00:00
|
|
|
mGridWidth = gridWidth;
|
|
|
|
mGridHeight = gridHeight;
|
|
|
|
mGridSize = mGridWidth * mGridHeight;
|
2011-07-12 05:58:46 +00:00
|
|
|
mCellWidth = (minWidth + mGridWidth - 1) / mGridWidth;
|
|
|
|
mCellHeight = (height + mGridHeight - 1) / mGridHeight;
|
|
|
|
mKeyboardMinWidth = minWidth;
|
|
|
|
mKeyboardHeight = height;
|
|
|
|
mGridNeighbors = new int[mGridSize][];
|
|
|
|
if (minWidth == 0 || height == 0) {
|
|
|
|
// No proximity required. Keyboard might be mini keyboard.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
computeNearestNeighbors(keyWidth, keys);
|
2011-02-22 08:28:55 +00:00
|
|
|
}
|
|
|
|
|
2011-08-04 03:08:22 +00:00
|
|
|
public static ProximityInfo getDummyProximityInfo() {
|
|
|
|
return new ProximityInfo(1, 1, 1, 1, 1, Collections.<Key>emptyList());
|
|
|
|
}
|
|
|
|
|
2011-08-08 04:37:11 +00:00
|
|
|
public static ProximityInfo getSpellCheckerProximityInfo() {
|
|
|
|
final ProximityInfo spellCheckerProximityInfo = getDummyProximityInfo();
|
|
|
|
spellCheckerProximityInfo.mNativeProximityInfo =
|
|
|
|
spellCheckerProximityInfo.setProximityInfoNative(
|
|
|
|
SpellCheckerProximityInfo.ROW_SIZE,
|
|
|
|
480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY);
|
|
|
|
return spellCheckerProximityInfo;
|
|
|
|
}
|
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
private int mNativeProximityInfo;
|
2011-02-25 09:21:02 +00:00
|
|
|
static {
|
|
|
|
Utils.loadNativeLibrary();
|
|
|
|
}
|
2011-02-22 08:28:55 +00:00
|
|
|
private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
|
|
|
|
int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
|
|
|
|
private native void releaseProximityInfoNative(int nativeProximityInfo);
|
|
|
|
|
2011-07-12 05:58:46 +00:00
|
|
|
private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
|
2011-03-04 14:06:45 +00:00
|
|
|
int keyboardHeight, List<Key> keys) {
|
2011-02-22 08:28:55 +00:00
|
|
|
int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
|
2011-03-04 14:06:45 +00:00
|
|
|
Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
|
2011-02-22 08:28:55 +00:00
|
|
|
for (int i = 0; i < mGridSize; ++i) {
|
2011-03-04 14:06:45 +00:00
|
|
|
final int proximityCharsLength = gridNeighborKeyIndexes[i].length;
|
|
|
|
for (int j = 0; j < proximityCharsLength; ++j) {
|
|
|
|
proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] =
|
|
|
|
keys.get(gridNeighborKeyIndexes[i][j]).mCode;
|
2011-02-22 08:28:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE,
|
2011-03-04 14:06:45 +00:00
|
|
|
keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
|
2011-02-22 08:28:55 +00:00
|
|
|
}
|
|
|
|
|
2011-07-12 05:58:46 +00:00
|
|
|
public int getNativeProximityInfo() {
|
2011-02-22 08:28:55 +00:00
|
|
|
return mNativeProximityInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void finalize() throws Throwable {
|
|
|
|
try {
|
|
|
|
if (mNativeProximityInfo != 0) {
|
|
|
|
releaseProximityInfoNative(mNativeProximityInfo);
|
|
|
|
mNativeProximityInfo = 0;
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
super.finalize();
|
|
|
|
}
|
|
|
|
}
|
2011-07-12 05:58:46 +00:00
|
|
|
|
|
|
|
private void computeNearestNeighbors(int defaultWidth, List<Key> keys) {
|
|
|
|
final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
|
|
|
|
final int threshold = thresholdBase * thresholdBase;
|
|
|
|
// Round-up so we don't have any pixels outside the grid
|
|
|
|
final int[] indices = new int[keys.size()];
|
|
|
|
final int gridWidth = mGridWidth * mCellWidth;
|
|
|
|
final int gridHeight = mGridHeight * mCellHeight;
|
|
|
|
for (int x = 0; x < gridWidth; x += mCellWidth) {
|
|
|
|
for (int y = 0; y < gridHeight; y += mCellHeight) {
|
|
|
|
final int centerX = x + mCellWidth / 2;
|
|
|
|
final int centerY = y + mCellHeight / 2;
|
|
|
|
int count = 0;
|
|
|
|
for (int i = 0; i < keys.size(); i++) {
|
|
|
|
final Key key = keys.get(i);
|
|
|
|
if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
|
|
|
|
indices[count++] = i;
|
|
|
|
}
|
|
|
|
final int[] cell = new int[count];
|
|
|
|
System.arraycopy(indices, 0, cell, 0, count);
|
|
|
|
mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = cell;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int[] getNearestKeys(int x, int y) {
|
|
|
|
if (mGridNeighbors == null) {
|
|
|
|
return EMPTY_INT_ARRAY;
|
|
|
|
}
|
|
|
|
if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
|
|
|
|
int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth);
|
|
|
|
if (index < mGridSize) {
|
|
|
|
return mGridNeighbors[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return EMPTY_INT_ARRAY;
|
|
|
|
}
|
2011-02-22 08:28:55 +00:00
|
|
|
}
|