aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/values-am/strings.xml6
-rw-r--r--java/res/values-ar/strings.xml6
-rw-r--r--java/res/values-el/strings.xml6
-rw-r--r--java/res/values-fi/strings.xml6
-rw-r--r--java/res/values-it/strings.xml6
-rw-r--r--java/res/values-iw/strings.xml6
-rw-r--r--java/res/values-sv/strings.xml6
-rw-r--r--java/res/values-sw/strings.xml6
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java11
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java16
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java16
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java47
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java31
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java5
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java80
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java218
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java21
19 files changed, 339 insertions, 170 deletions
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 513c17686..7b0891f94 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"ለብቁ ተጠቃሚዎች አማራጮች"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"ወደ ሌሎች የግቤት ስልቶች ቀይር"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"የቋንቋ መቀየሪያ ቁልፍ ሌሎች የግቤት ስልቶችንም ይሸፍናል"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"የቋንቋ መቀየሪያ ቁልፍ"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"በርካታ የግቤት ቋንቋዎች ሲነቁ አሳይ"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"የቁልፍ ብቅ ባይ መዘግየትን ያስወገዳል"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"የዘገየ የለም"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ነባሪ"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index b1c7afe5a..8e7e752d0 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"خيارات للخبراء"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"التبديل إلى أسلوب إدخال آخر"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"يغطي مفتاح تبديل اللغات أساليب الإدخال الأخرى أيضًا"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"مفتاح تبديل اللغة"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"يظهر عندما يتم تمكين لغات الإدخال متعددة"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"تأخير إزالة النافذة المنبثقة الأساسية"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"بلا تأخير"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"افتراضي"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 63f65126d..4f80bd18d 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"Επιλογές για έμπειρους χρήστες"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Άλλη μέθοδος εισόδου"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Το κλειδί αλλαγής γλώσσας καλύπτει και άλλες μεθόδους εισόδου"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Πλήκτρο εναλλαγής γλώσσας"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Εμφάνιση κατά την ενεργοποίηση πολλών γλωσσών εισόδου"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Χρόνος εξαφ. αναδ. παραθ."</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Χωρίς καθυστέρ."</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Προεπιλογή"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 68f946cfa..211c3aa47 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"Valinnat asiantuntijoille"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Käytä toista syöttötapaa"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kielenvaihtonäppäin kattaa myös muut syöttötavat"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Kielenvaihtonäppäin"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Näytä, kun käytössä on useita syöttökieliä"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Näppäimen hylkäysviive"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ei viivettä"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 1567c2080..49c7b9267 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"Opzioni per esperti"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Altri metodi immissione"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Il tasto per cambiare lingua offre altri metodi di immissione"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Tasto cambio lingua"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostra quando sono attive più lingue di immissione"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ritardo eliminaz. popup tasto"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nessun ritardo"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 5b6315b71..20eed68e5 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"אפשרויות למומחים"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"עבור לשיטות קלט אחרות"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"מתג החלפת השפה מכסה גם שיטות קלט אחרות"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"מתג החלפת שפה"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"הצג כאשר מורשה שימוש בשפות קלט מרובות"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"עיכוב סגירת חלון קופץ של מקש"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ללא עיכוב"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ברירת מחדל"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 1ec59d914..8a83de6bb 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"Alternativ för experter"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Byt till annan inmatning"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Språkbytesknappen omfattar även andra inmatningsmetoder"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Knapp för att byta språk"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Visa när flera inmatningsspråk är aktiverade"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ta bort popup-fördröjning"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fördröj inte"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 453b2806b..62cc82444 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -36,10 +36,8 @@
<string name="advanced_settings_summary" msgid="4487980456152830271">"Chaguo za wataalamu"</string>
<string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Badilisha hadi kwa mbinu zingine za ingizo"</string>
<string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ufunguo wa kubadilisha lugha unashughulikia mbinu zingine za ingizo pia"</string>
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Kitufe cha kubadilisha lugha"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Onyesha wakati lugha ingizo mbalimbali zinapowezeshwa"</string>
<string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Kuchelewesha kutupa kitufe ibukizi"</string>
<string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Hakuna kuchelewa"</string>
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index aaccf63ba..d97df7491 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -96,7 +96,7 @@ public class KeyboardLayoutSet {
String mKeyboardLayoutSetName;
int mMode;
EditorInfo mEditorInfo;
- boolean mTouchPositionCorrectionEnabled;
+ boolean mDisableTouchPositionCorrectionDataForTest;
boolean mVoiceKeyEnabled;
boolean mVoiceKeyOnMain;
boolean mNoSettingsKey;
@@ -167,7 +167,9 @@ public class KeyboardLayoutSet {
}
final int keyboardXmlId = elementParams.mKeyboardXmlId;
builder.load(keyboardXmlId, id);
- builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
+ if (mParams.mDisableTouchPositionCorrectionDataForTest) {
+ builder.disableTouchPositionCorrectionDataForTest();
+ }
builder.setProximityCharsCorrectionEnabled(
elementParams.mProximityCharsCorrectionEnabled);
keyboard = builder.build();
@@ -264,8 +266,9 @@ public class KeyboardLayoutSet {
return this;
}
- public void setTouchPositionCorrectionEnabled(final boolean enabled) {
- mParams.mTouchPositionCorrectionEnabled = enabled;
+ // For test only
+ public void disableTouchPositionCorrectionDataForTest() {
+ mParams.mDisableTouchPositionCorrectionDataForTest = true;
}
public KeyboardLayoutSet build() {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index f5c1b7a0c..f1fcfe785 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -318,12 +318,13 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
return hasMessages(MSG_TYPING_STATE_EXPIRED);
}
+ // TODO: Remove "gesture off while fast typing" related dead code.
@Override
public void startGestureOffWhileFastTypingTimer() {
- removeMessages(MSG_DISABLE_GESTURE_EXPIRED);
- PointerTracker.setGestureOffWhileFastTyping();
- sendMessageDelayed(obtainMessage(MSG_DISABLE_GESTURE_EXPIRED),
- mDisableGestureWhileFastTypingTimeout);
+// removeMessages(MSG_DISABLE_GESTURE_EXPIRED);
+// PointerTracker.setGestureOffWhileFastTyping();
+// sendMessageDelayed(obtainMessage(MSG_DISABLE_GESTURE_EXPIRED),
+// mDisableGestureWhileFastTypingTimeout);
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 0778ad902..d6c567ef7 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -169,6 +169,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
private boolean mIsDetectingGesture = false; // per PointerTracker.
private static boolean sInGesture = false;
private static long sGestureFirstDownTime;
+ private static long sLastLetterTypingUpTime;
private static final InputPointers sAggregratedPointers = new InputPointers(
GestureStroke.DEFAULT_CAPACITY);
private static int sLastRecognitionPointSize = 0;
@@ -698,6 +699,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
private void onGestureDownEvent(final int x, final int y, final long eventTime) {
mIsDetectingGesture = true;
+ mGestureStrokeWithPreviewPoints.setLastLetterTypingTime(eventTime, sLastLetterTypingUpTime);
final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime);
mGestureStrokeWithPreviewPoints.addPoint(x, y, elapsedTimeFromFirstDown,
true /* isMajorEvent */);
@@ -842,7 +844,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY);
}
- onUpEventInternal();
+ onUpEventInternal(eventTime);
onDownEventInternal(x, y, eventTime);
} else {
// HACK: If there are currently multiple touches, register the key even if
@@ -852,7 +854,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
// this hack.
if (getActivePointerTrackerCount() > 1 && sPointerTrackerQueue != null
&& !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) {
- onUpEventInternal();
+ onUpEventInternal(eventTime);
}
if (!mIsDetectingGesture) {
mKeyAlreadyProcessed = true;
@@ -897,7 +899,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
}
}
}
- onUpEventInternal();
+ onUpEventInternal(eventTime);
if (queue != null) {
queue.remove(this);
}
@@ -911,11 +913,11 @@ public class PointerTracker implements PointerTrackerQueue.Element {
if (DEBUG_EVENT) {
printTouchEvent("onPhntEvent:", getLastX(), getLastY(), eventTime);
}
- onUpEventInternal();
+ onUpEventInternal(eventTime);
mKeyAlreadyProcessed = true;
}
- private void onUpEventInternal() {
+ private void onUpEventInternal(final long eventTime) {
mTimerProxy.cancelKeyTimers();
mIsInSlidingKeyInput = false;
mIsDetectingGesture = false;
@@ -943,6 +945,10 @@ public class PointerTracker implements PointerTrackerQueue.Element {
}
if (currentKey != null && !currentKey.isRepeatable()) {
detectAndSendKey(currentKey, mKeyX, mKeyY);
+ final int code = currentKey.mCode;
+ if (Keyboard.isLetterCode(code) && code != Keyboard.CODE_SPACE) {
+ sLastLetterTypingUpTime = eventTime;
+ }
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index e1b082c16..6e138946f 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -44,7 +44,6 @@ public class ProximityInfo {
private final int mKeyboardHeight;
private final int mMostCommonKeyWidth;
private final Key[] mKeys;
- private final TouchPositionCorrection mTouchPositionCorrection;
private final Key[][] mGridNeighbors;
private final String mLocaleStr;
@@ -67,14 +66,13 @@ public class ProximityInfo {
mKeyHeight = mostCommonKeyHeight;
mMostCommonKeyWidth = mostCommonKeyWidth;
mKeys = keys;
- mTouchPositionCorrection = touchPositionCorrection;
mGridNeighbors = new Key[mGridSize][];
if (minWidth == 0 || height == 0) {
// No proximity required. Keyboard might be more keys keyboard.
return;
}
computeNearestNeighbors();
- mNativeProximityInfo = createNativeProximityInfo();
+ mNativeProximityInfo = createNativeProximityInfo(touchPositionCorrection);
}
public static ProximityInfo createDummyProximityInfo() {
@@ -106,12 +104,12 @@ public class ProximityInfo {
private native void releaseProximityInfoNative(long nativeProximityInfo);
- private final long createNativeProximityInfo() {
+ private final long createNativeProximityInfo(
+ final TouchPositionCorrection touchPositionCorrection) {
final Key[][] gridNeighborKeys = mGridNeighbors;
final int keyboardWidth = mKeyboardMinWidth;
final int keyboardHeight = mKeyboardHeight;
final Key[] keys = mKeys;
- final TouchPositionCorrection touchPositionCorrection = mTouchPositionCorrection;
final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE);
for (int i = 0; i < mGridSize; ++i) {
@@ -148,12 +146,12 @@ public class ProximityInfo {
final Key key = keys[i];
final Rect hitBox = key.mHitBox;
final int row = hitBox.top / mKeyHeight;
- if (row < touchPositionCorrection.mRadii.length) {
+ if (row < touchPositionCorrection.getRows()) {
final int hitBoxWidth = hitBox.width();
final int hitBoxHeight = hitBox.height();
- final float x = touchPositionCorrection.mXs[row];
- final float y = touchPositionCorrection.mYs[row];
- final float radius = touchPositionCorrection.mRadii[row];
+ final float x = touchPositionCorrection.getX(row);
+ final float y = touchPositionCorrection.getY(row);
+ final float radius = touchPositionCorrection.getRadius(row);
sweetSpotCenterXs[i] = hitBox.exactCenterX() + x * hitBoxWidth;
sweetSpotCenterYs[i] = hitBox.exactCenterY() + y * hitBoxHeight;
// Note that, in recent versions of Android, FloatMath is actually slower than
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
index 193c3a4ba..9fe6fa3f8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
@@ -34,8 +34,10 @@ public class GestureStroke {
private long mLastMajorEventTime;
private int mLastMajorEventX;
private int mLastMajorEventY;
+ private boolean mAfterFastTyping;
private int mKeyWidth;
+ private int mStartGestureLengthThresholdAfterFastTyping; // pixel
private int mStartGestureLengthThreshold; // pixel
private int mMinGestureSamplingLength; // pixel
private int mGestureRecognitionSpeedThreshold; // pixel / sec
@@ -45,7 +47,11 @@ public class GestureStroke {
private int mDetectFastMoveY;
// TODO: Move some of these to resource.
- private static final float START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH = 0.60f;
+ private static final int GESTURE_AFTER_FAST_TYPING_DURATION_THRESHOLD = 350; // msec
+ private static final float START_GESTURE_LENGTH_THRESHOLD_AFTER_FAST_TYPING_RATIO_TO_KEY_WIDTH =
+ 8.0f;
+ private static final int START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION = 400; // msec
+ private static final float START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH = 0.6f;
private static final int START_GESTURE_DURATION_THRESHOLD = 70; // msec
private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec
private static final float MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH = 1.0f / 6.0f;
@@ -67,6 +73,8 @@ public class GestureStroke {
public void setKeyboardGeometry(final int keyWidth) {
mKeyWidth = keyWidth;
// TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key?
+ mStartGestureLengthThresholdAfterFastTyping = (int)(keyWidth
+ * START_GESTURE_LENGTH_THRESHOLD_AFTER_FAST_TYPING_RATIO_TO_KEY_WIDTH);
mStartGestureLengthThreshold =
(int)(keyWidth * START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH);
mMinGestureSamplingLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH);
@@ -75,10 +83,33 @@ public class GestureStroke {
mDetectFastMoveSpeedThreshold =
(int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH);
if (DEBUG) {
- Log.d(TAG, "setKeyboardGeometry: keyWidth=" + keyWidth);
+ Log.d(TAG, "[" + mPointerId + "] setKeyboardGeometry: keyWidth=" + keyWidth
+ + " tL0=" + mStartGestureLengthThresholdAfterFastTyping
+ + " tL=" + mStartGestureLengthThreshold);
}
}
+ public void setLastLetterTypingTime(final long downTime, final long lastTypingTime) {
+ final long elpasedTimeAfterTyping = downTime - lastTypingTime;
+ if (elpasedTimeAfterTyping < GESTURE_AFTER_FAST_TYPING_DURATION_THRESHOLD) {
+ mAfterFastTyping = true;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "[" + mPointerId + "] setLastTypingTime: dT=" + elpasedTimeAfterTyping
+ + " afterFastTyping=" + mAfterFastTyping);
+ }
+ }
+
+ private int getStartGestureLengthThreshold(final int deltaTime) {
+ if (!mAfterFastTyping || deltaTime >= START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION) {
+ return mStartGestureLengthThreshold;
+ }
+ final int decayedThreshold =
+ (mStartGestureLengthThresholdAfterFastTyping - mStartGestureLengthThreshold)
+ * deltaTime / START_GESTURE_LENGTH_THRESHOLD_DECAY_DURATION;
+ return mStartGestureLengthThresholdAfterFastTyping - decayedThreshold;
+ }
+
public boolean isStartOfAGesture() {
if (mDetectFastMoveTime == 0) {
return false;
@@ -92,10 +123,12 @@ public class GestureStroke {
final int deltaLength = getDistance(
mXCoordinates.get(lastIndex), mYCoordinates.get(lastIndex),
mDetectFastMoveX, mDetectFastMoveY);
+ final int startGestureLengthThreshold = getStartGestureLengthThreshold(deltaTime);
final boolean isStartOfAGesture = deltaTime > START_GESTURE_DURATION_THRESHOLD
- && deltaLength > mStartGestureLengthThreshold;
+ && deltaLength > startGestureLengthThreshold;
if (DEBUG) {
- Log.d(TAG, "isStartOfAGesture: dT=" + deltaTime + " dL=" + deltaLength
+ Log.d(TAG, "[" + mPointerId + "] isStartOfAGesture: dT=" + deltaTime
+ + " dL=" + deltaLength + " tL=" + startGestureLengthThreshold
+ " points=" + size + (isStartOfAGesture ? " Detect start of a gesture" : ""));
}
return isStartOfAGesture;
@@ -109,6 +142,7 @@ public class GestureStroke {
mYCoordinates.setLength(0);
mLastMajorEventTime = 0;
mDetectFastMoveTime = 0;
+ mAfterFastTyping = false;
}
private void appendPoint(final int x, final int y, final int time) {
@@ -135,12 +169,13 @@ public class GestureStroke {
final int pixelsPerSec = pixels * MSEC_PER_SEC;
if (DEBUG) {
final float speed = (float)pixelsPerSec / msecs / mKeyWidth;
- Log.d(TAG, String.format("Speed=%.3f keyWidth/sec", speed));
+ Log.d(TAG, String.format("[" + mPointerId + "] speed=%.3f", speed));
}
// Equivalent to (pixels / msecs < mStartSpeedThreshold / MSEC_PER_SEC)
if (mDetectFastMoveTime == 0 && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) {
if (DEBUG) {
- Log.d(TAG, "Detect fast move: T=" + time + " points = " + size);
+ Log.d(TAG, "[" + mPointerId + "] detect fast move: T="
+ + time + " points = " + size);
}
mDetectFastMoveTime = time;
mDetectFastMoveX = x;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 31c7cb565..b314a3795 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -177,9 +177,9 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
return this;
}
- // TODO: Remove this method.
- public void setTouchPositionCorrectionEnabled(final boolean enabled) {
- mParams.mTouchPositionCorrection.setEnabled(enabled);
+ // For test only
+ public void disableTouchPositionCorrectionDataForTest() {
+ mParams.mTouchPositionCorrection.setEnabled(false);
}
public void setProximityCharsCorrectionEnabled(final boolean enabled) {
@@ -314,7 +314,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0);
- params.mTouchPositionCorrection.setEnabled(resourceId != 0);
if (resourceId != 0) {
final String[] data = mResources.getStringArray(resourceId);
params.mTouchPositionCorrection.load(data);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
index 69dc01cd6..811a620b3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
@@ -21,10 +21,10 @@ import com.android.inputmethod.latin.LatinImeLogger;
public class TouchPositionCorrection {
private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3;
- public boolean mEnabled;
- public float[] mXs;
- public float[] mYs;
- public float[] mRadii;
+ private boolean mEnabled;
+ private float[] mXs;
+ private float[] mYs;
+ private float[] mRadii;
public void load(final String[] data) {
final int dataLength = data.length;
@@ -53,24 +53,41 @@ public class TouchPositionCorrection {
mRadii[index] = value;
}
}
+ mEnabled = dataLength > 0;
} catch (NumberFormatException e) {
if (LatinImeLogger.sDBG) {
throw new RuntimeException(
"the number format for touch position correction data is invalid");
}
+ mEnabled = false;
mXs = null;
mYs = null;
mRadii = null;
}
}
- // TODO: Remove this method.
+ // For test only
public void setEnabled(final boolean enabled) {
mEnabled = enabled;
}
public boolean isValid() {
- return mEnabled && mXs != null && mYs != null && mRadii != null
- && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0;
+ return mEnabled;
+ }
+
+ public int getRows() {
+ return mRadii.length;
+ }
+
+ public float getX(final int row) {
+ return mXs[row];
+ }
+
+ public float getY(final int row) {
+ return mYs[row];
+ }
+
+ public float getRadius(final int row) {
+ return mRadii[row];
}
}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
index 4a3d11aa1..05255a6b3 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
@@ -100,6 +100,11 @@ public class UserHistoryDictIOUtils {
@Override
public int limit() {
+ return mBuffer.length - 1;
+ }
+
+ @Override
+ public int capacity() {
return mBuffer.length;
}
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index ac0fb0ece..19da5124a 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -157,47 +157,63 @@ public class BinaryDictIOUtils {
final int wordLen = word.codePointCount(0, word.length());
for (int depth = 0; depth < Constants.Dictionary.MAX_WORD_LENGTH; ++depth) {
if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD;
- int groupOffset = buffer.position() - header.mHeaderSize;
- final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer);
- groupOffset += BinaryDictInputOutput.getGroupCountSize(charGroupCount);
-
- for (int i = 0; i < charGroupCount; ++i) {
- final int charGroupPos = buffer.position();
- final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer,
- buffer.position(), header.mFormatOptions);
- boolean same = true;
- for (int p = 0, j = word.offsetByCodePoints(0, wordPos);
- p < currentInfo.mCharacters.length;
- ++p, j = word.offsetByCodePoints(j, 1)) {
- if (wordPos + p >= wordLen
- || word.codePointAt(j) != currentInfo.mCharacters[p]) {
- same = false;
- break;
+
+ do {
+ int groupOffset = buffer.position() - header.mHeaderSize;
+ final int charGroupCount = BinaryDictInputOutput.readCharGroupCount(buffer);
+ groupOffset += BinaryDictInputOutput.getGroupCountSize(charGroupCount);
+
+ boolean foundNextCharGroup = false;
+ for (int i = 0; i < charGroupCount; ++i) {
+ final int charGroupPos = buffer.position();
+ final CharGroupInfo currentInfo = BinaryDictInputOutput.readCharGroup(buffer,
+ buffer.position(), header.mFormatOptions);
+ boolean same = true;
+ for (int p = 0, j = word.offsetByCodePoints(0, wordPos);
+ p < currentInfo.mCharacters.length;
+ ++p, j = word.offsetByCodePoints(j, 1)) {
+ if (wordPos + p >= wordLen
+ || word.codePointAt(j) != currentInfo.mCharacters[p]) {
+ same = false;
+ break;
+ }
}
- }
- if (same) {
- if (wordPos + currentInfo.mCharacters.length == wordLen) {
- if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL) {
+ if (same) {
+ // found the group matches the word.
+ if (wordPos + currentInfo.mCharacters.length == wordLen) {
+ if (currentInfo.mFrequency == CharGroup.NOT_A_TERMINAL) {
+ return FormatSpec.NOT_VALID_WORD;
+ } else {
+ return charGroupPos;
+ }
+ }
+ wordPos += currentInfo.mCharacters.length;
+ if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
return FormatSpec.NOT_VALID_WORD;
- } else {
- return charGroupPos;
}
+ foundNextCharGroup = true;
+ buffer.position(currentInfo.mChildrenAddress);
+ break;
}
- wordPos += currentInfo.mCharacters.length;
- if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
- return FormatSpec.NOT_VALID_WORD;
- }
- buffer.position(currentInfo.mChildrenAddress);
- break;
+ groupOffset = currentInfo.mEndAddress;
}
- groupOffset = currentInfo.mEndAddress;
- // not found
- if (i >= charGroupCount - 1) {
+ // If we found the next char group, it is under the file pointer.
+ // But if not, we are at the end of this node so we expect to have
+ // a forward link address that we need to consult and possibly resume
+ // search on the next node in the linked list.
+ if (foundNextCharGroup) break;
+ if (!header.mFormatOptions.mSupportsDynamicUpdate) {
return FormatSpec.NOT_VALID_WORD;
}
- }
+
+ final int forwardLinkAddress = buffer.readUnsignedInt24();
+ if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) {
+ return FormatSpec.NOT_VALID_WORD;
+ }
+ buffer.position(forwardLinkAddress);
+ } while(true);
}
return FormatSpec.NOT_VALID_WORD;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index 4806bf9dc..f9339de08 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -36,7 +36,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import java.util.Stack;
import java.util.TreeMap;
/**
@@ -64,6 +63,7 @@ public class BinaryDictInputOutput {
public void position(int newPosition);
public void put(final byte b);
public int limit();
+ public int capacity();
}
public static final class ByteBufferWrapper implements FusionDictionaryBufferInterface {
@@ -113,6 +113,11 @@ public class BinaryDictInputOutput {
public int limit() {
return mBuffer.limit();
}
+
+ @Override
+ public int capacity() {
+ return mBuffer.capacity();
+ }
}
/**
@@ -412,6 +417,10 @@ public class BinaryDictInputOutput {
}
}
+ private static final int UINT8_MAX = 0xFF;
+ private static final int UINT16_MAX = 0xFFFF;
+ private static final int UINT24_MAX = 0xFFFFFF;
+
/**
* Compute the size, in bytes, that an address will occupy.
*
@@ -423,17 +432,25 @@ public class BinaryDictInputOutput {
* @return the byte size.
*/
private static int getByteSize(final int address) {
- assert(address < 0x1000000);
+ assert(address <= UINT24_MAX);
if (!hasChildrenAddress(address)) {
return 0;
- } else if (Math.abs(address) < 0x100) {
+ } else if (Math.abs(address) <= UINT8_MAX) {
return 1;
- } else if (Math.abs(address) < 0x10000) {
+ } else if (Math.abs(address) <= UINT16_MAX) {
return 2;
} else {
return 3;
}
}
+
+ private static final int SINT8_MAX = 0x7F;
+ private static final int SINT16_MAX = 0x7FFF;
+ private static final int SINT24_MAX = 0x7FFFFF;
+ private static final int MSB8 = 0x80;
+ private static final int MSB16 = 0x8000;
+ private static final int MSB24 = 0x800000;
+
// End utility methods.
// This method is responsible for finding a nice ordering of the nodes that favors run-time
@@ -509,13 +526,19 @@ public class BinaryDictInputOutput {
}
int groupSize = getGroupHeaderSize(group, formatOptions);
if (group.isTerminal()) groupSize += FormatSpec.GROUP_FREQUENCY_SIZE;
- if (null != group.mChildren) {
+ if (null == group.mChildren && formatOptions.mSupportsDynamicUpdate) {
+ groupSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
+ } else if (null != group.mChildren) {
final int offsetBasePoint = groupSize + node.mCachedAddress + size;
final int offset = group.mChildren.mCachedAddress - offsetBasePoint;
// assign my address to children's parent address
group.mChildren.mCachedParentAddress = group.mCachedAddress
- group.mChildren.mCachedAddress;
- groupSize += getByteSize(offset);
+ if (formatOptions.mSupportsDynamicUpdate) {
+ groupSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
+ } else {
+ groupSize += getByteSize(offset);
+ }
}
groupSize += getShortcutListSize(group.mShortcutTargets);
if (null != group.mBigrams) {
@@ -669,27 +692,52 @@ public class BinaryDictInputOutput {
}
}
+ /**
+ * Helper method to write a variable-size signed address to a file.
+ *
+ * @param buffer the buffer to write to.
+ * @param index the index in the buffer to write the address to.
+ * @param address the address to write.
+ * @return the size in bytes the address actually took.
+ */
+ private static int writeVariableSignedAddress(final byte[] buffer, int index,
+ final int address) {
+ if (!hasChildrenAddress(address)) {
+ buffer[index] = buffer[index + 1] = buffer[index + 2] = 0;
+ } else {
+ final int absAddress = Math.abs(address);
+ buffer[index++] = (byte)((address < 0 ? MSB8 : 0) | (0xFF & (absAddress >> 16)));
+ buffer[index++] = (byte)(0xFF & (absAddress >> 8));
+ buffer[index++] = (byte)(0xFF & absAddress);
+ }
+ return 3;
+ }
+
private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress,
- final int childrenOffset) {
+ final int childrenOffset, final FormatOptions formatOptions) {
byte flags = 0;
if (group.mChars.length > 1) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
if (group.mFrequency >= 0) {
flags |= FormatSpec.FLAG_IS_TERMINAL;
}
if (null != group.mChildren) {
- switch (getByteSize(childrenOffset)) {
- case 1:
- flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE;
- break;
- case 2:
- flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES;
- break;
- case 3:
- flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES;
- break;
- default:
- throw new RuntimeException("Node with a strange address");
- }
+ final int byteSize = formatOptions.mSupportsDynamicUpdate
+ ? FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE : getByteSize(childrenOffset);
+ switch (byteSize) {
+ case 1:
+ flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE;
+ break;
+ case 2:
+ flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES;
+ break;
+ case 3:
+ flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES;
+ break;
+ default:
+ throw new RuntimeException("Node with a strange address");
+ }
+ } else if (formatOptions.mSupportsDynamicUpdate) {
+ flags |= FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES;
}
if (null != group.mShortcutTargets) {
if (DBG && 0 == group.mShortcutTargets.size()) {
@@ -808,6 +856,25 @@ public class BinaryDictInputOutput {
+ (frequency & FormatSpec.FLAG_ATTRIBUTE_FREQUENCY);
}
+ private static final int writeParentAddress(final byte[] buffer, final int index,
+ final int address, final FormatOptions formatOptions) {
+ if (supportsDynamicUpdate(formatOptions)) {
+ if (address == FormatSpec.NO_PARENT_ADDRESS) {
+ buffer[index] = buffer[index + 1] = buffer[index + 2] = 0;
+ } else {
+ final int absAddress = Math.abs(address);
+ assert(absAddress <= SINT24_MAX);
+ buffer[index] = (byte)((address < 0 ? MSB8 : 0)
+ | ((absAddress >> 16) & 0xFF));
+ buffer[index + 1] = (byte)((absAddress >> 8) & 0xFF);
+ buffer[index + 2] = (byte)(absAddress & 0xFF);
+ }
+ return index + 3;
+ } else {
+ return index;
+ }
+ }
+
/**
* Write a node to memory. The node is expected to have its final position cached.
*
@@ -854,22 +921,15 @@ public class BinaryDictInputOutput {
final int childrenOffset = null == group.mChildren
? FormatSpec.NO_CHILDREN_ADDRESS
: group.mChildren.mCachedAddress - groupAddress;
- byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset);
+ byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset, formatOptions);
buffer[index++] = flags;
- if (supportsDynamicUpdate(formatOptions)) {
- if (parentAddress == FormatSpec.NO_PARENT_ADDRESS) {
- // this node is the root node.
- buffer[index] = buffer[index + 1] = buffer[index + 2] = 0;
- } else {
- // write parent address. (version 3)
- final int actualParentAddress = Math.abs(parentAddress
- + (node.mCachedAddress - group.mCachedAddress));
- buffer[index] = (byte)((actualParentAddress >> 16) & 0xFF);
- buffer[index + 1] = (byte)((actualParentAddress >> 8) & 0xFF);
- buffer[index + 2] = (byte)(actualParentAddress & 0xFF);
- }
- index += 3;
+ if (parentAddress == FormatSpec.NO_PARENT_ADDRESS) {
+ index = writeParentAddress(buffer, index, parentAddress, formatOptions);
+ } else {
+ index = writeParentAddress(buffer, index,
+ parentAddress + (node.mCachedAddress - group.mCachedAddress),
+ formatOptions);
}
index = CharEncoding.writeCharArray(group.mChars, buffer, index);
@@ -879,7 +939,13 @@ public class BinaryDictInputOutput {
if (group.mFrequency >= 0) {
buffer[index++] = (byte) group.mFrequency;
}
- final int shift = writeVariableAddress(buffer, index, childrenOffset);
+
+ final int shift;
+ if (formatOptions.mSupportsDynamicUpdate) {
+ shift = writeVariableSignedAddress(buffer, index, childrenOffset);
+ } else {
+ shift = writeVariableAddress(buffer, index, childrenOffset);
+ }
index += shift;
groupAddress += shift;
@@ -1104,6 +1170,58 @@ public class BinaryDictInputOutput {
// Input methods: Read a binary dictionary to memory.
// readDictionaryBinary is the public entry point for them.
+ private static int getChildrenAddressSize(final int optionFlags,
+ final FormatOptions formatOptions) {
+ if (formatOptions.mSupportsDynamicUpdate) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
+ switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) {
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE:
+ return 1;
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES:
+ return 2;
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES:
+ return 3;
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS:
+ default:
+ return 0;
+ }
+ }
+
+ private static int readChildrenAddress(final FusionDictionaryBufferInterface buffer,
+ final int optionFlags, final FormatOptions options) {
+ if (options.mSupportsDynamicUpdate) {
+ final int address = buffer.readUnsignedInt24();
+ if (address == 0) return FormatSpec.NO_CHILDREN_ADDRESS;
+ if ((address & MSB24) != 0) {
+ return -(address & SINT24_MAX);
+ } else {
+ return address;
+ }
+ }
+ int address;
+ switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) {
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE:
+ return buffer.readUnsignedByte();
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES:
+ return buffer.readUnsignedShort();
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES:
+ return buffer.readUnsignedInt24();
+ case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS:
+ default:
+ return FormatSpec.NO_CHILDREN_ADDRESS;
+ }
+ }
+
+ private static int readParentAddress(final FusionDictionaryBufferInterface buffer,
+ final FormatOptions formatOptions) {
+ if (supportsDynamicUpdate(formatOptions)) {
+ final int parentAddress = buffer.readUnsignedInt24();
+ final int sign = ((parentAddress & MSB24) != 0) ? -1 : 1;
+ return sign * (parentAddress & SINT24_MAX);
+ } else {
+ return FormatSpec.NO_PARENT_ADDRESS;
+ }
+ }
+
private static final int[] CHARACTER_BUFFER = new int[FormatSpec.MAX_WORD_LENGTH];
public static CharGroupInfo readCharGroup(final FusionDictionaryBufferInterface buffer,
final int originalGroupAddress, final FormatOptions options) {
@@ -1111,13 +1229,9 @@ public class BinaryDictInputOutput {
final int flags = buffer.readUnsignedByte();
++addressPointer;
- final int parentAddress;
+ final int parentAddress = readParentAddress(buffer, options);
if (supportsDynamicUpdate(options)) {
- // read the parent address. (version 3)
- parentAddress = -buffer.readUnsignedInt24();
addressPointer += 3;
- } else {
- parentAddress = FormatSpec.NO_PARENT_ADDRESS;
}
final int characters[];
@@ -1146,25 +1260,11 @@ public class BinaryDictInputOutput {
} else {
frequency = CharGroup.NOT_A_TERMINAL;
}
- int childrenAddress = addressPointer;
- switch (flags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) {
- case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_ONEBYTE:
- childrenAddress += buffer.readUnsignedByte();
- addressPointer += 1;
- break;
- case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_TWOBYTES:
- childrenAddress += buffer.readUnsignedShort();
- addressPointer += 2;
- break;
- case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_THREEBYTES:
- childrenAddress += buffer.readUnsignedInt24();
- addressPointer += 3;
- break;
- case FormatSpec.FLAG_GROUP_ADDRESS_TYPE_NOADDRESS:
- default:
- childrenAddress = FormatSpec.NO_CHILDREN_ADDRESS;
- break;
+ int childrenAddress = readChildrenAddress(buffer, flags, options);
+ if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) {
+ childrenAddress += addressPointer;
}
+ addressPointer += getChildrenAddressSize(flags, options);
ArrayList<WeightedString> shortcutTargets = null;
if (0 != (flags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS)) {
final int pointerBefore = buffer.position();
@@ -1250,6 +1350,7 @@ public class BinaryDictInputOutput {
final String result;
final int originalPointer = buffer.position();
+ buffer.position(address);
if (supportsDynamicUpdate(formatOptions)) {
result = getWordAtAddressWithParentAddress(buffer, headerSize, address, formatOptions);
@@ -1279,7 +1380,6 @@ public class BinaryDictInputOutput {
sGetWordBuffer[index--] =
currentInfo.mCharacters[currentInfo.mCharacters.length - i - 1];
}
-
if (currentInfo.mParentAddress == FormatSpec.NO_PARENT_ADDRESS) break;
currentAddress = currentInfo.mParentAddress + currentInfo.mOriginalAddress;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 63a61b46f..cab0661f6 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -42,11 +42,13 @@ public final class FormatSpec {
* ps
*
* f |
- * o | IF HAS_LINKEDLIST_NODE (defined in the file header)
+ * o | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header)
* r | forward link address, 3byte
- * w | the address must be positive.
- * a |
- * rdlinkaddress
+ * w | 1 byte = bbbbbbbb match
+ * a | case 1xxxxxxx => -((xxxxxxx << 16) + (next byte << 8) + next byte)
+ * r | otherwise => (xxxxxxx << 16) + (next byte << 8) + next byte
+ * d |
+ * linkaddress
*/
/* Node(CharGroup) layout is as follows:
@@ -63,11 +65,13 @@ public final class FormatSpec {
* | is blacklisted ? 1 bit, 1 = yes, 0 = no : FLAG_IS_BLACKLISTED
*
* p |
- * a | IF HAS_PARENT_ADDRESS (defined in the file header)
+ * a | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header)
* r | parent address, 3byte
- * e | the address must be negative, so the absolute value of the address is stored.
- * n |
- * taddress
+ * e | 1 byte = bbbbbbbb match
+ * n | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte)
+ * t | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte
+ * a |
+ * ddress
*
* c | IF FLAG_HAS_MULTIPLE_CHARS
* h | char, char, char, char n * (1 or 3 bytes) : use CharGroupInfo for i/o helpers
@@ -206,6 +210,7 @@ public final class FormatSpec {
// This option needs to be the same numeric value as the one in binary_format.h.
static final int NOT_VALID_WORD = -99;
+ static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3;
/**
* Options about file format.