aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dictionaries/es_wordlist.combined.gzbin1164600 -> 1164608 bytes
-rw-r--r--java/res/layout/key_preview.xml27
-rw-r--r--java/res/raw/main_es.dictbin1376670 -> 1376678 bytes
-rw-r--r--java/res/values/attrs.xml6
-rw-r--r--java/res/values/themes-common.xml2
-rw-r--r--java/res/values/themes-ics.xml8
-rw-r--r--java/res/values/themes-klp.xml8
-rw-r--r--java/res/values/themes-lxx-dark.xml8
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java156
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java90
-rw-r--r--native/jni/Android.mk3
-rw-r--r--native/jni/TargetUnitTests.mk55
-rwxr-xr-xnative/jni/run-tests.sh53
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java109
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java34
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java34
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java56
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java46
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java13
-rw-r--r--tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java58
-rw-r--r--tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java28
23 files changed, 454 insertions, 355 deletions
diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz
index 181a958c0..c0a5264fc 100644
--- a/dictionaries/es_wordlist.combined.gz
+++ b/dictionaries/es_wordlist.combined.gz
Binary files differ
diff --git a/java/res/layout/key_preview.xml b/java/res/layout/key_preview.xml
deleted file mode 100644
index 16d4c72c3..000000000
--- a/java/res/layout/key_preview.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minWidth="32dp"
- android:gravity="center"
- style="?attr/keyPreviewTextViewStyle"
-/>
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 83eefe4f6..0911b70f1 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index a1f478bd5..fcb919d0b 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -26,8 +26,6 @@
<attr name="keyboardViewStyle" format="reference" />
<!-- MainKeyboardView style -->
<attr name="mainKeyboardViewStyle" format="reference" />
- <!-- Key preview text view style -->
- <attr name="keyPreviewTextViewStyle" format="reference"/>
<!-- EmojiPalettesView style -->
<attr name="emojiPalettesViewStyle" format="reference" />
<!-- MoreKeysKeyboard style -->
@@ -106,8 +104,8 @@
<attr name="longPressShiftLockTimeout" format="integer" />
<!-- Ignore special key timeout while typing in millisecond. -->
<attr name="ignoreAltCodeKeyTimeout" format="integer" />
- <!-- Layout resource for key press feedback.-->
- <attr name="keyPreviewLayout" format="reference" />
+ <!-- Background resource for key press feedback.-->
+ <attr name="keyPreviewBackground" format="reference" />
<!-- Vertical offset of the key press feedback from the key. -->
<attr name="keyPreviewOffset" format="dimension" />
<!-- Height of the key press feedback popup. -->
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 02a93ca82..2b2a80aed 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -75,7 +75,6 @@
<item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
<item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
<item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
- <item name="keyPreviewLayout">@layout/key_preview</item>
<item name="keyPreviewHeight">@dimen/config_key_preview_height</item>
<!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
<item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
@@ -106,7 +105,6 @@
<style
name="MainKeyboardView"
parent="KeyboardView" />
- <style name="KeyPreviewTextView" />
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style name="EmojiPalettesView" />
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index 319b4aeed..073ae90b9 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.ICS</item>
<item name="keyboardViewStyle">@style/KeyboardView.ICS</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.ICS</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.ICS</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.ICS</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.ICS</item>
@@ -66,6 +65,7 @@
name="MainKeyboardView.ICS"
parent="KeyboardView.ICS"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style>
- <style
- name="KeyPreviewTextView.ICS"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_ics</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 208723dd3..f895de572 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.KLP</item>
<item name="keyboardViewStyle">@style/KeyboardView.KLP</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.KLP</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item>
@@ -66,6 +65,7 @@
name="MainKeyboardView.KLP"
parent="KeyboardView.KLP"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_klp</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style>
- <style
- name="KeyPreviewTextView.KLP"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_klp</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index e9a295c67..1db8f428e 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.LXX_Dark</item>
<item name="keyboardViewStyle">@style/KeyboardView.LXX_Dark</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Dark</item>
- <item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.LXX_Dark</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Dark</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LXX_Dark</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LXX_Dark</item>
@@ -67,6 +66,7 @@
name="MainKeyboardView.LXX_Dark"
parent="KeyboardView.LXX_Dark"
>
+ <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_dark</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_lxx_dark</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_lxx_dark</item>
@@ -76,12 +76,6 @@
<!-- A negative value to disable text shadow layer. -->
<item name="languageOnSpacebarTextShadowRadius">-1.0</item>
</style>
- <style
- name="KeyPreviewTextView.LXX_Dark"
- parent="KeyPreviewTextView"
- >
- <item name="android:background">@drawable/keyboard_key_feedback_lxx_dark</item>
- </style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 53628f760..81825934f 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -664,10 +664,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
@Override
public void onDismissMoreKeysPanel() {
dimEntireKeyboard(false /* dimmed */);
- dismissMoreKeysPanel();
- }
-
- private void dismissMoreKeysPanel() {
if (isShowingMoreKeysPanel()) {
mMoreKeysPanel.removeFromParent();
mMoreKeysPanel = null;
@@ -733,7 +729,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
public void onHideWindow() {
- dismissMoreKeysPanel();
+ onDismissMoreKeysPanel();
final MainKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate;
if (accessibilityDelegate != null) {
accessibilityDelegate.onHideWindow();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index d4c671028..6fc300beb 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -21,17 +21,12 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
-import android.widget.TextView;
import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
@@ -46,10 +41,11 @@ import java.util.HashSet;
* - how key previews should be shown and dismissed.
*/
public final class KeyPreviewChoreographer {
- // Free {@link TextView} pool that can be used for key preview.
- private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = new ArrayDeque<>();
- // Map from {@link Key} to {@link TextView} that is currently being displayed as key preview.
- private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = new HashMap<>();
+ // Free {@link KeyPreviewView} pool that can be used for key preview.
+ private final ArrayDeque<KeyPreviewView> mFreeKeyPreviewViews = new ArrayDeque<>();
+ // Map from {@link Key} to {@link KeyPreviewView} that is currently being displayed as key
+ // preview.
+ private final HashMap<Key,KeyPreviewView> mShowingKeyPreviewViews = new HashMap<>();
private final KeyPreviewDrawParams mParams;
@@ -57,32 +53,28 @@ public final class KeyPreviewChoreographer {
mParams = params;
}
- private TextView getKeyPreviewTextView(final Key key, final ViewGroup placerView) {
- TextView previewTextView = mShowingKeyPreviewTextViews.remove(key);
- if (previewTextView != null) {
- return previewTextView;
+ public KeyPreviewView getKeyPreviewView(final Key key, final ViewGroup placerView) {
+ KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.remove(key);
+ if (keyPreviewView != null) {
+ return keyPreviewView;
}
- previewTextView = mFreeKeyPreviewTextViews.poll();
- if (previewTextView != null) {
- return previewTextView;
+ keyPreviewView = mFreeKeyPreviewViews.poll();
+ if (keyPreviewView != null) {
+ return keyPreviewView;
}
final Context context = placerView.getContext();
- if (mParams.mLayoutId != 0) {
- previewTextView = (TextView)LayoutInflater.from(context)
- .inflate(mParams.mLayoutId, null);
- } else {
- previewTextView = new TextView(context);
- }
- placerView.addView(previewTextView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
- return previewTextView;
+ keyPreviewView = new KeyPreviewView(context, null /* attrs */);
+ keyPreviewView.setBackgroundResource(mParams.mPreviewBackgroundResId);
+ placerView.addView(keyPreviewView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
+ return keyPreviewView;
}
public boolean isShowingKeyPreview(final Key key) {
- return mShowingKeyPreviewTextViews.containsKey(key);
+ return mShowingKeyPreviewViews.containsKey(key);
}
public void dismissAllKeyPreviews() {
- for (final Key key : new HashSet<>(mShowingKeyPreviewTextViews.keySet())) {
+ for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) {
dismissKeyPreview(key, false /* withAnimation */);
}
}
@@ -91,11 +83,11 @@ public final class KeyPreviewChoreographer {
if (key == null) {
return;
}
- final TextView previewTextView = mShowingKeyPreviewTextViews.get(key);
- if (previewTextView == null) {
+ final KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.get(key);
+ if (keyPreviewView == null) {
return;
}
- final Object tag = previewTextView.getTag();
+ final Object tag = keyPreviewView.getTag();
if (withAnimation) {
if (tag instanceof KeyPreviewAnimations) {
final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag;
@@ -104,114 +96,76 @@ public final class KeyPreviewChoreographer {
}
}
// Dismiss preview without animation.
- mShowingKeyPreviewTextViews.remove(key);
+ mShowingKeyPreviewViews.remove(key);
if (tag instanceof Animator) {
((Animator)tag).cancel();
}
- previewTextView.setTag(null);
- previewTextView.setVisibility(View.INVISIBLE);
- mFreeKeyPreviewTextViews.add(previewTextView);
+ keyPreviewView.setTag(null);
+ keyPreviewView.setVisibility(View.INVISIBLE);
+ mFreeKeyPreviewViews.add(keyPreviewView);
}
- // Background state set
- private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
- { // STATE_MIDDLE
- {},
- { R.attr.state_has_morekeys }
- },
- { // STATE_LEFT
- { R.attr.state_left_edge },
- { R.attr.state_left_edge, R.attr.state_has_morekeys }
- },
- { // STATE_RIGHT
- { R.attr.state_right_edge },
- { R.attr.state_right_edge, R.attr.state_has_morekeys }
- }
- };
- private static final int STATE_MIDDLE = 0;
- private static final int STATE_LEFT = 1;
- private static final int STATE_RIGHT = 2;
- private static final int STATE_NORMAL = 0;
- private static final int STATE_HAS_MOREKEYS = 1;
-
public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet,
final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin,
final ViewGroup placerView, final boolean withAnimation) {
- final TextView previewTextView = getKeyPreviewTextView(key, placerView);
+ final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView);
placeKeyPreview(
- key, previewTextView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin);
- showKeyPreview(key, previewTextView, withAnimation);
+ key, keyPreviewView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin);
+ showKeyPreview(key, keyPreviewView, withAnimation);
}
- private void placeKeyPreview(final Key key, final TextView previewTextView,
+ private void placeKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams,
final int keyboardViewWidth, final int[] originCoords) {
- previewTextView.setTextColor(drawParams.mPreviewTextColor);
- final Drawable background = previewTextView.getBackground();
- final String label = key.getPreviewLabel();
- // What we show as preview should match what we show on a key top in onDraw().
- if (label != null) {
- // TODO Should take care of temporaryShiftLabel here.
- previewTextView.setCompoundDrawables(null, null, null, null);
- previewTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- key.selectPreviewTextSize(drawParams));
- previewTextView.setTypeface(key.selectPreviewTypeface(drawParams));
- previewTextView.setText(label);
- } else {
- previewTextView.setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
- previewTextView.setText(null);
- }
-
- previewTextView.measure(
+ keyPreviewView.setPreviewVisual(key, iconsSet, drawParams);
+ keyPreviewView.measure(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- mParams.setGeometry(previewTextView);
- final int previewWidth = previewTextView.getMeasuredWidth();
+ mParams.setGeometry(keyPreviewView);
+ final int previewWidth = keyPreviewView.getMeasuredWidth();
final int previewHeight = mParams.mPreviewHeight;
final int keyDrawWidth = key.getDrawWidth();
// 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
// the left/right background is used if such background is specified.
- final int statePosition;
+ final int keyPreviewPosition;
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
+ CoordinateUtils.x(originCoords);
if (previewX < 0) {
previewX = 0;
- statePosition = STATE_LEFT;
+ keyPreviewPosition = KeyPreviewView.POSITION_LEFT;
} else if (previewX > keyboardViewWidth - previewWidth) {
previewX = keyboardViewWidth - previewWidth;
- statePosition = STATE_RIGHT;
+ keyPreviewPosition = KeyPreviewView.POSITION_RIGHT;
} else {
- statePosition = STATE_MIDDLE;
+ keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE;
}
+ final boolean hasMoreKeys = (key.getMoreKeys() != null);
+ keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition);
// The key preview is placed vertically above the top edge of the parent key with an
// arbitrary offset.
final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset
+ CoordinateUtils.y(originCoords);
- if (background != null) {
- final int hasMoreKeys = (key.getMoreKeys() != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL;
- background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]);
- }
ViewLayoutUtils.placeViewAt(
- previewTextView, previewX, previewY, previewWidth, previewHeight);
- previewTextView.setPivotX(previewWidth / 2.0f);
- previewTextView.setPivotY(previewHeight);
+ keyPreviewView, previewX, previewY, previewWidth, previewHeight);
+ keyPreviewView.setPivotX(previewWidth / 2.0f);
+ keyPreviewView.setPivotY(previewHeight);
}
- private void showKeyPreview(final Key key, final TextView previewTextView,
+ private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final boolean withAnimation) {
if (!withAnimation) {
- previewTextView.setVisibility(View.VISIBLE);
- mShowingKeyPreviewTextViews.put(key, previewTextView);
+ keyPreviewView.setVisibility(View.VISIBLE);
+ mShowingKeyPreviewViews.put(key, keyPreviewView);
return;
}
// Show preview with animation.
- final Animator showUpAnimation = createShowUpAniation(key, previewTextView);
- final Animator dismissAnimation = createDismissAnimation(key, previewTextView);
+ final Animator showUpAnimation = createShowUpAniation(key, keyPreviewView);
+ final Animator dismissAnimation = createDismissAnimation(key, keyPreviewView);
final KeyPreviewAnimations animation = new KeyPreviewAnimations(
showUpAnimation, dismissAnimation);
- previewTextView.setTag(animation);
+ keyPreviewView.setTag(animation);
animation.startShowUp();
}
@@ -221,13 +175,13 @@ public final class KeyPreviewChoreographer {
private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
new DecelerateInterpolator();
- private Animator createShowUpAniation(final Key key, final TextView previewTextView) {
+ private Animator createShowUpAniation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_X, mParams.getShowUpStartScale(),
+ keyPreviewView, View.SCALE_X, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE);
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_Y, mParams.getShowUpStartScale(),
+ keyPreviewView, View.SCALE_Y, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE);
final AnimatorSet showUpAnimation = new AnimatorSet();
showUpAnimation.play(scaleXAnimation).with(scaleYAnimation);
@@ -236,18 +190,18 @@ public final class KeyPreviewChoreographer {
showUpAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(final Animator animation) {
- showKeyPreview(key, previewTextView, false /* withAnimation */);
+ showKeyPreview(key, keyPreviewView, false /* withAnimation */);
}
});
return showUpAnimation;
}
- private Animator createDismissAnimation(final Key key, final TextView previewTextView) {
+ private Animator createDismissAnimation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_X, mParams.getDismissEndScale());
+ keyPreviewView, View.SCALE_X, mParams.getDismissEndScale());
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
- previewTextView, View.SCALE_Y, mParams.getDismissEndScale());
+ keyPreviewView, View.SCALE_Y, mParams.getDismissEndScale());
final AnimatorSet dismissAnimation = new AnimatorSet();
dismissAnimation.play(scaleXAnimation).with(scaleYAnimation);
final int dismissDuration = Math.min(
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
index 37e5c889d..68c9831fa 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java
@@ -23,9 +23,9 @@ import com.android.inputmethod.latin.R;
public final class KeyPreviewDrawParams {
// XML attributes of {@link MainKeyboardView}.
- public final int mLayoutId;
public final int mPreviewOffset;
public final int mPreviewHeight;
+ public final int mPreviewBackgroundResId;
private int mShowUpDuration;
private int mDismissDuration;
private float mShowUpStartScale;
@@ -63,13 +63,10 @@ public final class KeyPreviewDrawParams {
R.styleable.MainKeyboardView_keyPreviewOffset, 0);
mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize(
R.styleable.MainKeyboardView_keyPreviewHeight, 0);
+ mPreviewBackgroundResId = mainKeyboardViewAttr.getResourceId(
+ R.styleable.MainKeyboardView_keyPreviewBackground, 0);
mLingerTimeout = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0);
- mLayoutId = mainKeyboardViewAttr.getResourceId(
- R.styleable.MainKeyboardView_keyPreviewLayout, 0);
- if (mLayoutId == 0) {
- mShowPopup = false;
- }
}
public void setVisibleOffset(final int previewVisibleOffset) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
new file mode 100644
index 000000000..360faf829
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.widget.TextView;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.latin.R;
+
+/**
+ * The pop up key preview view.
+ */
+public class KeyPreviewView extends TextView {
+ public static final int POSITION_MIDDLE = 0;
+ public static final int POSITION_LEFT = 1;
+ public static final int POSITION_RIGHT = 2;
+
+ public KeyPreviewView(final Context context, final AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setGravity(Gravity.CENTER);
+ }
+
+ public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet,
+ final KeyDrawParams drawParams) {
+ // What we show as preview should match what we show on a key top in onDraw().
+ final int iconId = key.getIconId();
+ if (iconId != KeyboardIconsSet.ICON_UNDEFINED) {
+ setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
+ setText(null);
+ return;
+ }
+
+ setCompoundDrawables(null, null, null, null);
+ setTextColor(drawParams.mPreviewTextColor);
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
+ setTypeface(key.selectPreviewTypeface(drawParams));
+ // TODO Should take care of temporaryShiftLabel here.
+ setText(key.getPreviewLabel());
+ }
+
+ // Background state set
+ private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
+ { // POSITION_MIDDLE
+ {},
+ { R.attr.state_has_morekeys }
+ },
+ { // POSITION_LEFT
+ { R.attr.state_left_edge },
+ { R.attr.state_left_edge, R.attr.state_has_morekeys }
+ },
+ { // POSITION_RIGHT
+ { R.attr.state_right_edge },
+ { R.attr.state_right_edge, R.attr.state_has_morekeys }
+ }
+ };
+ private static final int STATE_NORMAL = 0;
+ private static final int STATE_HAS_MOREKEYS = 1;
+
+ public void setPreviewBackground(final boolean hasMoreKeys, final int position) {
+ final Drawable background = getBackground();
+ if (background == null) {
+ return;
+ }
+ final int hasMoreKeysState = hasMoreKeys ? STATE_HAS_MOREKEYS : STATE_NORMAL;
+ background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[position][hasMoreKeysState]);
+ }
+}
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 47b5c3344..72f8f87e4 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -92,3 +92,6 @@ include $(LOCAL_PATH)/CleanupNativeFileList.mk
#################### Unit test on host environment
include $(LOCAL_PATH)/HostUnitTests.mk
+
+#################### Unit test on target environment
+include $(LOCAL_PATH)/TargetUnitTests.mk
diff --git a/native/jni/TargetUnitTests.mk b/native/jni/TargetUnitTests.mk
new file mode 100644
index 000000000..12aae44ea
--- /dev/null
+++ b/native/jni/TargetUnitTests.mk
@@ -0,0 +1,55 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+######################################
+include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/NativeFileList.mk
+
+#################### Target library for unit test
+LATIN_IME_SRC_DIR := src
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
+LOCAL_MODULE := liblatinime_target_static_for_unittests
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(addprefix $(LATIN_IME_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
+# Here intentionally use libc++_shared rather than libc++_static because
+# $(BUILD_NATIVE_TEST) has not yet supported libc++_static.
+LOCAL_SDK_VERSION := 14
+LOCAL_NDK_STL_VARIANT := c++_shared
+include $(BUILD_STATIC_LIBRARY)
+
+#################### Target native tests
+include $(CLEAR_VARS)
+LATIN_IME_TEST_SRC_DIR := tests
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
+LOCAL_MODULE := liblatinime_target_unittests
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := \
+ $(addprefix $(LATIN_IME_TEST_SRC_DIR)/, $(LATIN_IME_CORE_TEST_FILES))
+LOCAL_STATIC_LIBRARIES += liblatinime_target_static_for_unittests
+# Here intentionally include external/libcxx/libcxx.mk rather because
+# $(BUILD_NATIVE_TEST) fails when LOCAL_NDK_STL_VARIANT is specified.
+include external/libcxx/libcxx.mk
+include $(BUILD_NATIVE_TEST)
+
+#################### Clean up the tmp vars
+LATIN_IME_SRC_DIR :=
+LATIN_IME_TEST_SRC_DIR :=
+include $(LOCAL_PATH)/CleanupNativeFileList.mk
diff --git a/native/jni/run-tests.sh b/native/jni/run-tests.sh
index 5b60e0d65..3da45270d 100755
--- a/native/jni/run-tests.sh
+++ b/native/jni/run-tests.sh
@@ -13,17 +13,56 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+function usage() {
+ echo "usage: source run-tests.sh [--host] [--target] [-h] [--help]" 1>&2
+ echo " --host: run test on the host environment" 1>&2
+ echo " --no-host: skip host test" 1>&2
+ echo " --target: run test on the target environment" 1>&2
+ echo " --no-target: skip target device test" 1>&2
+}
+
+# check script arguments
if [[ $(type -t mmm) != function ]]; then
-echo "Usage:" 1>&2
-echo " source $0" 1>&2
-echo " or" 1>&2
-echo " . $0" 1>&2
+usage
if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
fi
+show_usage=no
+enable_host_test=yes
+enable_target_device_test=no
+while [ "$1" != "" ]
+ do
+ case "$1" in
+ "-h") show_usage=yes;;
+ "--help") show_usage=yes;;
+ "--target") enable_target_device_test=yes;;
+ "--no-target") enable_target_device_test=no;;
+ "--host") enable_host_test=yes;;
+ "--no-host") enable_host_test=no;;
+ esac
+ shift
+done
+
+if [[ $show_usage == yes ]]; then
+ usage
+ if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
+fi
+
+target_test_name=liblatinime_target_unittests
+host_test_name=liblatinime_host_unittests
+
pushd $PWD > /dev/null
cd $(gettop)
mmm -j16 packages/inputmethods/LatinIME/native/jni || \
- make -j16 liblatinime_host_unittests
-${ANDROID_HOST_OUT}/bin/liblatinime_host_unittests
-popd > /dev/null \ No newline at end of file
+ make -j16 adb $target_test_name $host_test_name
+if [[ $enable_host_test == yes ]]; then
+ $ANDROID_HOST_OUT/bin/$host_test_name
+fi
+if [[ $enable_target_device_test == yes ]]; then
+ target_test_local=$ANDROID_PRODUCT_OUT/data/nativetest/$target_test_name/$target_test_name
+ target_test_device=/data/nativetest/$target_test_name/$target_test_name
+ adb push $target_test_local $target_test_device
+ adb shell $target_test_device
+ adb shell rm -rf $target_test_device
+fi
+popd > /dev/null
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
index 2cbc04154..3ef03f4bd 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
@@ -26,11 +26,13 @@ import org.xml.sax.SAXException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -51,14 +53,17 @@ public final class BinaryDictOffdeviceUtils {
public final static String ENCRYPTION = "encrypted";
private final static int MAX_DECODE_DEPTH = 8;
+ private final static int COPY_BUFFER_SIZE = 8192;
public static class DecoderChainSpec {
ArrayList<String> mDecoderSpec = new ArrayList<>();
File mFile;
+
public DecoderChainSpec addStep(final String stepDescription) {
mDecoderSpec.add(stepDescription);
return this;
}
+
public String describeChain() {
final StringBuilder s = new StringBuilder("raw");
for (final String step : mDecoderSpec) {
@@ -70,13 +75,10 @@ public final class BinaryDictOffdeviceUtils {
}
public static void copy(final InputStream input, final OutputStream output) throws IOException {
- final byte[] buffer = new byte[1000];
- final BufferedInputStream in = new BufferedInputStream(input);
- final BufferedOutputStream out = new BufferedOutputStream(output);
- for (int readBytes = in.read(buffer); readBytes >= 0; readBytes = in.read(buffer))
+ final byte[] buffer = new byte[COPY_BUFFER_SIZE];
+ for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer)) {
output.write(buffer, 0, readBytes);
- in.close();
- out.close();
+ }
}
/**
@@ -131,11 +133,15 @@ public final class BinaryDictOffdeviceUtils {
try {
final File dst = File.createTempFile(PREFIX, SUFFIX);
dst.deleteOnExit();
- final FileOutputStream dstStream = new FileOutputStream(dst);
- copy(Compress.getUncompressedStream(new BufferedInputStream(new FileInputStream(src))),
- new BufferedOutputStream(dstStream)); // #copy() closes the streams
- return dst;
- } catch (IOException e) {
+ try (
+ final InputStream input = Compress.getUncompressedStream(
+ new BufferedInputStream(new FileInputStream(src)));
+ final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
+ ) {
+ copy(input, output);
+ return dst;
+ }
+ } catch (final IOException e) {
// Could not uncompress the file: presumably the file is simply not a compressed file
return null;
}
@@ -150,20 +156,20 @@ public final class BinaryDictOffdeviceUtils {
try {
final File dst = File.createTempFile(PREFIX, SUFFIX);
dst.deleteOnExit();
- final FileOutputStream dstStream = new FileOutputStream(dst);
- copy(Crypt.getDecryptedStream(new BufferedInputStream(new FileInputStream(src))),
- dstStream); // #copy() closes the streams
- return dst;
- } catch (IOException e) {
+ try (
+ final InputStream input = Crypt.getDecryptedStream(
+ new BufferedInputStream(new FileInputStream(src)));
+ final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
+ ) {
+ copy(input, output);
+ return dst;
+ }
+ } catch (final IOException e) {
// Could not decrypt the file: presumably the file is simply not a crypted file
return null;
}
}
- static void crash(final String filename, final Exception e) {
- throw new RuntimeException("Can't read file " + filename, e);
- }
-
static FusionDictionary getDictionary(final String filename, final boolean report) {
final File file = new File(filename);
if (report) {
@@ -172,45 +178,40 @@ public final class BinaryDictOffdeviceUtils {
}
try {
if (XmlDictInputOutput.isXmlUnigramDictionary(filename)) {
- if (report) System.out.println("Format : XML unigram list");
+ if (report) {
+ System.out.println("Format : XML unigram list");
+ }
return XmlDictInputOutput.readDictionaryXml(
new BufferedInputStream(new FileInputStream(file)),
null /* shortcuts */, null /* bigrams */);
- } else {
- final DecoderChainSpec decodedSpec = getRawDictionaryOrNull(file);
- if (null == decodedSpec) {
- crash(filename, new RuntimeException(
- filename + " does not seem to be a dictionary file"));
- } else if (CombinedInputOutput.isCombinedDictionary(
- decodedSpec.mFile.getAbsolutePath())){
- if (report) {
- System.out.println("Format : Combined format");
- System.out.println("Packaging : " + decodedSpec.describeChain());
- System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- }
- return CombinedInputOutput.readDictionaryCombined(
- new BufferedInputStream(new FileInputStream(decodedSpec.mFile)));
- } else {
- final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(
- decodedSpec.mFile, 0, decodedSpec.mFile.length(),
- DictDecoder.USE_BYTEARRAY);
- if (report) {
- System.out.println("Format : Binary dictionary format");
- System.out.println("Packaging : " + decodedSpec.describeChain());
- System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- }
- return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
+ }
+ final DecoderChainSpec decodedSpec = getRawDictionaryOrNull(file);
+ if (null == decodedSpec) {
+ throw new RuntimeException("Does not seem to be a dictionary file " + filename);
+ }
+ if (CombinedInputOutput.isCombinedDictionary(decodedSpec.mFile.getAbsolutePath())) {
+ if (report) {
+ System.out.println("Format : Combined format");
+ System.out.println("Packaging : " + decodedSpec.describeChain());
+ System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
}
+ try (final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(decodedSpec.mFile), "UTF-8"))) {
+ return CombinedInputOutput.readDictionaryCombined(reader);
+ }
+ }
+ final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(
+ decodedSpec.mFile, 0, decodedSpec.mFile.length(),
+ DictDecoder.USE_BYTEARRAY);
+ if (report) {
+ System.out.println("Format : Binary dictionary format");
+ System.out.println("Packaging : " + decodedSpec.describeChain());
+ System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
}
- } catch (IOException e) {
- crash(filename, e);
- } catch (SAXException e) {
- crash(filename, e);
- } catch (ParserConfigurationException e) {
- crash(filename, e);
- } catch (UnsupportedFormatException e) {
- crash(filename, e);
+ return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
+ } catch (final IOException | SAXException | ParserConfigurationException |
+ UnsupportedFormatException e) {
+ throw new RuntimeException("Can't read file " + filename, e);
}
- return null;
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
index 6a0e1b7f0..23cbee81c 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
@@ -26,13 +26,9 @@ import com.android.inputmethod.latin.makedict.WordProperty;
import com.android.inputmethod.latin.utils.CombinedFormatUtils;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;
@@ -57,27 +53,15 @@ public class CombinedInputOutput {
* @return true if the file is in the combined format, false otherwise
*/
public static boolean isCombinedDictionary(final String filename) {
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(new File(filename)));
+ try (final BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String firstLine = reader.readLine();
while (firstLine.startsWith(COMMENT_LINE_STARTER)) {
firstLine = reader.readLine();
}
return firstLine.matches(
"^" + CombinedFormatUtils.DICTIONARY_TAG + "=[^:]+(:[^=]+=[^:]+)*");
- } catch (FileNotFoundException e) {
+ } catch (final IOException e) {
return false;
- } catch (IOException e) {
- return false;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
}
@@ -87,12 +71,11 @@ public class CombinedInputOutput {
* This is the public method that will read a combined file and return the corresponding memory
* representation.
*
- * @param source the file to read the data from.
+ * @param reader the buffered reader to read the data from.
* @return the in-memory representation of the dictionary.
*/
- public static FusionDictionary readDictionaryCombined(final InputStream source)
+ public static FusionDictionary readDictionaryCombined(final BufferedReader reader)
throws IOException {
- final BufferedReader reader = new BufferedReader(new InputStreamReader(source, "UTF-8"));
String headerLine = reader.readLine();
while (headerLine.startsWith(COMMENT_LINE_STARTER)) {
headerLine = reader.readLine();
@@ -218,11 +201,11 @@ public class CombinedInputOutput {
/**
* Writes a dictionary to a combined file.
*
- * @param destination a destination stream to write to.
+ * @param destination a destination writer.
* @param dict the dictionary to write.
*/
- public static void writeDictionaryCombined(
- final Writer destination, final FusionDictionary dict) throws IOException {
+ public static void writeDictionaryCombined(final BufferedWriter destination,
+ final FusionDictionary dict) throws IOException {
final TreeSet<WordProperty> wordPropertiesInDict = new TreeSet<>();
for (final WordProperty wordProperty : dict) {
// This for ordering by frequency, then by asciibetic order
@@ -232,6 +215,5 @@ public class CombinedInputOutput {
for (final WordProperty wordProperty : wordPropertiesInDict) {
destination.write(CombinedFormatUtils.formatWordProperty(wordProperty));
}
- destination.close();
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
index b7f48b522..728a159a0 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Compress.java
@@ -16,11 +16,6 @@
package com.android.inputmethod.latin.dicttool;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -32,8 +27,7 @@ public class Compress {
// This container class is not publicly instantiable.
}
- public static OutputStream getCompressedStream(final OutputStream out)
- throws java.io.IOException {
+ public static OutputStream getCompressedStream(final OutputStream out) throws IOException {
return new GZIPOutputStream(out);
}
@@ -43,7 +37,6 @@ public class Compress {
static public class Compressor extends Dicttool.Command {
public static final String COMMAND = "compress";
- public static final String STDIN_OR_STDOUT = "-";
public Compressor() {
}
@@ -61,17 +54,18 @@ public class Compress {
}
final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT;
final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT;
- final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in
- : new BufferedInputStream(new FileInputStream(new File(inFilename)));
- final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out
- : new BufferedOutputStream(new FileOutputStream(new File(outFilename)));
- BinaryDictOffdeviceUtils.copy(input, new GZIPOutputStream(output));
+ try (
+ final InputStream input = getFileInputStreamOrStdIn(inFilename);
+ final OutputStream compressedOutput = getCompressedStream(
+ getFileOutputStreamOrStdOut(outFilename))
+ ) {
+ BinaryDictOffdeviceUtils.copy(input, compressedOutput);
+ }
}
}
static public class Uncompressor extends Dicttool.Command {
public static final String COMMAND = "uncompress";
- public static final String STDIN_OR_STDOUT = "-";
public Uncompressor() {
}
@@ -89,11 +83,13 @@ public class Compress {
}
final String inFilename = mArgs.length >= 1 ? mArgs[0] : STDIN_OR_STDOUT;
final String outFilename = mArgs.length >= 2 ? mArgs[1] : STDIN_OR_STDOUT;
- final InputStream input = inFilename.equals(STDIN_OR_STDOUT) ? System.in
- : new BufferedInputStream(new FileInputStream(new File(inFilename)));
- final OutputStream output = outFilename.equals(STDIN_OR_STDOUT) ? System.out
- : new BufferedOutputStream(new FileOutputStream(new File(outFilename)));
- BinaryDictOffdeviceUtils.copy(new GZIPInputStream(input), output);
+ try (
+ final InputStream uncompressedInput = getUncompressedStream(
+ getFileInputStreamOrStdIn(inFilename));
+ final OutputStream output = getFileOutputStreamOrStdOut(outFilename)
+ ) {
+ BinaryDictOffdeviceUtils.copy(uncompressedInput, output);
+ }
}
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
index 37c8d4184..3d0557b5c 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -27,19 +27,23 @@ import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.Ver2DictEncoder;
import com.android.inputmethod.latin.makedict.Ver4DictEncoder;
+import org.xml.sax.SAXException;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.SAXException;
-
/**
* Main class/method for DictionaryMaker.
*/
@@ -279,22 +283,21 @@ public class DictionaryMaker {
*/
private static FusionDictionary readCombinedFile(final String combinedFilename)
throws FileNotFoundException, IOException {
- FileInputStream inStream = null;
- try {
- final File file = new File(combinedFilename);
- inStream = new FileInputStream(file);
- return CombinedInputOutput.readDictionaryCombined(inStream);
- } finally {
- if (null != inStream) {
- try {
- inStream.close();
- } catch (IOException e) {
- // do nothing
- }
- }
+ try (final BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(combinedFilename), "UTF-8"))
+ ) {
+ return CombinedInputOutput.readDictionaryCombined(reader);
}
}
+ private static BufferedInputStream getBufferedFileInputStream(final String filename)
+ throws FileNotFoundException {
+ if (filename == null) {
+ return null;
+ }
+ return new BufferedInputStream(new FileInputStream(filename));
+ }
+
/**
* Read a dictionary from a unigram XML file, and optionally a bigram XML file.
*
@@ -310,12 +313,13 @@ public class DictionaryMaker {
private static FusionDictionary readXmlFile(final String unigramXmlFilename,
final String shortcutXmlFilename, final String bigramXmlFilename)
throws FileNotFoundException, SAXException, IOException, ParserConfigurationException {
- final FileInputStream unigrams = new FileInputStream(new File(unigramXmlFilename));
- final FileInputStream shortcuts = null == shortcutXmlFilename ? null :
- new FileInputStream(new File(shortcutXmlFilename));
- final FileInputStream bigrams = null == bigramXmlFilename ? null :
- new FileInputStream(new File(bigramXmlFilename));
- return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams);
+ try (
+ final BufferedInputStream unigrams = getBufferedFileInputStream(unigramXmlFilename);
+ final BufferedInputStream shortcuts = getBufferedFileInputStream(shortcutXmlFilename);
+ final BufferedInputStream bigrams = getBufferedFileInputStream(bigramXmlFilename);
+ ) {
+ return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams);
+ }
}
/**
@@ -374,8 +378,9 @@ public class DictionaryMaker {
*/
private static void writeXmlDictionary(final String outputFilename,
final FusionDictionary dict) throws FileNotFoundException, IOException {
- XmlDictInputOutput.writeDictionaryXml(new BufferedWriter(new FileWriter(outputFilename)),
- dict);
+ try (final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
+ XmlDictInputOutput.writeDictionaryXml(writer, dict);
+ }
}
/**
@@ -388,7 +393,8 @@ public class DictionaryMaker {
*/
private static void writeCombinedDictionary(final String outputFilename,
final FusionDictionary dict) throws FileNotFoundException, IOException {
- CombinedInputOutput.writeDictionaryCombined(
- new BufferedWriter(new FileWriter(outputFilename)), dict);
+ try (final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
+ CombinedInputOutput.writeDictionaryCombined(writer, dict);
+ }
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
index 8ae035f64..e49b35084 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Dicttool.java
@@ -16,23 +16,63 @@
package com.android.inputmethod.latin.dicttool;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
public class Dicttool {
public static abstract class Command {
+ public static final String STDIN_OR_STDOUT = "-";
protected String[] mArgs;
+
public void setArgs(String[] args) throws IllegalArgumentException {
mArgs = args;
}
+
+ protected static InputStream getFileInputStreamOrStdIn(final String inFilename)
+ throws FileNotFoundException {
+ if (STDIN_OR_STDOUT.equals(inFilename)) {
+ return System.in;
+ }
+ return getFileInputStream(new File(inFilename));
+ }
+
+ protected static InputStream getFileInputStream(final File inFile)
+ throws FileNotFoundException {
+ return new BufferedInputStream(new FileInputStream(inFile));
+ }
+
+ protected static OutputStream getFileOutputStreamOrStdOut(final String outFilename)
+ throws FileNotFoundException {
+ if (STDIN_OR_STDOUT.equals(outFilename)) {
+ return System.out;
+ }
+ return getFileOutputStream(new File(outFilename));
+ }
+
+ protected static OutputStream getFileOutputStream(final File outFile)
+ throws FileNotFoundException {
+ return new BufferedOutputStream(new FileOutputStream(outFile));
+ }
+
abstract public String getHelp();
abstract public void run() throws Exception;
}
+
static HashMap<String, Class<? extends Command>> sCommands = new HashMap<>();
+
static {
CommandList.populate();
}
+
public static void addCommand(final String commandName, final Class<? extends Command> cls) {
sCommands.put(commandName, cls);
}
@@ -60,7 +100,7 @@ public class Dicttool {
return sCommands.containsKey(commandName);
}
- private Command getCommand(final String[] arguments) {
+ private static Command getCommand(final String[] arguments) {
final String commandName = arguments[0];
if (!isCommand(commandName)) {
throw new RuntimeException("Unknown command : " + commandName);
@@ -76,7 +116,7 @@ public class Dicttool {
* @param arguments the arguments passed to dicttool.
* @return 0 for success, an error code otherwise (always 1 at the moment)
*/
- private int execute(final String[] arguments) {
+ private static int execute(final String[] arguments) {
final Command command = getCommand(arguments);
try {
command.run();
@@ -95,6 +135,6 @@ public class Dicttool {
return;
}
// Exit with the success/error code from #execute() as status.
- System.exit(new Dicttool().execute(arguments));
+ System.exit(execute(arguments));
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
index dff3387be..1f6798269 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
@@ -21,8 +21,9 @@ import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
public class Package {
private Package() {
@@ -86,9 +87,13 @@ public class Package {
}
System.out.println("Packaging : " + decodedSpec.describeChain());
System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
- final FileOutputStream dstStream = new FileOutputStream(new File(mArgs[1]));
- BinaryDictOffdeviceUtils.copy(new BufferedInputStream(
- new FileInputStream(decodedSpec.mFile)), new BufferedOutputStream(dstStream));
+ try (
+ final InputStream input = getFileInputStream(decodedSpec.mFile);
+ final OutputStream output = new BufferedOutputStream(
+ getFileOutputStreamOrStdOut(mArgs[1]))
+ ) {
+ BinaryDictOffdeviceUtils.copy(input, output);
+ }
}
}
}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
index 7435fa7d6..bdec44761 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
@@ -23,13 +23,16 @@ import com.android.inputmethod.latin.makedict.ProbabilityInfo;
import com.android.inputmethod.latin.makedict.WeightedString;
import com.android.inputmethod.latin.makedict.WordProperty;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
+import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;
@@ -38,10 +41,6 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
/**
* Reads and writes XML files for a FusionDictionary.
*
@@ -57,8 +56,6 @@ public class XmlDictInputOutput {
private static final String WORD_ATTR = "word";
private static final String NOT_A_WORD_ATTR = "not_a_word";
- private static final String OPTIONS_KEY = "options";
-
/**
* SAX handler for a unigram XML file.
*/
@@ -120,7 +117,6 @@ public class XmlDictInputOutput {
final String attrName = attrs.getLocalName(attrIndex);
attributes.put(attrName, attrs.getValue(attrIndex));
}
- final String optionsString = attributes.get(OPTIONS_KEY);
mDictionary = new FusionDictionary(new PtNodeArray(),
new DictionaryOptions(attributes));
} else {
@@ -244,14 +240,13 @@ public class XmlDictInputOutput {
protected int getValueFromFreqString(final String freqString) {
if (WHITELIST_MARKER.equals(freqString)) {
return WHITELIST_FREQ_VALUE;
- } else {
- final int intValue = super.getValueFromFreqString(freqString);
- if (intValue < MIN_FREQ || intValue > MAX_FREQ) {
- throw new RuntimeException("Shortcut freq out of range. Accepted range is "
- + MIN_FREQ + ".." + MAX_FREQ);
- }
- return intValue;
}
+ final int intValue = super.getValueFromFreqString(freqString);
+ if (intValue < MIN_FREQ || intValue > MAX_FREQ) {
+ throw new RuntimeException("Shortcut freq out of range. Accepted range is "
+ + MIN_FREQ + ".." + MAX_FREQ);
+ }
+ return intValue;
}
// As per getAssocMap(), this never returns null.
@@ -269,23 +264,12 @@ public class XmlDictInputOutput {
* @return true if the file is in the unigram XML format, false otherwise
*/
public static boolean isXmlUnigramDictionary(final String filename) {
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(new File(filename)));
+ try (final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new FileInputStream(filename), "UTF-8"))) {
final String firstLine = reader.readLine();
return firstLine.matches("^\\s*<wordlist .*>\\s*$");
- } catch (FileNotFoundException e) {
+ } catch (final IOException e) {
return false;
- } catch (IOException e) {
- return false;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // do nothing
- }
- }
}
}
@@ -300,8 +284,8 @@ public class XmlDictInputOutput {
* @param bigrams the file to read the bigrams from, or null.
* @return the in-memory representation of the dictionary.
*/
- public static FusionDictionary readDictionaryXml(final InputStream unigrams,
- final InputStream shortcuts, final InputStream bigrams)
+ public static FusionDictionary readDictionaryXml(final BufferedInputStream unigrams,
+ final BufferedInputStream shortcuts, final BufferedInputStream bigrams)
throws SAXException, IOException, ParserConfigurationException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
@@ -350,8 +334,8 @@ public class XmlDictInputOutput {
* @param destination a destination stream to write to.
* @param dict the dictionary to write.
*/
- public static void writeDictionaryXml(Writer destination, FusionDictionary dict)
- throws IOException {
+ public static void writeDictionaryXml(final BufferedWriter destination,
+ final FusionDictionary dict) throws IOException {
final TreeSet<WordProperty> wordPropertiesInDict = new TreeSet<>();
for (WordProperty wordProperty : dict) {
wordPropertiesInDict.add(wordProperty);
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
index fccb654b0..0236a446d 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
@@ -62,13 +62,13 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
final File dst = File.createTempFile("testGetRawDict", ".tmp");
dst.deleteOnExit();
-
- final OutputStream out = Compress.getCompressedStream(
+ try (final OutputStream out = Compress.getCompressedStream(
Compress.getCompressedStream(
Compress.getCompressedStream(
- new BufferedOutputStream(new FileOutputStream(dst)))));
- final DictEncoder dictEncoder = new Ver2DictEncoder(out);
- dictEncoder.writeDictionary(dict, new FormatOptions(2, false));
+ new BufferedOutputStream(new FileOutputStream(dst)))))) {
+ final DictEncoder dictEncoder = new Ver2DictEncoder(out);
+ dictEncoder.writeDictionary(dict, new FormatOptions(2, false));
+ }
// Test for an actually compressed dictionary and its contents
final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec =
@@ -96,11 +96,11 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
// Randomly create some 4k file containing garbage
final File dst = File.createTempFile("testGetRawDict", ".tmp");
dst.deleteOnExit();
- final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
- for (int i = 0; i < 1024; ++i) {
- out.write(0x12345678);
+ try (final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst))) {
+ for (int i = 0; i < 1024; ++i) {
+ out.write(0x12345678);
+ }
}
- out.close();
// Test that a random data file actually fails
assertNull("Wrongly identified data file",
@@ -108,12 +108,12 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
final File gzDst = File.createTempFile("testGetRawDict", ".tmp");
gzDst.deleteOnExit();
- final OutputStream gzOut =
- Compress.getCompressedStream(new BufferedOutputStream(new FileOutputStream(gzDst)));
- for (int i = 0; i < 1024; ++i) {
- gzOut.write(0x12345678);
+ try (final OutputStream gzOut = Compress.getCompressedStream(
+ new BufferedOutputStream(new FileOutputStream(gzDst)))) {
+ for (int i = 0; i < 1024; ++i) {
+ gzOut.write(0x12345678);
+ }
}
- gzOut.close();
// Test that a compressed random data file actually fails
assertNull("Wrongly identified data file",