Merge remote-tracking branch 'goog/master' into mergescriptpackage

main
Ken Wakasa 2012-12-04 18:29:25 +09:00
commit 3709da91a5
22 changed files with 302 additions and 142 deletions

View File

@ -81,6 +81,11 @@
<!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] --> <!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
<string name="use_contacts_dict_summary">Use names from Contacts for suggestions and corrections</string> <string name="use_contacts_dict_summary">Use names from Contacts for suggestions and corrections</string>
<!-- Option name for enabling or disabling the double-space period feature that lets double tap on spacebar insert a period followed by a space [CHAR LIMIT=25] -->
<string name="use_double_space_period">Double-space period</string>
<!-- Description for option enabling or disabling the double-space period feature that lets double tap on spacebar insert a period followed by a space [CHAR LIMIT=65] -->
<string name="use_double_space_period_summary">Double tap on spacebar inserts a period followed by a space</string>
<!-- Option to enable auto capitalization of sentences --> <!-- Option to enable auto capitalization of sentences -->
<string name="auto_cap">Auto-capitalization</string> <string name="auto_cap">Auto-capitalization</string>
<!-- Description for option to enable auto capitalization of sentences --> <!-- Description for option to enable auto capitalization of sentences -->

View File

@ -118,6 +118,12 @@
android:summary="@string/use_contacts_dict_summary" android:summary="@string/use_contacts_dict_summary"
android:persistent="true" android:persistent="true"
android:defaultValue="true" /> android:defaultValue="true" />
<CheckBoxPreference
android:key="pref_key_use_double_space_period"
android:title="@string/use_double_space_period"
android:summary="@string/use_double_space_period_summary"
android:persistent="true"
android:defaultValue="true" />
<CheckBoxPreference <CheckBoxPreference
android:key="pref_show_language_switch_key" android:key="pref_show_language_switch_key"
android:title="@string/show_language_switch_key" android:title="@string/show_language_switch_key"

View File

@ -135,7 +135,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// Preview placer view // Preview placer view
private final PreviewPlacerView mPreviewPlacerView; private final PreviewPlacerView mPreviewPlacerView;
private final int[] mCoordinates = CoordinateUtils.newInstance(); private final int[] mOriginCoords = CoordinateUtils.newInstance();
// Key preview // Key preview
private static final int PREVIEW_ALPHA = 240; private static final int PREVIEW_ALPHA = 240;
@ -833,10 +833,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// In transient state. // In transient state.
return; return;
} }
final int[] viewOrigin = CoordinateUtils.newInstance(); getLocationInWindow(mOriginCoords);
getLocationInWindow(viewOrigin);
final DisplayMetrics dm = getResources().getDisplayMetrics(); final DisplayMetrics dm = getResources().getDisplayMetrics();
if (CoordinateUtils.y(viewOrigin) < dm.heightPixels / 4) { if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) {
// In transient state. // In transient state.
return; return;
} }
@ -851,11 +850,21 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView"); Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView");
} else { } else {
windowContentView.addView(mPreviewPlacerView); windowContentView.addView(mPreviewPlacerView);
mPreviewPlacerView.setKeyboardViewGeometry( mPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height);
CoordinateUtils.x(viewOrigin), CoordinateUtils.y(viewOrigin), width, height);
} }
} }
@Override
public void showSlidingKeyInputPreview(final PointerTracker tracker) {
locatePreviewPlacerView();
mPreviewPlacerView.showSlidingKeyInputPreview(tracker);
}
@Override
public void dismissSlidingKeyInputPreview() {
mPreviewPlacerView.dismissSlidingKeyInputPreview();
}
public void showGestureFloatingPreviewText(final String gestureFloatingPreviewText) { public void showGestureFloatingPreviewText(final String gestureFloatingPreviewText) {
locatePreviewPlacerView(); locatePreviewPlacerView();
mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText); mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText);
@ -937,13 +946,13 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// The distance between the top edge of the parent key and the bottom of the visible part // The distance between the top edge of the parent key and the bottom of the visible part
// of the key preview background. // of the key preview background.
previewParams.mPreviewVisibleOffset = mPreviewOffset - previewText.getPaddingBottom(); previewParams.mPreviewVisibleOffset = mPreviewOffset - previewText.getPaddingBottom();
getLocationInWindow(mCoordinates); getLocationInWindow(mOriginCoords);
// The key preview is horizontally aligned with the center of the visible part of the // The key preview is horizontally aligned with the center of the visible part of the
// parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and
// the left/right background is used if such background is specified. // the left/right background is used if such background is specified.
final int statePosition; final int statePosition;
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
+ CoordinateUtils.x(mCoordinates); + CoordinateUtils.x(mOriginCoords);
if (previewX < 0) { if (previewX < 0) {
previewX = 0; previewX = 0;
statePosition = STATE_LEFT; statePosition = STATE_LEFT;
@ -956,7 +965,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// The key preview is placed vertically above the top edge of the parent key with an // The key preview is placed vertically above the top edge of the parent key with an
// arbitrary offset. // arbitrary offset.
final int previewY = key.mY - previewHeight + mPreviewOffset final int previewY = key.mY - previewHeight + mPreviewOffset
+ CoordinateUtils.y(mCoordinates); + CoordinateUtils.y(mOriginCoords);
if (background != null) { if (background != null) {
final int hasMoreKeys = (key.mMoreKeys != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL; final int hasMoreKeys = (key.mMoreKeys != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL;

View File

@ -49,6 +49,7 @@ import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.keyboard.internal.KeyDrawParams; import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.TouchScreenRegulator; import com.android.inputmethod.keyboard.internal.TouchScreenRegulator;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.CoordinateUtils;
import com.android.inputmethod.latin.DebugSettings; import com.android.inputmethod.latin.DebugSettings;
import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LatinImeLogger;
@ -672,12 +673,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
mMoreKeysPanel = moreKeysPanel; mMoreKeysPanel = moreKeysPanel;
mMoreKeysPanelPointerTrackerId = tracker.mPointerId; mMoreKeysPanelPointerTrackerId = tracker.mPointerId;
final int[] lastCoords = CoordinateUtils.newInstance();
tracker.getLastCoordinates(lastCoords);
final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview(); final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview();
// The more keys keyboard is usually horizontally aligned with the center of the parent key. // The more keys keyboard is usually horizontally aligned with the center of the parent key.
// If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
// keys keyboard is placed at the touch point of the parent key. // keys keyboard is placed at the touch point of the parent key.
final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled) final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled)
? tracker.getLastX() ? CoordinateUtils.x(lastCoords)
: parentKey.mX + parentKey.mWidth / 2; : parentKey.mX + parentKey.mWidth / 2;
// The more keys keyboard is usually vertically aligned with the top edge of the parent key // The more keys keyboard is usually vertically aligned with the top edge of the parent key
// (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically
@ -687,8 +690,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
final int pointY = parentKey.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset; final int pointY = parentKey.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset;
moreKeysPanel.showMoreKeysPanel( moreKeysPanel.showMoreKeysPanel(
this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener); this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener);
final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); final int translatedX = moreKeysPanel.translateX(CoordinateUtils.x(lastCoords));
final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); final int translatedY = moreKeysPanel.translateY(CoordinateUtils.y(lastCoords));
tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel); tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
dimEntireKeyboard(true); dimEntireKeyboard(true);
return true; return true;
@ -788,10 +791,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
} else if (pointerCount == 2 && oldPointerCount == 1) { } else if (pointerCount == 2 && oldPointerCount == 1) {
// Single-touch to multi-touch transition. // Single-touch to multi-touch transition.
// Send an up event for the last pointer. // Send an up event for the last pointer.
final int lastX = tracker.getLastX(); final int[] lastCoords = CoordinateUtils.newInstance();
final int lastY = tracker.getLastY(); mOldKey = tracker.getKeyOn(
mOldKey = tracker.getKeyOn(lastX, lastY); CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords));
tracker.onUpEvent(lastX, lastY, eventTime); tracker.onUpEvent(
CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords), eventTime);
} else if (pointerCount == 1 && oldPointerCount == 1) { } else if (pointerCount == 1 && oldPointerCount == 1) {
tracker.processMotionEvent(action, x, y, eventTime, this); tracker.processMotionEvent(action, x, y, eventTime, this);
} else { } else {

View File

@ -28,6 +28,7 @@ import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.CoordinateUtils;
import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
@ -80,6 +81,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
public void invalidateKey(Key key); public void invalidateKey(Key key);
public void showKeyPreview(PointerTracker tracker); public void showKeyPreview(PointerTracker tracker);
public void dismissKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker);
public void showSlidingKeyInputPreview(PointerTracker tracker);
public void dismissSlidingKeyInputPreview();
public void showGesturePreviewTrail(PointerTracker tracker, boolean isOldestTracker); public void showGesturePreviewTrail(PointerTracker tracker, boolean isOldestTracker);
} }
@ -296,6 +299,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
// The position and time at which first down event occurred. // The position and time at which first down event occurred.
private long mDownTime; private long mDownTime;
private int[] mDownCoordinates = CoordinateUtils.newInstance();
private long mUpTime; private long mUpTime;
// The current key where this pointer is. // The current key where this pointer is.
@ -540,6 +544,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
return mIsInSlidingKeyInput; return mIsInSlidingKeyInput;
} }
public boolean isInSlidingKeyInputFromModifier() {
return mIsInSlidingKeyInputFromModifier;
}
public Key getKey() { public Key getKey() {
return mCurrentKey; return mCurrentKey;
} }
@ -642,20 +650,21 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
return mGestureStrokeWithPreviewPoints; return mGestureStrokeWithPreviewPoints;
} }
public int getLastX() { public void getLastCoordinates(final int[] outCoords) {
return mLastX; CoordinateUtils.set(outCoords, mLastX, mLastY);
}
public int getLastY() {
return mLastY;
} }
public long getDownTime() { public long getDownTime() {
return mDownTime; return mDownTime;
} }
public void getDownCoordinates(final int[] outCoords) {
CoordinateUtils.copy(outCoords, mDownCoordinates);
}
private Key onDownKey(final int x, final int y, final long eventTime) { private Key onDownKey(final int x, final int y, final long eventTime) {
mDownTime = eventTime; mDownTime = eventTime;
CoordinateUtils.set(mDownCoordinates, x, y);
mBogusMoveEventDetector.onDownKey(); mBogusMoveEventDetector.onDownKey();
return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
} }
@ -721,6 +730,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (key != null) { if (key != null) {
updateBatchInput(eventTime); updateBatchInput(eventTime);
} }
if (mIsTrackingCanceled) {
return;
}
mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this));
} }
@ -759,6 +771,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
} }
} }
} }
if (mIsTrackingCanceled) {
return;
}
mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this));
} }
@ -867,6 +882,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
private void resetSlidingKeyInput() { private void resetSlidingKeyInput() {
mIsInSlidingKeyInput = false; mIsInSlidingKeyInput = false;
mIsInSlidingKeyInputFromModifier = false; mIsInSlidingKeyInputFromModifier = false;
mDrawingProxy.dismissSlidingKeyInputPreview();
} }
private void onGestureMoveEvent(final int x, final int y, final long eventTime, private void onGestureMoveEvent(final int x, final int y, final long eventTime,
@ -1061,6 +1077,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
slideOutFromOldKey(oldKey, x, y); slideOutFromOldKey(oldKey, x, y);
} }
} }
mDrawingProxy.showSlidingKeyInputPreview(this);
} }
public void onUpEvent(final int x, final int y, final long eventTime) { public void onUpEvent(final int x, final int y, final long eventTime) {
@ -1087,7 +1104,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
@Override @Override
public void onPhantomUpEvent(final long eventTime) { public void onPhantomUpEvent(final long eventTime) {
if (DEBUG_EVENT) { if (DEBUG_EVENT) {
printTouchEvent("onPhntEvent:", getLastX(), getLastY(), eventTime); printTouchEvent("onPhntEvent:", mLastX, mLastY, eventTime);
} }
onUpEventInternal(eventTime); onUpEventInternal(eventTime);
cancelTracking(); cancelTracking();
@ -1134,6 +1151,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
} }
public void onLongPressed() { public void onLongPressed() {
resetSlidingKeyInput();
cancelTracking(); cancelTracking();
setReleasedKeyGraphics(mCurrentKey); setReleasedKeyGraphics(mCurrentKey);
sPointerTrackerQueue.remove(this); sPointerTrackerQueue.remove(this);

View File

@ -99,6 +99,7 @@ public final class ProximityInfo {
JniUtils.loadNativeLibrary(); JniUtils.loadNativeLibrary();
} }
// TODO: Stop passing proximityCharsArray
private native long setProximityInfoNative( private native long setProximityInfoNative(
String locale, int maxProximityCharsSize, int displayWidth, String locale, int maxProximityCharsSize, int displayWidth,
int displayHeight, int gridWidth, int gridHeight, int displayHeight, int gridWidth, int gridHeight,
@ -109,22 +110,56 @@ public final class ProximityInfo {
private native void releaseProximityInfoNative(long nativeProximityInfo); private native void releaseProximityInfoNative(long nativeProximityInfo);
private final long createNativeProximityInfo( private static boolean needsProximityInfo(final Key key) {
final TouchPositionCorrection touchPositionCorrection) { // Don't include special keys into ProximityInfo.
return key.mCode >= Constants.CODE_SPACE;
}
private static int getProximityInfoKeysCount(final Key[] keys) {
int count = 0;
for (final Key key : keys) {
if (needsProximityInfo(key)) {
count++;
}
}
return count;
}
private long createNativeProximityInfo(final TouchPositionCorrection touchPositionCorrection) {
final Key[][] gridNeighborKeys = mGridNeighbors; final Key[][] gridNeighborKeys = mGridNeighbors;
final int keyboardWidth = mKeyboardMinWidth;
final int keyboardHeight = mKeyboardHeight;
final Key[] keys = mKeys;
final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE); Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE);
for (int i = 0; i < mGridSize; ++i) { for (int i = 0; i < mGridSize; ++i) {
final int proximityCharsLength = gridNeighborKeys[i].length; final int proximityCharsLength = gridNeighborKeys[i].length;
int infoIndex = i * MAX_PROXIMITY_CHARS_SIZE;
for (int j = 0; j < proximityCharsLength; ++j) { for (int j = 0; j < proximityCharsLength; ++j) {
proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] = final Key neighborKey = gridNeighborKeys[i][j];
gridNeighborKeys[i][j].mCode; // Excluding from proximityCharsArray
if (!needsProximityInfo(neighborKey)) {
continue;
}
proximityCharsArray[infoIndex] = neighborKey.mCode;
infoIndex++;
} }
} }
final int keyCount = keys.length; if (DEBUG) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < mGridSize; i++) {
sb.setLength(0);
for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; j++) {
final int code = proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j];
if (code == Constants.NOT_A_CODE) {
break;
}
if (sb.length() > 0) sb.append(" ");
sb.append(Constants.printableCode(code));
}
Log.d(TAG, "proxmityChars["+i+"]: " + sb);
}
}
final Key[] keys = mKeys;
final int keyCount = getProximityInfoKeysCount(keys);
final int[] keyXCoordinates = new int[keyCount]; final int[] keyXCoordinates = new int[keyCount];
final int[] keyYCoordinates = new int[keyCount]; final int[] keyYCoordinates = new int[keyCount];
final int[] keyWidths = new int[keyCount]; final int[] keyWidths = new int[keyCount];
@ -134,13 +169,18 @@ public final class ProximityInfo {
final float[] sweetSpotCenterYs; final float[] sweetSpotCenterYs;
final float[] sweetSpotRadii; final float[] sweetSpotRadii;
for (int i = 0; i < keyCount; ++i) { for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) {
final Key key = keys[i]; final Key key = keys[keyIndex];
keyXCoordinates[i] = key.mX; // Excluding from key coordinate arrays
keyYCoordinates[i] = key.mY; if (!needsProximityInfo(key)) {
keyWidths[i] = key.mWidth; continue;
keyHeights[i] = key.mHeight; }
keyCharCodes[i] = key.mCode; keyXCoordinates[infoIndex] = key.mX;
keyYCoordinates[infoIndex] = key.mY;
keyWidths[infoIndex] = key.mWidth;
keyHeights[infoIndex] = key.mHeight;
keyCharCodes[infoIndex] = key.mCode;
infoIndex++;
} }
if (touchPositionCorrection != null && touchPositionCorrection.isValid()) { if (touchPositionCorrection != null && touchPositionCorrection.isValid()) {
@ -153,28 +193,36 @@ public final class ProximityInfo {
final int rows = touchPositionCorrection.getRows(); final int rows = touchPositionCorrection.getRows();
final float defaultRadius = DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS final float defaultRadius = DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS
* (float)Math.hypot(mMostCommonKeyWidth, mMostCommonKeyHeight); * (float)Math.hypot(mMostCommonKeyWidth, mMostCommonKeyHeight);
for (int i = 0; i < keyCount; i++) { for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) {
final Key key = keys[i]; final Key key = keys[keyIndex];
// Excluding from touch position correction arrays
if (!needsProximityInfo(key)) {
continue;
}
final Rect hitBox = key.mHitBox; final Rect hitBox = key.mHitBox;
sweetSpotCenterXs[i] = hitBox.exactCenterX(); sweetSpotCenterXs[infoIndex] = hitBox.exactCenterX();
sweetSpotCenterYs[i] = hitBox.exactCenterY(); sweetSpotCenterYs[infoIndex] = hitBox.exactCenterY();
sweetSpotRadii[i] = defaultRadius; sweetSpotRadii[infoIndex] = defaultRadius;
final int row = hitBox.top / mMostCommonKeyHeight; final int row = hitBox.top / mMostCommonKeyHeight;
if (row < rows) { if (row < rows) {
final int hitBoxWidth = hitBox.width(); final int hitBoxWidth = hitBox.width();
final int hitBoxHeight = hitBox.height(); final int hitBoxHeight = hitBox.height();
final float hitBoxDiagonal = (float)Math.hypot(hitBoxWidth, hitBoxHeight); final float hitBoxDiagonal = (float)Math.hypot(hitBoxWidth, hitBoxHeight);
sweetSpotCenterXs[i] += touchPositionCorrection.getX(row) * hitBoxWidth; sweetSpotCenterXs[infoIndex] +=
sweetSpotCenterYs[i] += touchPositionCorrection.getY(row) * hitBoxHeight; touchPositionCorrection.getX(row) * hitBoxWidth;
sweetSpotRadii[i] = touchPositionCorrection.getRadius(row) * hitBoxDiagonal; sweetSpotCenterYs[infoIndex] +=
touchPositionCorrection.getY(row) * hitBoxHeight;
sweetSpotRadii[infoIndex] =
touchPositionCorrection.getRadius(row) * hitBoxDiagonal;
} }
if (DEBUG) { if (DEBUG) {
Log.d(TAG, String.format( Log.d(TAG, String.format(
" [%2d] row=%d x/y/r=%7.2f/%7.2f/%5.2f %s code=%s", i, row, " [%2d] row=%d x/y/r=%7.2f/%7.2f/%5.2f %s code=%s", infoIndex, row,
sweetSpotCenterXs[i], sweetSpotCenterYs[i], sweetSpotRadii[i], sweetSpotCenterXs[infoIndex], sweetSpotCenterYs[infoIndex],
(row < rows ? "correct" : "default"), sweetSpotRadii[infoIndex], (row < rows ? "correct" : "default"),
Constants.printableCode(key.mCode))); Constants.printableCode(key.mCode)));
} }
infoIndex++;
} }
} else { } else {
sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null;
@ -183,11 +231,11 @@ public final class ProximityInfo {
} }
} }
// TODO: Stop passing proximityCharsArray
return setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, return setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE,
keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, mKeyboardMinWidth, mKeyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth,
proximityCharsArray, proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths,
keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
} }
public long getNativeProximityInfo() { public long getNativeProximityInfo() {

View File

@ -36,6 +36,7 @@ import android.widget.RelativeLayout;
import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.Params; import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.Params;
import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.CoordinateUtils;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
@ -47,8 +48,7 @@ public final class PreviewPlacerView extends RelativeLayout {
private final float mGestureFloatingPreviewVerticalPadding; private final float mGestureFloatingPreviewVerticalPadding;
private final float mGestureFloatingPreviewRoundRadius; private final float mGestureFloatingPreviewRoundRadius;
private int mKeyboardViewOriginX; private final int[] mKeyboardViewOrigin = CoordinateUtils.newInstance();
private int mKeyboardViewOriginY;
private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails = private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
CollectionUtils.newSparseArray(); CollectionUtils.newSparseArray();
@ -68,11 +68,14 @@ public final class PreviewPlacerView extends RelativeLayout {
private final int mGestureFloatingPreviewTextHeight; private final int mGestureFloatingPreviewTextHeight;
// {@link RectF} is needed for {@link Canvas#drawRoundRect(RectF, float, float, Paint)}. // {@link RectF} is needed for {@link Canvas#drawRoundRect(RectF, float, float, Paint)}.
private final RectF mGestureFloatingPreviewRectangle = new RectF(); private final RectF mGestureFloatingPreviewRectangle = new RectF();
private int mLastPointerX; private final int[] mLastPointerCoords = CoordinateUtils.newInstance();
private int mLastPointerY;
private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' }; private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' };
private boolean mDrawsGestureFloatingPreviewText; private boolean mDrawsGestureFloatingPreviewText;
private boolean mShowSlidingKeyInputPreview;
private final int[] mRubberBandFrom = CoordinateUtils.newInstance();
private final int[] mRubberBandTo = CoordinateUtils.newInstance();
private final DrawingHandler mDrawingHandler; private final DrawingHandler mDrawingHandler;
private static final class DrawingHandler extends StaticInnerHandlerWrapper<PreviewPlacerView> { private static final class DrawingHandler extends StaticInnerHandlerWrapper<PreviewPlacerView> {
@ -168,9 +171,8 @@ public final class PreviewPlacerView extends RelativeLayout {
setLayerType(LAYER_TYPE_HARDWARE, layerPaint); setLayerType(LAYER_TYPE_HARDWARE, layerPaint);
} }
public void setKeyboardViewGeometry(final int x, final int y, final int w, final int h) { public void setKeyboardViewGeometry(final int[] originCoords, final int w, final int h) {
mKeyboardViewOriginX = x; CoordinateUtils.copy(mKeyboardViewOrigin, originCoords);
mKeyboardViewOriginY = y;
mOffscreenOffsetY = (int)(h * GestureStroke.EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO); mOffscreenOffsetY = (int)(h * GestureStroke.EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO);
mOffscreenWidth = w; mOffscreenWidth = w;
mOffscreenHeight = mOffscreenOffsetY + h; mOffscreenHeight = mOffscreenOffsetY + h;
@ -186,8 +188,7 @@ public final class PreviewPlacerView extends RelativeLayout {
final boolean needsToUpdateLastPointer = final boolean needsToUpdateLastPointer =
isOldestTracker && mDrawsGestureFloatingPreviewText; isOldestTracker && mDrawsGestureFloatingPreviewText;
if (needsToUpdateLastPointer) { if (needsToUpdateLastPointer) {
mLastPointerX = tracker.getLastX(); tracker.getLastCoordinates(mLastPointerCoords);
mLastPointerY = tracker.getLastY();
} }
if (mDrawsGesturePreviewTrail) { if (mDrawsGesturePreviewTrail) {
@ -208,6 +209,21 @@ public final class PreviewPlacerView extends RelativeLayout {
} }
} }
public void showSlidingKeyInputPreview(final PointerTracker tracker) {
if (!tracker.isInSlidingKeyInputFromModifier()) {
mShowSlidingKeyInputPreview = false;
return;
}
tracker.getDownCoordinates(mRubberBandFrom);
tracker.getLastCoordinates(mRubberBandTo);
mShowSlidingKeyInputPreview = true;
invalidate();
}
public void dismissSlidingKeyInputPreview() {
mShowSlidingKeyInputPreview = false;
}
@Override @Override
protected void onDetachedFromWindow() { protected void onDetachedFromWindow() {
freeOffscreenBuffer(); freeOffscreenBuffer();
@ -234,6 +250,8 @@ public final class PreviewPlacerView extends RelativeLayout {
@Override @Override
public void onDraw(final Canvas canvas) { public void onDraw(final Canvas canvas) {
super.onDraw(canvas); super.onDraw(canvas);
final int originX = CoordinateUtils.x(mKeyboardViewOrigin);
final int originY = CoordinateUtils.y(mKeyboardViewOrigin);
if (mDrawsGesturePreviewTrail) { if (mDrawsGesturePreviewTrail) {
mayAllocateOffscreenBuffer(); mayAllocateOffscreenBuffer();
// Draw gesture trails to offscreen buffer. // Draw gesture trails to offscreen buffer.
@ -241,11 +259,11 @@ public final class PreviewPlacerView extends RelativeLayout {
mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect); mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect);
// Transfer offscreen buffer to screen. // Transfer offscreen buffer to screen.
if (!mOffscreenDirtyRect.isEmpty()) { if (!mOffscreenDirtyRect.isEmpty()) {
final int offsetY = mKeyboardViewOriginY - mOffscreenOffsetY; final int offsetY = originY - mOffscreenOffsetY;
canvas.translate(mKeyboardViewOriginX, offsetY); canvas.translate(originX, offsetY);
canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect, canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
mGesturePaint); mGesturePaint);
canvas.translate(-mKeyboardViewOriginX, -offsetY); canvas.translate(-originX, -offsetY);
// Note: Defer clearing the dirty rectangle here because we will get cleared // Note: Defer clearing the dirty rectangle here because we will get cleared
// rectangle on the canvas. // rectangle on the canvas.
} }
@ -254,9 +272,14 @@ public final class PreviewPlacerView extends RelativeLayout {
} }
} }
if (mDrawsGestureFloatingPreviewText) { if (mDrawsGestureFloatingPreviewText) {
canvas.translate(mKeyboardViewOriginX, mKeyboardViewOriginY); canvas.translate(originX, originY);
drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText); drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
canvas.translate(-mKeyboardViewOriginX, -mKeyboardViewOriginY); canvas.translate(-originX, -originY);
}
if (mShowSlidingKeyInputPreview) {
canvas.translate(originX, originY);
drawSlidingKeyInputPreview(canvas);
canvas.translate(-originX, -originY);
} }
} }
@ -317,8 +340,6 @@ public final class PreviewPlacerView extends RelativeLayout {
final Paint paint = mTextPaint; final Paint paint = mTextPaint;
final RectF rectangle = mGestureFloatingPreviewRectangle; final RectF rectangle = mGestureFloatingPreviewRectangle;
// TODO: Figure out how we should deal with the floating preview text with multiple moving
// fingers.
// Paint the round rectangle background. // Paint the round rectangle background.
final int textHeight = mGestureFloatingPreviewTextHeight; final int textHeight = mGestureFloatingPreviewTextHeight;
@ -328,9 +349,11 @@ public final class PreviewPlacerView extends RelativeLayout {
final float rectWidth = textWidth + hPad * 2.0f; final float rectWidth = textWidth + hPad * 2.0f;
final float rectHeight = textHeight + vPad * 2.0f; final float rectHeight = textHeight + vPad * 2.0f;
final int canvasWidth = canvas.getWidth(); final int canvasWidth = canvas.getWidth();
final float rectX = Math.min(Math.max(mLastPointerX - rectWidth / 2.0f, 0.0f), final float rectX = Math.min(
Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f),
canvasWidth - rectWidth); canvasWidth - rectWidth);
final float rectY = mLastPointerY - mGestureFloatingPreviewTextOffset - rectHeight; final float rectY = CoordinateUtils.y(mLastPointerCoords)
- mGestureFloatingPreviewTextOffset - rectHeight;
rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight); rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
final float round = mGestureFloatingPreviewRoundRadius; final float round = mGestureFloatingPreviewRoundRadius;
paint.setColor(mGestureFloatingPreviewColor); paint.setColor(mGestureFloatingPreviewColor);
@ -341,4 +364,8 @@ public final class PreviewPlacerView extends RelativeLayout {
final float textY = rectY + vPad + textHeight; final float textY = rectY + vPad + textHeight;
canvas.drawText(gestureFloatingPreviewText, textX, textY, paint); canvas.drawText(gestureFloatingPreviewText, textX, textY, paint);
} }
private void drawSlidingKeyInputPreview(final Canvas canvas) {
// TODO: Implement rubber band preview
}
} }

View File

@ -36,4 +36,14 @@ public final class CoordinateUtils {
public static int y(final int[] coords) { public static int y(final int[] coords) {
return coords[INDEX_Y]; return coords[INDEX_Y];
} }
public static void set(final int[] coords, final int x, final int y) {
coords[INDEX_X] = x;
coords[INDEX_Y] = y;
}
public static void copy(final int[] destination, final int[] source) {
destination[INDEX_X] = source[INDEX_X];
destination[INDEX_Y] = source[INDEX_Y];
}
} }

View File

@ -1177,6 +1177,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private boolean maybeDoubleSpace() { private boolean maybeDoubleSpace() {
if (!mCurrentSettings.mCorrectionEnabled) return false; if (!mCurrentSettings.mCorrectionEnabled) return false;
if (!mCurrentSettings.mUseDoubleSpacePeriod) return false;
if (!mHandler.isAcceptingDoubleSpaces()) return false; if (!mHandler.isAcceptingDoubleSpaces()) return false;
final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0); final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3 if (lastThree != null && lastThree.length() == 3

View File

@ -60,6 +60,8 @@ public final class Settings extends InputMethodSettingsFragment
"last_user_dictionary_write_time"; "last_user_dictionary_write_time";
public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD =
"pref_key_use_double_space_period";
public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY = public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
"pref_show_language_switch_key"; "pref_show_language_switch_key";
public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =

View File

@ -75,6 +75,7 @@ public final class SettingsValues {
@SuppressWarnings("unused") // TODO: Use this @SuppressWarnings("unused") // TODO: Use this
private final String mKeyPreviewPopupDismissDelayRawValue; private final String mKeyPreviewPopupDismissDelayRawValue;
public final boolean mUseContactsDict; public final boolean mUseContactsDict;
public final boolean mUseDoubleSpacePeriod;
// Use bigrams to predict the next word when there is no input for it yet // Use bigrams to predict the next word when there is no input for it yet
public final boolean mBigramPredictionEnabled; public final boolean mBigramPredictionEnabled;
@SuppressWarnings("unused") // TODO: Use this @SuppressWarnings("unused") // TODO: Use this
@ -154,6 +155,7 @@ public final class SettingsValues {
Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout))); Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout)));
mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true);
mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue); mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res); mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res);
mVibrationDurationSettingsRawValue = mVibrationDurationSettingsRawValue =

View File

@ -438,15 +438,23 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE; if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
final int len = text.length(); final int len = text.length();
int capsCount = 1; int capsCount = 1;
int letterCount = 1;
for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) { for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
if (1 != capsCount && i != capsCount) break; if (1 != capsCount && letterCount != capsCount) break;
if (Character.isUpperCase(text.codePointAt(i))) ++capsCount; final int codePoint = text.codePointAt(i);
if (Character.isUpperCase(codePoint)) {
++capsCount;
++letterCount;
} else if (Character.isLetter(codePoint)) {
// We need to discount non-letters since they may not be upper-case, but may
// still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
++letterCount;
}
} }
// We know the first char is upper case. So we want to test if either everything // We know the first char is upper case. So we want to test if either every letter other
// else is lower case, or if everything else is upper case. If the string is // than the first is lower case, or if they are all upper case. If the string is exactly
// exactly one char long, then we will arrive here with capsCount 1, and this is // one char long, then we will arrive here with letterCount 1, and this is correct, too.
// correct, too.
if (1 == capsCount) return CAPITALIZE_FIRST; if (1 == capsCount) return CAPITALIZE_FIRST;
return (len == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE); return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
} }
} }

View File

@ -28,9 +28,11 @@ import android.view.textservice.TextInfo;
import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer; import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer;
import java.util.ArrayList; import java.util.ArrayList;
@ -188,6 +190,35 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
return (letterCount * 4 < length * 3); return (letterCount * 4 < length * 3);
} }
/**
* Helper method to test valid capitalizations of a word.
*
* If the "text" is lower-case, we test only the exact string.
* If the "Text" is capitalized, we test the exact string "Text" and the lower-cased
* version of it "text".
* If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased
* version of it "text" and the capitalized version of it "Text".
*/
private boolean isInDictForAnyCapitalization(final Dictionary dict, final String text,
final int capitalizeType) {
// If the word is in there as is, then it's in the dictionary. If not, we'll test lower
// case versions, but only if the word is not already all-lower case or mixed case.
if (dict.isValidWord(text)) return true;
if (AndroidSpellCheckerService.CAPITALIZE_NONE == capitalizeType) return false;
// If we come here, we have a capitalized word (either First- or All-).
// Downcase the word and look it up again. If the word is only capitalized, we
// tested all possibilities, so if it's still negative we can return false.
final String lowerCaseText = text.toLowerCase(mLocale);
if (dict.isValidWord(lowerCaseText)) return true;
if (AndroidSpellCheckerService.CAPITALIZE_FIRST == capitalizeType) return false;
// If the lower case version is not in the dictionary, it's still possible
// that we have an all-caps version of a word that needs to be capitalized
// according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans".
return dict.isValidWord(StringUtils.toTitleCase(lowerCaseText, mLocale));
}
// Note : this must be reentrant // Note : this must be reentrant
/** /**
* Gets a list of suggestions for a specific string. This returns a list of possible * Gets a list of suggestions for a specific string. This returns a list of possible
@ -272,13 +303,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0, suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0,
suggestionStr.length(), suggestion.mScore); suggestionStr.length(), suggestion.mScore);
} }
isInDict = dictInfo.mDictionary.isValidWord(text); isInDict = isInDictForAnyCapitalization(dictInfo.mDictionary, text, capitalizeType);
if (!isInDict && AndroidSpellCheckerService.CAPITALIZE_NONE != capitalizeType) {
// We want to test the word again if it's all caps or first caps only.
// If it's fully down, we already tested it, if it's mixed case, we don't
// want to test a lowercase version of it.
isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
}
} finally { } finally {
if (null != dictInfo) { if (null != dictInfo) {
if (!mDictionaryPool.offer(dictInfo)) { if (!mDictionaryPool.offer(dictInfo)) {

View File

@ -925,18 +925,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
public static void latinIME_onWindowHidden(final int savedSelectionStart, public static void latinIME_onWindowHidden(final int savedSelectionStart,
final int savedSelectionEnd, final InputConnection ic) { final int savedSelectionEnd, final InputConnection ic) {
if (ic != null) { if (ic != null) {
// Capture the TextView contents. This will trigger onUpdateSelection(), so we
// set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called,
// it can tell that it was generated by the logging code, and not by the user, and
// therefore keep user-visible state as is.
ic.beginBatchEdit();
ic.performContextMenuAction(android.R.id.selectAll);
CharSequence charSequence = ic.getSelectedText(0);
ic.setSelection(savedSelectionStart, savedSelectionEnd);
ic.endBatchEdit();
sLatinIMEExpectingUpdateSelection = true;
final Object[] values = new Object[2]; final Object[] values = new Object[2];
if (OUTPUT_ENTIRE_BUFFER) { if (OUTPUT_ENTIRE_BUFFER) {
// Capture the TextView contents. This will trigger onUpdateSelection(), so we
// set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called,
// it can tell that it was generated by the logging code, and not by the user, and
// therefore keep user-visible state as is.
ic.beginBatchEdit();
ic.performContextMenuAction(android.R.id.selectAll);
CharSequence charSequence = ic.getSelectedText(0);
if (savedSelectionStart != -1 && savedSelectionEnd != -1) {
ic.setSelection(savedSelectionStart, savedSelectionEnd);
}
ic.endBatchEdit();
sLatinIMEExpectingUpdateSelection = true;
if (TextUtils.isEmpty(charSequence)) { if (TextUtils.isEmpty(charSequence)) {
values[0] = false; values[0] = false;
values[1] = ""; values[1] = "";

View File

@ -21,23 +21,23 @@ namespace latinime {
// TODO: Have proximity character informations in each language's binary dictionary. // TODO: Have proximity character informations in each language's binary dictionary.
const char *AdditionalProximityChars::LOCALE_EN_US = "en"; const char *AdditionalProximityChars::LOCALE_EN_US = "en";
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = { const int AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = {
'e', 'i', 'o', 'u' 'e', 'i', 'o', 'u'
}; };
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_E[EN_US_ADDITIONAL_E_SIZE] = { const int AdditionalProximityChars::EN_US_ADDITIONAL_E[EN_US_ADDITIONAL_E_SIZE] = {
'a', 'i', 'o', 'u' 'a', 'i', 'o', 'u'
}; };
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_I[EN_US_ADDITIONAL_I_SIZE] = { const int AdditionalProximityChars::EN_US_ADDITIONAL_I[EN_US_ADDITIONAL_I_SIZE] = {
'a', 'e', 'o', 'u' 'a', 'e', 'o', 'u'
}; };
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_O[EN_US_ADDITIONAL_O_SIZE] = { const int AdditionalProximityChars::EN_US_ADDITIONAL_O[EN_US_ADDITIONAL_O_SIZE] = {
'a', 'e', 'i', 'u' 'a', 'e', 'i', 'u'
}; };
const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_U[EN_US_ADDITIONAL_U_SIZE] = { const int AdditionalProximityChars::EN_US_ADDITIONAL_U[EN_US_ADDITIONAL_U_SIZE] = {
'a', 'e', 'i', 'o' 'a', 'e', 'i', 'o'
}; };
} // namespace latinime } // namespace latinime

View File

@ -18,7 +18,6 @@
#define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H #define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
#include <cstring> #include <cstring>
#include <stdint.h>
#include "defines.h" #include "defines.h"
@ -29,15 +28,15 @@ class AdditionalProximityChars {
DISALLOW_IMPLICIT_CONSTRUCTORS(AdditionalProximityChars); DISALLOW_IMPLICIT_CONSTRUCTORS(AdditionalProximityChars);
static const char *LOCALE_EN_US; static const char *LOCALE_EN_US;
static const int EN_US_ADDITIONAL_A_SIZE = 4; static const int EN_US_ADDITIONAL_A_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_A[]; static const int EN_US_ADDITIONAL_A[];
static const int EN_US_ADDITIONAL_E_SIZE = 4; static const int EN_US_ADDITIONAL_E_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_E[]; static const int EN_US_ADDITIONAL_E[];
static const int EN_US_ADDITIONAL_I_SIZE = 4; static const int EN_US_ADDITIONAL_I_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_I[]; static const int EN_US_ADDITIONAL_I[];
static const int EN_US_ADDITIONAL_O_SIZE = 4; static const int EN_US_ADDITIONAL_O_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_O[]; static const int EN_US_ADDITIONAL_O[];
static const int EN_US_ADDITIONAL_U_SIZE = 4; static const int EN_US_ADDITIONAL_U_SIZE = 4;
static const int32_t EN_US_ADDITIONAL_U[]; static const int EN_US_ADDITIONAL_U[];
AK_FORCE_INLINE static bool isEnLocale(const char *localeStr) { AK_FORCE_INLINE static bool isEnLocale(const char *localeStr) {
const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US); const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US);
@ -46,7 +45,7 @@ class AdditionalProximityChars {
} }
public: public:
static int getAdditionalCharsSize(const char *localeStr, const int32_t c) { static int getAdditionalCharsSize(const char *localeStr, const int c) {
if (!isEnLocale(localeStr)) { if (!isEnLocale(localeStr)) {
return 0; return 0;
} }
@ -66,7 +65,7 @@ class AdditionalProximityChars {
} }
} }
static const int32_t *getAdditionalChars(const char *localeStr, const int32_t c) { static const int *getAdditionalChars(const char *localeStr, const int c) {
if (!isEnLocale(localeStr)) { if (!isEnLocale(localeStr)) {
return 0; return 0;
} }

View File

@ -146,8 +146,8 @@ int BigramDictionary::getBigrams(const int *prevWord, int prevWordLength, int *i
// Returns a pointer to the start of the bigram list. // Returns a pointer to the start of the bigram list.
// If the word is not found or has no bigrams, this function returns 0. // If the word is not found or has no bigrams, this function returns 0.
int BigramDictionary::getBigramListPositionForWord(const int32_t *prevWord, int BigramDictionary::getBigramListPositionForWord(const int *prevWord, const int prevWordLength,
const int prevWordLength, const bool forceLowerCaseSearch) const { const bool forceLowerCaseSearch) const {
if (0 >= prevWordLength) return 0; if (0 >= prevWordLength) return 0;
const uint8_t *const root = DICT; const uint8_t *const root = DICT;
int pos = BinaryFormat::getTerminalPosition(root, prevWord, prevWordLength, int pos = BinaryFormat::getTerminalPosition(root, prevWord, prevWordLength,
@ -167,7 +167,7 @@ int BigramDictionary::getBigramListPositionForWord(const int32_t *prevWord,
return pos; return pos;
} }
void BigramDictionary::fillBigramAddressToFrequencyMapAndFilter(const int32_t *prevWord, void BigramDictionary::fillBigramAddressToFrequencyMapAndFilter(const int *prevWord,
const int prevWordLength, std::map<int, int> *map, uint8_t *filter) const { const int prevWordLength, std::map<int, int> *map, uint8_t *filter) const {
memset(filter, 0, BIGRAM_FILTER_BYTE_SIZE); memset(filter, 0, BIGRAM_FILTER_BYTE_SIZE);
const uint8_t *const root = DICT; const uint8_t *const root = DICT;
@ -207,7 +207,7 @@ bool BigramDictionary::checkFirstCharacter(int *word, int *inputCodes) const {
return false; return false;
} }
bool BigramDictionary::isValidBigram(const int32_t *word1, int length1, const int32_t *word2, bool BigramDictionary::isValidBigram(const int *word1, int length1, const int *word2,
int length2) const { int length2) const {
const uint8_t *const root = DICT; const uint8_t *const root = DICT;
int pos = getBigramListPositionForWord(word1, length1, false /* forceLowerCaseSearch */); int pos = getBigramListPositionForWord(word1, length1, false /* forceLowerCaseSearch */);

View File

@ -201,7 +201,6 @@ inline void BinaryFormat::readHeaderValue(const uint8_t *const dict, const char
outValue[outValueIndex++] = codePoint; outValue[outValueIndex++] = codePoint;
codePoint = getCodePointAndForwardPointer(dict, &index); codePoint = getCodePointAndForwardPointer(dict, &index);
} }
if (outValueIndex < outValueIndex) outValue[outValueIndex] = 0;
// Finished copying. Break to go to the termination code. // Finished copying. Break to go to the termination code.
break; break;
} }
@ -219,7 +218,6 @@ inline void BinaryFormat::readHeaderValue(const uint8_t *const dict, const char
// Put a terminator 0 if possible at all (always unless outValueSize is <= 0) // Put a terminator 0 if possible at all (always unless outValueSize is <= 0)
if (outValueIndex >= outValueSize) outValueIndex = outValueSize - 1; if (outValueIndex >= outValueSize) outValueIndex = outValueSize - 1;
if (outValueIndex >= 0) outValue[outValueIndex] = 0; if (outValueIndex >= 0) outValue[outValueIndex] = 0;
return;
} }
inline int BinaryFormat::readHeaderValueInt(const uint8_t *const dict, const char *const key) { inline int BinaryFormat::readHeaderValueInt(const uint8_t *const dict, const char *const key) {

View File

@ -28,7 +28,6 @@
namespace latinime { namespace latinime {
// TODO: Change the type of all keyCodes to uint32_t
Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int maxWordLength, Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int maxWordLength,
int maxWords, int maxPredictions) int maxWords, int maxPredictions)
: mDict(static_cast<unsigned char *>(dict)), : mDict(static_cast<unsigned char *>(dict)),
@ -81,19 +80,18 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi
} }
} }
int Dictionary::getBigrams(const int32_t *word, int length, int *codes, int codesSize, int Dictionary::getBigrams(const int *word, int length, int *codes, int codesSize,
int *outWords, int *frequencies, int *outputTypes) const { int *outWords, int *frequencies, int *outputTypes) const {
if (length <= 0) return 0; if (length <= 0) return 0;
return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies, return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies,
outputTypes); outputTypes);
} }
int Dictionary::getFrequency(const int32_t *word, int length) const { int Dictionary::getFrequency(const int *word, int length) const {
return mUnigramDictionary->getFrequency(word, length); return mUnigramDictionary->getFrequency(word, length);
} }
bool Dictionary::isValidBigram(const int32_t *word1, int length1, const int32_t *word2, bool Dictionary::isValidBigram(const int *word1, int length1, const int *word2, int length2) const {
int length2) const {
return mBigramDictionary->isValidBigram(word1, length1, word2, length2); return mBigramDictionary->isValidBigram(word1, length1, word2, length2);
} }
} // namespace latinime } // namespace latinime

View File

@ -50,11 +50,11 @@ class Dictionary {
bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices, bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices,
int *outputTypes) const; int *outputTypes) const;
int getBigrams(const int32_t *word, int length, int *codes, int codesSize, int *outWords, int getBigrams(const int *word, int length, int *codes, int codesSize, int *outWords,
int *frequencies, int *outputTypes) const; int *frequencies, int *outputTypes) const;
int getFrequency(const int32_t *word, int length) const; int getFrequency(const int *word, int length) const;
bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const; bool isValidBigram(const int *word1, int length1, const int *word2, int length2) const;
const uint8_t *getDict() const { // required to release dictionary buffer const uint8_t *getDict() const { // required to release dictionary buffer
return mDict; return mDict;
} }

View File

@ -66,7 +66,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma
HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
&& keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
&& sweetSpotCenterYs && sweetSpotRadii), && sweetSpotCenterYs && sweetSpotRadii),
mProximityCharsArray(new int32_t[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE
/* proximityGridLength */]), /* proximityGridLength */]),
mCodeToKeyMap() { mCodeToKeyMap() {
const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
@ -115,7 +115,7 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
if (DEBUG_PROXIMITY_INFO) { if (DEBUG_PROXIMITY_INFO) {
AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y); AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
} }
int32_t *proximityCharsArray = mProximityCharsArray; int *proximityCharsArray = mProximityCharsArray;
for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
if (DEBUG_PROXIMITY_INFO) { if (DEBUG_PROXIMITY_INFO) {
AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]); AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
@ -163,14 +163,14 @@ int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int
} }
void ProximityInfo::calculateNearbyKeyCodes( void ProximityInfo::calculateNearbyKeyCodes(
const int x, const int y, const int32_t primaryKey, int *inputCodes) const { const int x, const int y, const int primaryKey, int *inputCodes) const {
int32_t *proximityCharsArray = mProximityCharsArray; int *proximityCharsArray = mProximityCharsArray;
int insertPos = 0; int insertPos = 0;
inputCodes[insertPos++] = primaryKey; inputCodes[insertPos++] = primaryKey;
const int startIndex = getStartIndexFromCoordinates(x, y); const int startIndex = getStartIndexFromCoordinates(x, y);
if (startIndex >= 0) { if (startIndex >= 0) {
for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
const int32_t c = proximityCharsArray[startIndex + i]; const int c = proximityCharsArray[startIndex + i];
if (c < KEYCODE_SPACE || c == primaryKey) { if (c < KEYCODE_SPACE || c == primaryKey) {
continue; continue;
} }
@ -198,13 +198,13 @@ void ProximityInfo::calculateNearbyKeyCodes(
return; return;
} }
const int32_t *additionalProximityChars = const int *additionalProximityChars =
AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey); AdditionalProximityChars::getAdditionalChars(mLocaleStr, primaryKey);
for (int j = 0; j < additionalProximitySize; ++j) { for (int j = 0; j < additionalProximitySize; ++j) {
const int32_t ac = additionalProximityChars[j]; const int ac = additionalProximityChars[j];
int k = 0; int k = 0;
for (; k < insertPos; ++k) { for (; k < insertPos; ++k) {
if (static_cast<int>(ac) == inputCodes[k]) { if (ac == inputCodes[k]) {
break; break;
} }
} }
@ -235,7 +235,7 @@ int ProximityInfo::getKeyIndexOf(const int c) const {
if (c == NOT_A_CODE_POINT) { if (c == NOT_A_CODE_POINT) {
return NOT_AN_INDEX; return NOT_AN_INDEX;
} }
const int lowerCode = static_cast<int>(toLowerCase(c)); const int lowerCode = toLowerCase(c);
hash_map_compat<int, int>::const_iterator mapPos = mCodeToKeyMap.find(lowerCode); hash_map_compat<int, int>::const_iterator mapPos = mCodeToKeyMap.find(lowerCode);
if (mapPos != mCodeToKeyMap.end()) { if (mapPos != mCodeToKeyMap.end()) {
return mapPos->second; return mapPos->second;
@ -254,7 +254,7 @@ void ProximityInfo::initializeG() {
// TODO: Optimize // TODO: Optimize
for (int i = 0; i < KEY_COUNT; ++i) { for (int i = 0; i < KEY_COUNT; ++i) {
const int code = mKeyCodePoints[i]; const int code = mKeyCodePoints[i];
const int lowerCode = static_cast<int>(toLowerCase(code)); const int lowerCode = toLowerCase(code);
mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2; mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2; mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
mCodeToKeyMap[lowerCode] = i; mCodeToKeyMap[lowerCode] = i;

View File

@ -17,8 +17,6 @@
#ifndef LATINIME_PROXIMITY_INFO_H #ifndef LATINIME_PROXIMITY_INFO_H
#define LATINIME_PROXIMITY_INFO_H #define LATINIME_PROXIMITY_INFO_H
#include <stdint.h>
#include "defines.h" #include "defines.h"
#include "hash_map_compat.h" #include "hash_map_compat.h"
#include "jni.h" #include "jni.h"
@ -59,7 +57,7 @@ class ProximityInfo {
return mSweetSpotCenterYs[keyIndex]; return mSweetSpotCenterYs[keyIndex];
} }
void calculateNearbyKeyCodes( void calculateNearbyKeyCodes(
const int x, const int y, const int32_t primaryKey, int *inputCodes) const; const int x, const int y, const int primaryKey, int *inputCodes) const;
bool hasTouchPositionCorrectionData() const { bool hasTouchPositionCorrectionData() const {
return HAS_TOUCH_POSITION_CORRECTION_DATA; return HAS_TOUCH_POSITION_CORRECTION_DATA;
@ -141,12 +139,12 @@ class ProximityInfo {
const int KEYBOARD_HEIGHT; const int KEYBOARD_HEIGHT;
const bool HAS_TOUCH_POSITION_CORRECTION_DATA; const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
char mLocaleStr[MAX_LOCALE_STRING_LENGTH]; char mLocaleStr[MAX_LOCALE_STRING_LENGTH];
int32_t *mProximityCharsArray; int *mProximityCharsArray;
int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyWidths[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyWidths[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyHeights[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyHeights[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyCodePoints[MAX_KEY_COUNT_IN_A_KEYBOARD]; int mKeyCodePoints[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD]; float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD]; float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD]; float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];