aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values-land/dimens.xml3
-rw-r--r--java/res/values/attrs.xml5
-rw-r--r--java/res/values/dimens.xml3
-rw-r--r--java/res/xml/kbd_emoji_category1.xml30
-rw-r--r--java/res/xml/kbd_emoji_category2.xml30
-rw-r--r--java/res/xml/kbd_emoji_category3.xml30
-rw-r--r--java/res/xml/kbd_emoji_category4.xml30
-rw-r--r--java/res/xml/kbd_emoji_category5.xml30
-rw-r--r--java/res/xml/kbd_emoji_category6.xml30
-rw-r--r--java/res/xml/kbd_emoji_recents.xml30
-rw-r--r--java/res/xml/keyboard_layout_set_emoji.xml44
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java85
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java78
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java10
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java2
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/DictDecoder.java17
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java13
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java2
-rw-r--r--java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java21
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java48
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java3
22 files changed, 506 insertions, 47 deletions
diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml
index c78c25f86..d411cb954 100644
--- a/java/res/values-land/dimens.xml
+++ b/java/res/values-land/dimens.xml
@@ -79,4 +79,7 @@
<dimen name="gesture_floating_preview_text_offset">54dp</dimen>
<dimen name="gesture_floating_preview_horizontal_padding">23dp</dimen>
<dimen name="gesture_floating_preview_vertical_padding">15dp</dimen>
+
+ <!-- Emoji keyboard -->
+ <fraction name="emoji_keyboard_key_width">8.3333%p</fraction>
</resources>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 4c5097654..7ebaf75be 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -215,6 +215,11 @@
<attr name="iconEmojiKey" format="reference" />
</declare-styleable>
+ <declare-styleable name="Keyboard_GridRows">
+ <attr name="codesArray" format="reference" />
+ <attr name="textsArray" format="reference" />
+ </declare-styleable>
+
<declare-styleable name="Keyboard_Key">
<!-- The unicode value that this key outputs.
Code value represented in hexadecimal prefixed with "0x" or code value reference using
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index 98ae76cb1..bb5f0bb8b 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -123,6 +123,9 @@
<dimen name="gesture_floating_preview_vertical_padding">16dp</dimen>
<dimen name="gesture_floating_preview_round_radius">3dp</dimen>
+ <!-- Emoji keyboard -->
+ <fraction name="emoji_keyboard_key_width">14.2857%p</fraction>
+
<!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. -->
<dimen name="accessibility_edge_slop">8dp</dimen>
diff --git a/java/res/xml/kbd_emoji_category1.xml b/java/res/xml/kbd_emoji_category1.xml
new file mode 100644
index 000000000..92b0c3fbf
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category1.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_faces"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_category2.xml b/java/res/xml/kbd_emoji_category2.xml
new file mode 100644
index 000000000..17d36c52f
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category2.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_objects"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_category3.xml b/java/res/xml/kbd_emoji_category3.xml
new file mode 100644
index 000000000..9000a3a11
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category3.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_nature"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_category4.xml b/java/res/xml/kbd_emoji_category4.xml
new file mode 100644
index 000000000..e79e124e7
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category4.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_places"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_category5.xml b/java/res/xml/kbd_emoji_category5.xml
new file mode 100644
index 000000000..07b3d908c
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category5.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_symbols"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_category6.xml b/java/res/xml/kbd_emoji_category6.xml
new file mode 100644
index 000000000..a07966b07
--- /dev/null
+++ b/java/res/xml/kbd_emoji_category6.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:textsArray="@array/emoji_emoticons"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/kbd_emoji_recents.xml b/java/res/xml/kbd_emoji_recents.xml
new file mode 100644
index 000000000..8b4fa958c
--- /dev/null
+++ b/java/res/xml/kbd_emoji_recents.xml
@@ -0,0 +1,30 @@
+<?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.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+ latin:keyWidth="@fraction/emoji_keyboard_key_width"
+ latin:keyLetterSize="90%p"
+>
+ <GridRows
+ latin:codesArray="@array/emoji_recents"
+ latin:keyLabelFlags="fontNormal"
+ latin:backgroundType="empty" />
+</Keyboard>
diff --git a/java/res/xml/keyboard_layout_set_emoji.xml b/java/res/xml/keyboard_layout_set_emoji.xml
new file mode 100644
index 000000000..98e6b6b5c
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_emoji.xml
@@ -0,0 +1,44 @@
+<?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.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="emojiRecents"
+ latin:elementKeyboard="@xml/kbd_emoji_recents" />
+ <Element
+ latin:elementName="emojiCategory1"
+ latin:elementKeyboard="@xml/kbd_emoji_category1" />
+ <Element
+ latin:elementName="emojiCategory2"
+ latin:elementKeyboard="@xml/kbd_emoji_category2" />
+ <Element
+ latin:elementName="emojiCategory3"
+ latin:elementKeyboard="@xml/kbd_emoji_category3" />
+ <Element
+ latin:elementName="emojiCategory4"
+ latin:elementKeyboard="@xml/kbd_emoji_category4" />
+ <Element
+ latin:elementName="emojiCategory5"
+ latin:elementKeyboard="@xml/kbd_emoji_category5" />
+ <Element
+ latin:elementName="emojiCategory6"
+ latin:elementKeyboard="@xml/kbd_emoji_category6" />
+</KeyboardLayoutSet>
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 0b3737e48..23f037fbd 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -51,6 +51,11 @@ public class Keyboard {
/** Total width of the keyboard, including the padding and keys */
public final int mOccupiedWidth;
+ /** Base height of the keyboard, used to calculate rows' height */
+ public final int mBaseHeight;
+ /** Base width of the keyboard, used to calculate keys' width */
+ public final int mBaseWidth;
+
/** The padding above the keyboard */
public final int mTopPadding;
/** Default gap between rows */
@@ -84,6 +89,8 @@ public class Keyboard {
mThemeId = params.mThemeId;
mOccupiedHeight = params.mOccupiedHeight;
mOccupiedWidth = params.mOccupiedWidth;
+ mBaseHeight = params.mBaseHeight;
+ mBaseWidth = params.mBaseWidth;
mMostCommonKeyHeight = params.mMostCommonKeyHeight;
mMostCommonKeyWidth = params.mMostCommonKeyWidth;
mMoreKeysTemplate = params.mMoreKeysTemplate;
@@ -109,6 +116,8 @@ public class Keyboard {
mThemeId = keyboard.mThemeId;
mOccupiedHeight = keyboard.mOccupiedHeight;
mOccupiedWidth = keyboard.mOccupiedWidth;
+ mBaseHeight = keyboard.mBaseHeight;
+ mBaseWidth = keyboard.mBaseWidth;
mMostCommonKeyHeight = keyboard.mMostCommonKeyHeight;
mMostCommonKeyWidth = keyboard.mMostCommonKeyWidth;
mMoreKeysTemplate = keyboard.mMoreKeysTemplate;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
new file mode 100644
index 000000000..c10fdbace
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import com.android.inputmethod.latin.Constants;
+
+/**
+ * The string parser of codesArray specification for <GridRows />. The attribute codesArray is an
+ * array of string.
+ * Each element of the array defines a key label by specifying a code point as a hexadecimal string.
+ * A key label may consist of multiple code points separated by comma.
+ * Each element of the array optionally can have an output text definition after vertical bar
+ * marker. An output text may consist of multiple code points separated by comma.
+ * The format of the codesArray element should be:
+ * <pre>
+ * codePointInHex[,codePoint2InHex]*(|outputTextCodePointInHex[,outputTextCodePoint2InHex]*)?
+ * </pre>
+ */
+// TODO: Write unit tests for this class.
+public final class CodesArrayParser {
+ // Constants for parsing.
+ private static final char COMMA = ',';
+ private static final char VERTICAL_BAR = '|';
+ private static final String COMMA_STRING = ",";
+ private static final int BASE_HEX = 16;
+
+ private CodesArrayParser() {
+ // This utility class is not publicly instantiable.
+ }
+
+ private static String getLabelSpec(final String codesArraySpec) {
+ final int pos = codesArraySpec.indexOf(VERTICAL_BAR);
+ return (pos < 0) ? codesArraySpec : codesArraySpec.substring(0, pos);
+ }
+
+ public static String parseLabel(final String codesArraySpec) {
+ final String labelSpec = getLabelSpec(codesArraySpec);
+ final StringBuilder sb = new StringBuilder();
+ for (final String codeInHex : labelSpec.split(COMMA_STRING)) {
+ final int codePoint = Integer.parseInt(codeInHex, BASE_HEX);
+ sb.appendCodePoint(codePoint);
+ }
+ return sb.toString();
+ }
+
+ private static String getCodeSpec(final String codesArraySpec) {
+ final int pos = codesArraySpec.indexOf(VERTICAL_BAR);
+ return (pos < 0) ? codesArraySpec : codesArraySpec.substring(pos + 1);
+ }
+
+ public static int parseCode(final String codesArraySpec) {
+ final String codeSpec = getCodeSpec(codesArraySpec);
+ if (codeSpec.indexOf(COMMA) < 0) {
+ return Integer.parseInt(codeSpec, BASE_HEX);
+ }
+ return Constants.CODE_OUTPUT_TEXT;
+ }
+
+ public static String parseOutputText(final String codesArraySpec) {
+ final String codeSpec = getCodeSpec(codesArraySpec);
+ if (codeSpec.indexOf(COMMA) < 0) {
+ return null;
+ }
+ final StringBuilder sb = new StringBuilder();
+ for (final String codeInHex : codeSpec.split(COMMA_STRING)) {
+ final int codePoint = Integer.parseInt(codeInHex, BASE_HEX);
+ sb.appendCodePoint(codePoint);
+ }
+ return sb.toString();
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 3f0773e15..8c70389ba 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -29,6 +29,7 @@ import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.RunInLocale;
@@ -113,6 +114,7 @@ import java.util.Locale;
* </pre>
*/
+// TODO: Write unit tests for this class.
public class KeyboardBuilder<KP extends KeyboardParams> {
private static final String BUILDER_TAG = "Keyboard.Builder";
private static final boolean DEBUG = false;
@@ -120,6 +122,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
// Keyboard XML Tags
private static final String TAG_KEYBOARD = "Keyboard";
private static final String TAG_ROW = "Row";
+ private static final String TAG_GRID_ROWS = "GridRows";
private static final String TAG_KEY = "Key";
private static final String TAG_SPACER = "Spacer";
private static final String TAG_INCLUDE = "include";
@@ -312,6 +315,9 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
startRow(row);
}
parseRowContent(parser, row, skip);
+ } else if (TAG_GRID_ROWS.equals(tag)) {
+ if (DEBUG) startTag("<%s>%s", TAG_GRID_ROWS, skip ? " skipped" : "");
+ parseGridRows(parser, skip);
} else if (TAG_INCLUDE.equals(tag)) {
parseIncludeKeyboardContent(parser, skip);
} else if (TAG_SWITCH.equals(tag)) {
@@ -389,6 +395,73 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
}
+ private void parseGridRows(final XmlPullParser parser, final boolean skip)
+ throws XmlPullParserException, IOException {
+ if (skip) {
+ XmlParseUtils.checkEndTag(TAG_GRID_ROWS, parser);
+ if (DEBUG) {
+ startEndTag("<%s /> skipped", TAG_GRID_ROWS);
+ }
+ return;
+ }
+ final KeyboardRow gridRows = new KeyboardRow(mResources, mParams, parser, mCurrentY);
+ final TypedArray gridRowAttr = mResources.obtainAttributes(
+ Xml.asAttributeSet(parser), R.styleable.Keyboard_GridRows);
+ final int codesArrayId = gridRowAttr.getResourceId(
+ R.styleable.Keyboard_GridRows_codesArray, 0);
+ final int textsArrayId = gridRowAttr.getResourceId(
+ R.styleable.Keyboard_GridRows_textsArray, 0);
+ gridRowAttr.recycle();
+ if (codesArrayId == 0 && textsArrayId == 0) {
+ throw new XmlParseUtils.ParseException(
+ "Missing codesArray or textsArray attributes", parser);
+ }
+ if (codesArrayId != 0 && textsArrayId != 0) {
+ throw new XmlParseUtils.ParseException(
+ "Both codesArray and textsArray attributes specifed", parser);
+ }
+ final String[] array = mResources.getStringArray(
+ codesArrayId != 0 ? codesArrayId : textsArrayId);
+ final int counts = array.length;
+ final float keyWidth = gridRows.getKeyWidth(null, 0.0f);
+ final int numColumns = (int)(mParams.mOccupiedWidth / keyWidth);
+ for (int index = 0; index < counts; index += numColumns) {
+ final KeyboardRow row = new KeyboardRow(mResources, mParams, parser, mCurrentY);
+ startRow(row);
+ for (int c = 0; c < numColumns; c++) {
+ final int i = index + c;
+ if (i >= counts) {
+ break;
+ }
+ final String label;
+ final int code;
+ final String outputText;
+ if (codesArrayId != 0) {
+ final String codeArraySpec = array[i];
+ label = CodesArrayParser.parseLabel(codeArraySpec);
+ code = CodesArrayParser.parseCode(codeArraySpec);
+ outputText = CodesArrayParser.parseOutputText(codeArraySpec);
+ } else {
+ final String textArraySpec = array[i];
+ // TODO: Utilize KeySpecParser or write more generic TextsArrayParser.
+ label = textArraySpec;
+ code = Constants.CODE_OUTPUT_TEXT;
+ outputText = textArraySpec + (char)Constants.CODE_SPACE;
+ }
+ final int x = (int)row.getKeyX(null);
+ final int y = row.getKeyY();
+ final Key key = new Key(mParams, label, null /* hintLabel */, 0 /* iconId */,
+ code, outputText, x, y, (int)keyWidth, (int)row.getRowHeight(),
+ row.getDefaultKeyLabelFlags(), row.getDefaultBackgroundType());
+ endKey(key);
+ row.advanceXPos(keyWidth);
+ }
+ endRow(row);
+ }
+
+ XmlParseUtils.checkEndTag(TAG_GRID_ROWS, parser);
+ }
+
private void parseKey(final XmlPullParser parser, final KeyboardRow row, final boolean skip)
throws XmlPullParserException, IOException {
if (skip) {
@@ -744,7 +817,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
private void endKeyboard() {
- // nothing to do here.
+ // {@link #parseGridRows(XmlPullParser,boolean)} may populate keyboard rows higher than
+ // previously expected.
+ final int actualHeight = mCurrentY - mParams.mVerticalGap + mParams.mBottomPadding;
+ mParams.mOccupiedHeight = Math.max(mParams.mOccupiedHeight, actualHeight);
}
private void addEdgeSpace(final float width, final KeyboardRow row) {
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index b95db2183..79f5ad8bd 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -326,15 +326,11 @@ public class BinaryDictEncoderUtils {
}
int nodeSize = getNodeHeaderSize(ptNode, formatOptions);
if (ptNode.isTerminal()) nodeSize += FormatSpec.PTNODE_FREQUENCY_SIZE;
- if (null == ptNode.mChildren && formatOptions.mSupportsDynamicUpdate) {
+ if (formatOptions.mSupportsDynamicUpdate) {
nodeSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
} else if (null != ptNode.mChildren) {
- if (formatOptions.mSupportsDynamicUpdate) {
- nodeSize += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
- } else {
- nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
- nodeSize + size, ptNode.mChildren));
- }
+ nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
+ nodeSize + size, ptNode.mChildren));
}
nodeSize += getShortcutListSize(ptNode.mShortcutTargets);
if (null != ptNode.mBigrams) {
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index a08e28c8b..106f02519 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -148,7 +148,7 @@ public final class BinaryDictIOUtils {
* @throws IOException if the file can't be read.
* @throws UnsupportedFormatException if the format of the file is not recognized.
*/
- public static void readUnigramsAndBigramsBinary(final Ver3DictDecoder dictDecoder,
+ /* package */ static void readUnigramsAndBigramsBinary(final Ver3DictDecoder dictDecoder,
final Map<Integer, String> words, final Map<Integer, Integer> frequencies,
final Map<Integer, ArrayList<PendingAttribute>> bigrams) throws IOException,
UnsupportedFormatException {
diff --git a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
index d5fcacc09..11a3f0b3a 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
@@ -29,6 +29,8 @@ import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.TreeMap;
/**
* An interface of binary dictionary decoder.
@@ -71,6 +73,21 @@ public interface DictDecoder {
public int getTerminalPosition(final String word)
throws IOException, UnsupportedFormatException;
+ /**
+ * Reads unigrams and bigrams from the binary file.
+ * Doesn't store a full memory representation of the dictionary.
+ *
+ * @param words the map to store the address as a key and the word as a value.
+ * @param frequencies the map to store the address as a key and the frequency as a value.
+ * @param bigrams the map to store the address as a key and the list of address as a value.
+ * @throws IOException if the file can't be read.
+ * @throws UnsupportedFormatException if the format of the file is not recognized.
+ */
+ public void readUnigramsAndBigramsBinary(final TreeMap<Integer, String> words,
+ final TreeMap<Integer, Integer> frequencies,
+ final TreeMap<Integer, ArrayList<PendingAttribute>> bigrams)
+ throws IOException, UnsupportedFormatException;
+
// Flags for DictionaryBufferFactory.
public static final int USE_READONLY_BYTEBUFFER = 0x01000000;
public static final int USE_BYTEARRAY = 0x02000000;
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
index 77e6393ee..1fff9b49e 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver3DictDecoder.java
@@ -31,6 +31,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.TreeMap;
/**
* An implementation of DictDecoder for version 3 binary dictionary.
@@ -317,4 +318,16 @@ public class Ver3DictDecoder implements DictDecoder {
}
return BinaryDictIOUtils.getTerminalPosition(this, word);
}
+
+ @Override
+ public void readUnigramsAndBigramsBinary(final TreeMap<Integer, String> words,
+ final TreeMap<Integer, Integer> frequencies,
+ final TreeMap<Integer, ArrayList<PendingAttribute>> bigrams)
+ throws IOException, UnsupportedFormatException {
+ if (mDictBuffer == null) {
+ openDictBuffer();
+ }
+ BinaryDictIOUtils.readUnigramsAndBigramsBinary(this, words, frequencies, bigrams);
+ }
+
}
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index cec6dbab4..021bf0825 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -27,10 +27,8 @@ import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
-import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
index 9d3d8a5da..99788f6f2 100644
--- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java
@@ -32,7 +32,8 @@ import com.android.inputmethod.latin.personalization.UserHistoryDictionaryBigram
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
/**
* Reads and writes Binary files for a UserHistoryDictionary.
@@ -119,12 +120,11 @@ public final class UserHistoryDictIOUtils {
*/
public static void readDictionaryBinary(final Ver3DictDecoder dictDecoder,
final OnAddWordListener dict) {
- final Map<Integer, String> unigrams = CollectionUtils.newTreeMap();
- final Map<Integer, Integer> frequencies = CollectionUtils.newTreeMap();
- final Map<Integer, ArrayList<PendingAttribute>> bigrams = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, String> unigrams = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, Integer> frequencies = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, ArrayList<PendingAttribute>> bigrams = CollectionUtils.newTreeMap();
try {
- BinaryDictIOUtils.readUnigramsAndBigramsBinary(dictDecoder, unigrams, frequencies,
- bigrams);
+ dictDecoder.readUnigramsAndBigramsBinary(unigrams, frequencies, bigrams);
} catch (IOException e) {
Log.e(TAG, "IO exception while reading file", e);
} catch (UnsupportedFormatException e) {
@@ -139,10 +139,11 @@ public final class UserHistoryDictIOUtils {
* Adds all unigrams and bigrams in maps to OnAddWordListener.
*/
@UsedForTesting
- static void addWordsFromWordMap(final Map<Integer, String> unigrams,
- final Map<Integer, Integer> frequencies,
- final Map<Integer, ArrayList<PendingAttribute>> bigrams, final OnAddWordListener to) {
- for (Map.Entry<Integer, String> entry : unigrams.entrySet()) {
+ static void addWordsFromWordMap(final TreeMap<Integer, String> unigrams,
+ final TreeMap<Integer, Integer> frequencies,
+ final TreeMap<Integer, ArrayList<PendingAttribute>> bigrams,
+ final OnAddWordListener to) {
+ for (Entry<Integer, String> entry : unigrams.entrySet()) {
final String word1 = entry.getValue();
final int unigramFrequency = frequencies.get(entry.getKey());
to.setUnigram(word1, null, unigramFrequency);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index bb5b96a48..72ec5a302 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -39,10 +39,10 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
+import java.util.TreeMap;
/**
* Unit tests for BinaryDictDecoderUtils and BinaryDictEncoderUtils.
@@ -61,13 +61,13 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
private static final int USE_BYTE_ARRAY = 1;
private static final int USE_BYTE_BUFFER = 2;
- private static final List<String> sWords = CollectionUtils.newArrayList();
+ private static final ArrayList<String> sWords = CollectionUtils.newArrayList();
private static final SparseArray<List<Integer>> sEmptyBigrams =
CollectionUtils.newSparseArray();
private static final SparseArray<List<Integer>> sStarBigrams = CollectionUtils.newSparseArray();
private static final SparseArray<List<Integer>> sChainBigrams =
CollectionUtils.newSparseArray();
- private static final Map<String, List<String>> sShortcuts = CollectionUtils.newHashMap();
+ private static final HashMap<String, List<String>> sShortcuts = CollectionUtils.newHashMap();
private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
@@ -177,7 +177,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
* Adds unigrams to the dictionary.
*/
private void addUnigrams(final int number, final FusionDictionary dict,
- final List<String> words, final Map<String, List<String>> shortcutMap) {
+ final List<String> words, final HashMap<String, List<String>> shortcutMap) {
for (int i = 0; i < number; ++i) {
final String word = words.get(i);
final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList();
@@ -234,7 +234,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
private void checkDictionary(final FusionDictionary dict, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap) {
+ final SparseArray<List<Integer>> bigrams,
+ final HashMap<String, List<String>> shortcutMap) {
assertNotNull(dict);
// check unigram
@@ -255,7 +256,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
// check shortcut
if (shortcutMap != null) {
- for (final Map.Entry<String, List<String>> entry : shortcutMap.entrySet()) {
+ for (final Entry<String, List<String>> entry : shortcutMap.entrySet()) {
assertTrue(words.contains(entry.getKey()));
final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
entry.getKey());
@@ -278,8 +279,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
// Tests for readDictionaryBinary and writeDictionaryBinary
private long timeReadingAndCheckDict(final File file, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcutMap,
- final int bufferType) {
+ final SparseArray<List<Integer>> bigrams,
+ final HashMap<String, List<String>> shortcutMap, final int bufferType) {
long now, diff = -1;
FusionDictionary dict = null;
@@ -302,7 +303,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
// Tests for readDictionaryBinary and writeDictionaryBinary
private String runReadAndWrite(final List<String> words,
- final SparseArray<List<Integer>> bigrams, final Map<String, List<String>> shortcuts,
+ final SparseArray<List<Integer>> bigrams, final HashMap<String, List<String>> shortcuts,
final int bufferType, final FormatSpec.FormatOptions formatOptions,
final String message) {
File file = null;
@@ -387,9 +388,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
private void checkWordMap(final List<String> expectedWords,
final SparseArray<List<Integer>> expectedBigrams,
- final Map<Integer, String> resultWords,
- final Map<Integer, Integer> resultFrequencies,
- final Map<Integer, ArrayList<PendingAttribute>> resultBigrams) {
+ final TreeMap<Integer, String> resultWords,
+ final TreeMap<Integer, Integer> resultFrequencies,
+ final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams) {
// check unigrams
final Set<String> actualWordsSet = new HashSet<String>(resultWords.values());
final Set<String> expectedWordsSet = new HashSet<String>(expectedWords);
@@ -400,7 +401,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
// check bigrams
- final Map<String, List<String>> expBigrams = new HashMap<String, List<String>>();
+ final HashMap<String, List<String>> expBigrams = new HashMap<String, List<String>>();
for (int i = 0; i < expectedBigrams.size(); ++i) {
final String word1 = expectedWords.get(expectedBigrams.keyAt(i));
for (int w2 : expectedBigrams.valueAt(i)) {
@@ -411,7 +412,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
}
- final Map<String, List<String>> actBigrams = new HashMap<String, List<String>>();
+ final HashMap<String, List<String>> actBigrams = new HashMap<String, List<String>>();
for (Entry<Integer, ArrayList<PendingAttribute>> entry : resultBigrams.entrySet()) {
final String word1 = resultWords.get(entry.getKey());
final int unigramFreq = resultFrequencies.get(entry.getKey());
@@ -435,10 +436,10 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final SparseArray<List<Integer>> bigrams, final int bufferType) {
FileInputStream inStream = null;
- final Map<Integer, String> resultWords = CollectionUtils.newTreeMap();
- final Map<Integer, ArrayList<PendingAttribute>> resultBigrams =
+ final TreeMap<Integer, String> resultWords = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams =
CollectionUtils.newTreeMap();
- final Map<Integer, Integer> resultFreqs = CollectionUtils.newTreeMap();
+ final TreeMap<Integer, Integer> resultFreqs = CollectionUtils.newTreeMap();
long now = -1, diff = -1;
try {
@@ -446,8 +447,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
dictDecoder.openDictBuffer();
assertNotNull("Can't get buffer.", dictDecoder.getDictBuffer());
now = System.currentTimeMillis();
- BinaryDictIOUtils.readUnigramsAndBigramsBinary(dictDecoder, resultWords, resultFreqs,
- resultBigrams);
+ dictDecoder.readUnigramsAndBigramsBinary(resultWords, resultFreqs, resultBigrams);
diff = System.currentTimeMillis() - now;
} catch (IOException e) {
Log.e(TAG, "IOException", e);
@@ -467,7 +467,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
return diff;
}
- private String runReadUnigramsAndBigramsBinary(final List<String> words,
+ private String runReadUnigramsAndBigramsBinary(final ArrayList<String> words,
final SparseArray<List<Integer>> bigrams, final int bufferType,
final FormatSpec.FormatOptions formatOptions, final String message) {
File file = null;
@@ -496,8 +496,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
+ " : " + message + " : " + outputOptions(bufferType, formatOptions);
}
- private void runReadUnigramsAndBigramsTests(final List<String> results, final int bufferType,
- final FormatSpec.FormatOptions formatOptions) {
+ private void runReadUnigramsAndBigramsTests(final ArrayList<String> results,
+ final int bufferType, final FormatSpec.FormatOptions formatOptions) {
results.add(runReadUnigramsAndBigramsBinary(sWords, sEmptyBigrams, bufferType,
formatOptions, "unigram"));
results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
@@ -507,7 +507,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
- final List<String> results = CollectionUtils.newArrayList();
+ final ArrayList<String> results = CollectionUtils.newArrayList();
runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2);
runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
@@ -519,7 +519,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
public void testReadUnigramsAndBigramsBinaryWithByteArray() {
- final List<String> results = CollectionUtils.newArrayList();
+ final ArrayList<String> results = CollectionUtils.newArrayList();
runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2);
runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
index 7a6708bb3..8e0c6dfe2 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
@@ -22,8 +22,6 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-import com.android.inputmethod.latin.makedict.DictDecoder.
- DictionaryBufferFromWritableByteBufferFactory;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
@@ -128,6 +126,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
}
}
+ @SuppressWarnings("unused")
private static void printBinaryFile(final Ver3DictDecoder dictDecoder)
throws IOException, UnsupportedFormatException {
final FileHeader fileHeader = dictDecoder.readHeader();