diff options
Diffstat (limited to 'java')
11 files changed, 228 insertions, 179 deletions
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 783946252..a13021bd0 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -90,6 +90,7 @@ android:summary="@string/gesture_input_summary" android:persistent="true" android:defaultValue="true" /> + <!-- TODO: Move these two options to the advanced settings. --> <CheckBoxPreference android:key="pref_gesture_floating_preview_text" android:title="@string/gesture_floating_preview_text" @@ -139,10 +140,6 @@ android:summary="@string/include_other_imes_in_language_switch_list_summary" android:persistent="true" android:defaultValue="false" /> - <PreferenceScreen - android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings" - android:key="custom_input_styles" - android:title="@string/custom_input_styles_title" /> <!-- Values for popup dismiss delay are added programmatically --> <CheckBoxPreference android:key="pref_sliding_key_input_preview" @@ -150,6 +147,10 @@ android:summary="@string/sliding_key_input_preview_summary" android:persistent="true" android:defaultValue="true" /> + <PreferenceScreen + android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings" + android:key="custom_input_styles" + android:title="@string/custom_input_styles_title" /> <ListPreference android:key="pref_key_preview_popup_dismiss_delay" android:title="@string/key_preview_popup_dismiss_delay" /> diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 43d28be5d..e4e75c342 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -26,10 +26,8 @@ import android.graphics.Paint.Align; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Region; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.util.SparseArray; import android.view.View; import com.android.inputmethod.keyboard.internal.KeyDrawParams; @@ -73,15 +71,15 @@ import java.util.HashSet; */ public class KeyboardView extends View { // XML attributes - protected final KeyVisualAttributes mKeyVisualAttributes; + private final KeyVisualAttributes mKeyVisualAttributes; private final int mKeyLabelHorizontalPadding; private final float mKeyHintLetterPadding; private final float mKeyPopupHintLetterPadding; private final float mKeyShiftedLetterHintPadding; private final float mKeyTextShadowRadius; - protected final float mVerticalCorrection; - protected final Drawable mKeyBackground; - protected final Rect mKeyBackgroundPadding = new Rect(); + private final float mVerticalCorrection; + private final Drawable mKeyBackground; + private final Rect mKeyBackgroundPadding = new Rect(); // HORIZONTAL ELLIPSIS "...", character for popup hint. private static final String POPUP_HINT_CHAR = "\u2026"; @@ -113,10 +111,6 @@ public class KeyboardView extends View { private final Canvas mOffscreenCanvas = new Canvas(); private final Paint mPaint = new Paint(); private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); - // This sparse array caches key label text height in pixel indexed by key label text size. - private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray(); - // This sparse array caches key label text width in pixel indexed by key label text size. - private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray(); private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; @@ -134,15 +128,15 @@ public class KeyboardView extends View { mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset( R.styleable.KeyboardView_keyLabelHorizontalPadding, 0); mKeyHintLetterPadding = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_keyHintLetterPadding, 0); + R.styleable.KeyboardView_keyHintLetterPadding, 0.0f); mKeyPopupHintLetterPadding = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_keyPopupHintLetterPadding, 0); + R.styleable.KeyboardView_keyPopupHintLetterPadding, 0.0f); mKeyShiftedLetterHintPadding = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0); + R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0.0f); mKeyTextShadowRadius = keyboardViewAttr.getFloat( R.styleable.KeyboardView_keyTextShadowRadius, 0.0f); mVerticalCorrection = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_verticalCorrection, 0); + R.styleable.KeyboardView_verticalCorrection, 0.0f); keyboardViewAttr.recycle(); final TypedArray keyAttr = context.obtainStyledAttributes(attrs, @@ -185,6 +179,14 @@ public class KeyboardView extends View { return mKeyboard; } + protected float getVerticalCorrection() { + return mVerticalCorrection; + } + + protected void updateKeyDrawParams(final int keyHeight) { + mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes); + } + @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { if (mKeyboard != null) { @@ -213,7 +215,7 @@ public class KeyboardView extends View { } onDrawKeyboard(mOffscreenCanvas); } - canvas.drawBitmap(mOffscreenBuffer, 0, 0, null); + canvas.drawBitmap(mOffscreenBuffer, 0.0f, 0.0f, null); } private boolean maybeAllocateOffscreenBuffer() { @@ -333,7 +335,7 @@ public class KeyboardView extends View { canvas.translate(bgX, bgY); background.draw(canvas); if (LatinImeLogger.sVISUALDEBUG) { - drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint()); + drawRectangle(canvas, 0.0f, 0.0f, bgWidth, bgHeight, 0x80c00000, new Paint()); } canvas.translate(-bgX, -bgY); } @@ -347,7 +349,7 @@ public class KeyboardView extends View { final float centerY = keyHeight * 0.5f; if (LatinImeLogger.sVISUALDEBUG) { - drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint()); + drawRectangle(canvas, 0.0f, 0.0f, keyWidth, keyHeight, 0x800000c0, new Paint()); } // Draw key label. @@ -357,14 +359,16 @@ public class KeyboardView extends View { final String label = key.mLabel; paint.setTypeface(key.selectTypeface(params)); paint.setTextSize(key.selectTextSize(params)); - final float labelCharHeight = getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint); - final float labelCharWidth = getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint); + final float labelCharHeight = TypefaceUtils.getCharHeight( + KEY_LABEL_REFERENCE_CHAR, paint); + final float labelCharWidth = TypefaceUtils.getCharWidth( + KEY_LABEL_REFERENCE_CHAR, paint); // Vertical label text alignment. - final float baseline = centerY + labelCharHeight / 2; + final float baseline = centerY + labelCharHeight / 2.0f; // Horizontal label text alignment - float labelWidth = 0; + float labelWidth = 0.0f; if (key.isAlignLeft()) { positionX = mKeyLabelHorizontalPadding; paint.setTextAlign(Align.LEFT); @@ -373,31 +377,31 @@ public class KeyboardView extends View { paint.setTextAlign(Align.RIGHT); } else if (key.isAlignLeftOfCenter()) { // TODO: Parameterise this? - positionX = centerX - labelCharWidth * 7 / 4; + positionX = centerX - labelCharWidth * 7.0f / 4.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasLabelWithIconLeft() && icon != null) { - labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; - positionX = centerX + labelWidth / 2; + positionX = centerX + labelWidth / 2.0f; paint.setTextAlign(Align.RIGHT); } else if (key.hasLabelWithIconRight() && icon != null) { - labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; - positionX = centerX - labelWidth / 2; + positionX = centerX - labelWidth / 2.0f; paint.setTextAlign(Align.LEFT); } else { positionX = centerX; paint.setTextAlign(Align.CENTER); } if (key.needsXScale()) { - paint.setTextScaleX( - Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint))); + paint.setTextScaleX(Math.min(1.0f, + (keyWidth * MAX_LABEL_RATIO) / TypefaceUtils.getLabelWidth(label, paint))); } paint.setColor(key.selectTextColor(params)); if (key.isEnabled()) { // Set a drop shadow for the text - paint.setShadowLayer(mKeyTextShadowRadius, 0, 0, params.mTextShadowColor); + paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor); } else { // Make label invisible paint.setColor(Color.TRANSPARENT); @@ -405,7 +409,7 @@ public class KeyboardView extends View { blendAlpha(paint, params.mAnimAlpha); canvas.drawText(label, 0, label.length(), positionX, baseline, paint); // Turn off drop shadow and reset x-scale. - paint.setShadowLayer(0, 0, 0, 0); + paint.setShadowLayer(0.0f, 0.0f, 0.0f, Color.TRANSPARENT); paint.setTextScaleX(1.0f); if (icon != null) { @@ -413,10 +417,10 @@ public class KeyboardView extends View { final int iconHeight = icon.getIntrinsicHeight(); final int iconY = (keyHeight - iconHeight) / 2; if (key.hasLabelWithIconLeft()) { - final int iconX = (int)(centerX - labelWidth / 2); + final int iconX = (int)(centerX - labelWidth / 2.0f); drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight); } else if (key.hasLabelWithIconRight()) { - final int iconX = (int)(centerX + labelWidth / 2 - iconWidth); + final int iconX = (int)(centerX + labelWidth / 2.0f - iconWidth); drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight); } } @@ -439,20 +443,23 @@ public class KeyboardView extends View { // The hint label is placed just right of the key label. Used mainly on // "phone number" layout. // TODO: Generalize the following calculations. - hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2; - hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2; + hintX = positionX + + TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2.0f; + hintY = centerY + + TypefaceUtils.getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasShiftedLetterHint()) { // The hint label is placed at top-right corner of the key. Used mainly on tablet. hintX = keyWidth - mKeyShiftedLetterHintPadding - - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; + - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; paint.getFontMetrics(mFontMetrics); hintY = -mFontMetrics.top; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() // The hint letter is placed at top-right corner of the key. Used mainly on phone. hintX = keyWidth - mKeyHintLetterPadding - - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2; + - TypefaceUtils.getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) + / 2.0f; hintY = -paint.ascent(); paint.setTextAlign(Align.CENTER); } @@ -506,7 +513,7 @@ public class KeyboardView extends View { paint.setColor(params.mHintLabelColor); paint.setTextAlign(Align.CENTER); final float hintX = keyWidth - mKeyHintLetterPadding - - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; + - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; final float hintY = keyHeight - mKeyPopupHintLetterPadding; canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint); @@ -517,54 +524,6 @@ public class KeyboardView extends View { } } - private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) { - final int labelSize = (int)paint.getTextSize(); - final Typeface face = paint.getTypeface(); - final int codePointOffset = referenceChar << 15; - if (face == Typeface.DEFAULT) { - return codePointOffset + labelSize; - } else if (face == Typeface.DEFAULT_BOLD) { - return codePointOffset + labelSize + 0x1000; - } else if (face == Typeface.MONOSPACE) { - return codePointOffset + labelSize + 0x2000; - } else { - return codePointOffset + labelSize; - } - } - - // Working variable for the following methods. - private final Rect mTextBounds = new Rect(); - - private float getCharHeight(final char[] referenceChar, final Paint paint) { - final int key = getCharGeometryCacheKey(referenceChar[0], paint); - final Float cachedValue = sTextHeightCache.get(key); - if (cachedValue != null) - return cachedValue; - - paint.getTextBounds(referenceChar, 0, 1, mTextBounds); - final float height = mTextBounds.height(); - sTextHeightCache.put(key, height); - return height; - } - - private float getCharWidth(final char[] referenceChar, final Paint paint) { - final int key = getCharGeometryCacheKey(referenceChar[0], paint); - final Float cachedValue = sTextWidthCache.get(key); - if (cachedValue != null) - return cachedValue; - - paint.getTextBounds(referenceChar, 0, 1, mTextBounds); - final float width = mTextBounds.width(); - sTextWidthCache.put(key, width); - return width; - } - - // TODO: Remove this method. - public float getLabelWidth(final String label, final Paint paint) { - paint.getTextBounds(label, 0, label.length(), mTextBounds); - return mTextBounds.width(); - } - protected static void drawIcon(final Canvas canvas, final Drawable icon, final int x, final int y, final int width, final int height) { canvas.translate(x, y); @@ -578,7 +537,7 @@ public class KeyboardView extends View { paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(1.0f); paint.setColor(color); - canvas.drawLine(0, y, w, y, paint); + canvas.drawLine(0.0f, y, w, y, paint); } private static void drawVerticalLine(final Canvas canvas, final float x, final float h, @@ -586,7 +545,7 @@ public class KeyboardView extends View { paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(1.0f); paint.setColor(color); - canvas.drawLine(x, 0, x, h, paint); + canvas.drawLine(x, 0.0f, x, h, paint); } private static void drawRectangle(final Canvas canvas, final float x, final float y, @@ -595,15 +554,20 @@ public class KeyboardView extends View { paint.setStrokeWidth(1.0f); paint.setColor(color); canvas.translate(x, y); - canvas.drawRect(0, 0, w, h, paint); + canvas.drawRect(0.0f, 0.0f, w, h, paint); canvas.translate(-x, -y); } - public Paint newDefaultLabelPaint() { + public Paint newLabelPaint(final Key key) { final Paint paint = new Paint(); paint.setAntiAlias(true); - paint.setTypeface(mKeyDrawParams.mTypeface); - paint.setTextSize(mKeyDrawParams.mLabelSize); + if (key == null) { + paint.setTypeface(mKeyDrawParams.mTypeface); + paint.setTextSize(mKeyDrawParams.mLabelSize); + } else { + paint.setTypeface(key.selectTypeface(mKeyDrawParams)); + paint.setTextSize(key.selectTextSize(mKeyDrawParams)); + } return paint; } diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 7dfbea353..ba78d014a 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -530,9 +530,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistance, 0); + R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0); + R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); mKeyDetector = new KeyDetector( keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr); @@ -655,7 +655,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mKeyTimerHandler.cancelLongPressTimer(); super.setKeyboard(keyboard); mKeyDetector.setKeyboard( - keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection); + keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection()); PointerTracker.setKeyDetector(mKeyDetector); mTouchScreenRegulator.setKeyboardGeometry(keyboard.mOccupiedWidth); mMoreKeysKeyboardCache.clear(); @@ -1329,7 +1329,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // Overlay a dark rectangle to dim. if (mNeedsToDimEntireKeyboard) { - canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundDimAlphaPaint); + canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mBackgroundDimAlphaPaint); } } @@ -1353,9 +1353,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } } - private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { + private static boolean fitsTextIntoWidth(final int width, final String text, + final Paint paint) { paint.setTextScaleX(1.0f); - final float textWidth = getLabelWidth(text, paint); + final float textWidth = TypefaceUtils.getLabelWidth(text, paint); if (textWidth < width) { return true; } @@ -1366,12 +1367,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } paint.setTextScaleX(scaleX); - return getLabelWidth(text, paint) < width; + return TypefaceUtils.getLabelWidth(text, paint) < width; } // Layout language name on spacebar. - private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype, - final int width) { + private static String layoutLanguageOnSpacebar(final Paint paint, + final InputMethodSubtype subtype, final int width) { // Choose appropriate language name to fit into the width. final String fullText = getFullDisplayName(subtype); if (fitsTextIntoWidth(width, fullText, paint)) { diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 66c30149c..ae08a5953 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -17,6 +17,7 @@ package com.android.inputmethod.keyboard; import android.content.Context; +import android.content.res.Resources; import android.graphics.Paint; import android.graphics.drawable.Drawable; @@ -73,10 +74,11 @@ public final class MoreKeysKeyboard extends Keyboard { final int rowHeight, final int coordXInParent, final int parentKeyboardWidth, final boolean isFixedColumnOrder, final int dividerWidth) { mIsFixedOrder = isFixedColumnOrder; - if (parentKeyboardWidth / keyWidth < maxColumns) { + if (parentKeyboardWidth / keyWidth < Math.min(numKeys, maxColumns)) { throw new IllegalArgumentException( "Keyboard is too small to hold more keys keyboard: " - + parentKeyboardWidth + " " + keyWidth + " " + maxColumns); + + parentKeyboardWidth + " " + keyWidth + " " + + numKeys + " " + maxColumns); } mDefaultKeyWidth = keyWidth; mDefaultRowHeight = rowHeight; @@ -257,7 +259,6 @@ public final class MoreKeysKeyboard extends Keyboard { private static final float LABEL_PADDING_RATIO = 0.2f; private static final float DIVIDER_RATIO = 0.2f; - /** * The builder of MoreKeysKeyboard. * @param context the context of {@link MoreKeysKeyboardView}. @@ -289,11 +290,23 @@ public final class MoreKeysKeyboard extends Keyboard { // be considered because the vertical positions of both backgrounds were already // adjusted with their bottom paddings deducted. width = keyPreviewDrawParams.mPreviewVisibleWidth; - height = keyPreviewDrawParams.mPreviewVisibleHeight - + mParams.mVerticalGap; + height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap; + // TODO: Remove this check. + if (width == 0) { + throw new IllegalArgumentException( + "Zero width key detected: " + parentKey + " in " + parentKeyboard.mId); + } } else { - width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth); + width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth, + context.getResources()); height = parentKeyboard.mMostCommonKeyHeight; + // TODO: Remove this check. + if (width == 0) { + throw new IllegalArgumentException( + "Zero width calculated: " + parentKey + + " moreKeys=" + java.util.Arrays.toString(parentKey.mMoreKeys) + + " in " + parentKeyboard.mId); + } } final int dividerWidth; if (parentKey.needsDividersInMoreKeys()) { @@ -310,22 +323,18 @@ public final class MoreKeysKeyboard extends Keyboard { } private static int getMaxKeyWidth(final KeyboardView view, final Key parentKey, - final int minKeyWidth) { - final int padding = (int)(view.getResources() - .getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding) - + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0)); - final Paint paint = view.newDefaultLabelPaint(); - paint.setTypeface(parentKey.selectTypeface(view.mKeyDrawParams)); - paint.setTextSize(parentKey.selectMoreKeyTextSize(view.mKeyDrawParams)); + final int minKeyWidth, final Resources res) { + final float padding = + res.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding) + + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0.0f); + final Paint paint = view.newLabelPaint(parentKey); int maxWidth = minKeyWidth; for (final MoreKeySpec spec : parentKey.mMoreKeys) { final String label = spec.mLabel; // If the label is single letter, minKeyWidth is enough to hold the label. if (label != null && StringUtils.codePointCount(label) > 1) { - final int width = (int)view.getLabelWidth(label, paint) + padding; - if (maxWidth < width) { - maxWidth = width; - } + maxWidth = Math.max(maxWidth, + (int)(TypefaceUtils.getLabelWidth(label, paint) + padding)); } } return maxWidth; diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 0d42ab2fe..a356eb119 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -71,7 +71,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel public void setKeyboard(final Keyboard keyboard) { super.setKeyboard(keyboard); mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), - -getPaddingTop() + mVerticalCorrection); + -getPaddingTop() + getVerticalCorrection()); } @Override diff --git a/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java b/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java new file mode 100644 index 000000000..6a54e119c --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/TypefaceUtils.java @@ -0,0 +1,91 @@ +/* + * 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; + +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.util.SparseArray; + +import com.android.inputmethod.latin.CollectionUtils; + +public final class TypefaceUtils { + private TypefaceUtils() { + // This utility class is not publicly instantiable. + } + + // This sparse array caches key label text height in pixel indexed by key label text size. + private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray(); + // Working variable for the following method. + private static final Rect sTextHeightBounds = new Rect(); + + public static float getCharHeight(final char[] referenceChar, final Paint paint) { + final int key = getCharGeometryCacheKey(referenceChar[0], paint); + synchronized (sTextHeightCache) { + final Float cachedValue = sTextHeightCache.get(key); + if (cachedValue != null) { + return cachedValue; + } + + paint.getTextBounds(referenceChar, 0, 1, sTextHeightBounds); + final float height = sTextHeightBounds.height(); + sTextHeightCache.put(key, height); + return height; + } + } + + // This sparse array caches key label text width in pixel indexed by key label text size. + private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray(); + // Working variable for the following method. + private static final Rect sTextWidthBounds = new Rect(); + + public static float getCharWidth(final char[] referenceChar, final Paint paint) { + final int key = getCharGeometryCacheKey(referenceChar[0], paint); + synchronized (sTextWidthCache) { + final Float cachedValue = sTextWidthCache.get(key); + if (cachedValue != null) { + return cachedValue; + } + + paint.getTextBounds(referenceChar, 0, 1, sTextWidthBounds); + final float width = sTextWidthBounds.width(); + sTextWidthCache.put(key, width); + return width; + } + } + + private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) { + final int labelSize = (int)paint.getTextSize(); + final Typeface face = paint.getTypeface(); + final int codePointOffset = referenceChar << 15; + if (face == Typeface.DEFAULT) { + return codePointOffset + labelSize; + } else if (face == Typeface.DEFAULT_BOLD) { + return codePointOffset + labelSize + 0x1000; + } else if (face == Typeface.MONOSPACE) { + return codePointOffset + labelSize + 0x2000; + } else { + return codePointOffset + labelSize; + } + } + + public static float getLabelWidth(final String label, final Paint paint) { + final Rect textBounds = new Rect(); + paint.getTextBounds(label, 0, label.length(), textBounds); + return textBounds.width(); + } +} diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index e7c7e2b8a..17d281518 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -647,7 +647,7 @@ public final class FusionDictionary implements Iterable<Word> { if (index < codePoints.length) return null; if (!currentGroup.isTerminal()) return null; - if (DBG && !codePoints.equals(checker.toString())) return null; + if (DBG && !string.equals(checker.toString())) return null; return currentGroup; } @@ -853,16 +853,19 @@ public final class FusionDictionary implements Iterable<Word> { if (currentPos.pos.hasNext()) { final CharGroup currentGroup = currentPos.pos.next(); currentPos.length = mCurrentString.length(); - for (int i : currentGroup.mChars) + for (int i : currentGroup.mChars) { mCurrentString.append(Character.toChars(i)); + } if (null != currentGroup.mChildren) { currentPos = new Position(currentGroup.mChildren.mData); + currentPos.length = mCurrentString.length(); mPositions.addLast(currentPos); } - if (currentGroup.mFrequency >= 0) + if (currentGroup.mFrequency >= 0) { return new Word(mCurrentString.toString(), currentGroup.mFrequency, currentGroup.mShortcutTargets, currentGroup.mBigrams, currentGroup.mIsNotAWord, currentGroup.mIsBlacklistEntry); + } } else { mPositions.removeLast(); currentPos = mPositions.getLast(); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java index 2c18b6e38..0c480eaba 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -16,12 +16,11 @@ package com.android.inputmethod.latin.spellcheck; +import android.util.SparseIntArray; + import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; -import java.util.TreeMap; - public final class SpellCheckerProximityInfo extends ProximityInfo { public SpellCheckerProximityInfo(final int script) { super(getProximityForScript(script), PROXIMITY_GRID_WIDTH, PROXIMITY_GRID_HEIGHT); @@ -43,29 +42,14 @@ public final class SpellCheckerProximityInfo extends ProximityInfo { public static final int NOT_A_COORDINATE_PAIR = -1; // Helper methods - static void buildProximityIndices(final int[] proximity, - final TreeMap<Integer, Integer> indices) { - for (int i = 0; i < proximity.length; i += ROW_SIZE) { - if (NUL != proximity[i]) indices.put(proximity[i], i / ROW_SIZE); + static void buildProximityIndices(final int[] proximity, final int rowSize, + final SparseIntArray indices) { + for (int i = 0; i < proximity.length; i += rowSize) { + if (NUL != proximity[i]) indices.put(proximity[i], i / rowSize); } } - static int computeIndex(final int characterCode, - final TreeMap<Integer, Integer> indices) { - final Integer result = indices.get(characterCode); - if (null == result) return NOT_AN_INDEX; - return result; - } - private static final class Latin { - // This is a map from the code point to the index in the PROXIMITY array. - // At the time the native code to read the binary dictionary needs the proximity info be - // passed as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input - // character. - // Since we need to build such an array, we want to be able to search in our big proximity - // data quickly by character, and a map is probably the best way to do this. - private static final TreeMap<Integer, Integer> INDICES = CollectionUtils.newTreeMap(); - // The proximity here is the union of // - the proximity for a QWERTY keyboard. // - the proximity for an AZERTY keyboard. @@ -125,17 +109,20 @@ public final class SpellCheckerProximityInfo extends ProximityInfo { NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, }; - static { - buildProximityIndices(PROXIMITY, INDICES); - } + // This is a mapping array from the code point to the index in the PROXIMITY array. + // When we check the spelling of a word, we need to pass (x,y) coordinates to the native + // code for each letter of the word. These are most easily computed from the index in the + // PROXIMITY array. Since we'll need to do that very often, the index lookup from the code + // point needs to be as fast as possible, and a map is probably the best way to do this. + // To avoid unnecessary boxing conversion to Integer, here we use SparseIntArray. + static final SparseIntArray INDICES = new SparseIntArray(PROXIMITY.length / ROW_SIZE); - static int getIndexOf(int characterCode) { - return computeIndex(characterCode, INDICES); + static { + buildProximityIndices(PROXIMITY, ROW_SIZE, INDICES); } } private static final class Cyrillic { - private static final TreeMap<Integer, Integer> INDICES = CollectionUtils.newTreeMap(); // TODO: The following table is solely based on the keyboard layout. Consult with Russian // speakers on commonly misspelled words/letters. /* @@ -286,17 +273,14 @@ public final class SpellCheckerProximityInfo extends ProximityInfo { NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, }; - static { - buildProximityIndices(PROXIMITY, INDICES); - } + static final SparseIntArray INDICES = new SparseIntArray(PROXIMITY.length / ROW_SIZE); - static int getIndexOf(int characterCode) { - return computeIndex(characterCode, INDICES); + static { + buildProximityIndices(PROXIMITY, ROW_SIZE, INDICES); } } private static final class Greek { - private static final TreeMap<Integer, Integer> INDICES = CollectionUtils.newTreeMap(); // TODO: The following table is solely based on the keyboard layout. Consult with Greek // speakers on commonly misspelled words/letters. /* @@ -427,12 +411,10 @@ public final class SpellCheckerProximityInfo extends ProximityInfo { NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, }; - static { - buildProximityIndices(PROXIMITY, INDICES); - } + static final SparseIntArray INDICES = new SparseIntArray(PROXIMITY.length / ROW_SIZE); - static int getIndexOf(int characterCode) { - return computeIndex(characterCode, INDICES); + static { + buildProximityIndices(PROXIMITY, ROW_SIZE, INDICES); } } @@ -452,11 +434,11 @@ public final class SpellCheckerProximityInfo extends ProximityInfo { private static int getIndexOfCodeForScript(final int codePoint, final int script) { switch (script) { case AndroidSpellCheckerService.SCRIPT_LATIN: - return Latin.getIndexOf(codePoint); + return Latin.INDICES.get(codePoint, NOT_AN_INDEX); case AndroidSpellCheckerService.SCRIPT_CYRILLIC: - return Cyrillic.getIndexOf(codePoint); + return Cyrillic.INDICES.get(codePoint, NOT_AN_INDEX); case AndroidSpellCheckerService.SCRIPT_GREEK: - return Greek.getIndexOf(codePoint); + return Greek.INDICES.get(codePoint, NOT_AN_INDEX); default: throw new RuntimeException("Wrong script supplied: " + script); } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index ed408bb3c..3037669c0 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -16,12 +16,14 @@ package com.android.inputmethod.latin.suggestions; +import android.content.Context; import android.content.res.Resources; import android.graphics.Paint; import android.graphics.drawable.Drawable; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.TypefaceUtils; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; @@ -50,16 +52,12 @@ public final class MoreSuggestions extends Keyboard { super(); } - // TODO: Remove {@link MoreSuggestionsView} argument. public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth, - final int minWidth, final int maxRow, final MoreSuggestionsView view) { + final int minWidth, final int maxRow, final Paint paint, final Resources res) { clearKeys(); - final Resources res = view.getResources(); mDivider = res.getDrawable(R.drawable.more_suggestions_divider); mDividerWidth = mDivider.getIntrinsicWidth(); - final int padding = (int) res.getDimension( - R.dimen.more_suggestions_key_horizontal_padding); - final Paint paint = view.newDefaultLabelPaint(); + final float padding = res.getDimension(R.dimen.more_suggestions_key_horizontal_padding); int row = 0; int pos = fromPos, rowStartPos = fromPos; @@ -67,7 +65,7 @@ public final class MoreSuggestions extends Keyboard { while (pos < size) { final String word = suggestions.getWord(pos); // TODO: Should take care of text x-scaling. - mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding; + mWidths[pos] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding); final int numColumn = pos - rowStartPos + 1; final int columnWidth = (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn; @@ -169,8 +167,8 @@ public final class MoreSuggestions extends Keyboard { private int mFromPos; private int mToPos; - public Builder(final MoreSuggestionsView paneView) { - super(paneView.getContext(), new MoreSuggestionsParam()); + public Builder(final Context context, final MoreSuggestionsView paneView) { + super(context, new MoreSuggestionsParam()); mPaneView = paneView; } @@ -183,7 +181,7 @@ public final class MoreSuggestions extends Keyboard { mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight); final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow, - mPaneView); + mPaneView.newLabelPaint(null /* key */), mResources); mFromPos = fromPos; mToPos = fromPos + count; mSuggestions = suggestions; diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 438820d17..94715cd84 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -43,7 +43,7 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView { } public void updateKeyboardGeometry(final int keyHeight) { - mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes); + updateKeyDrawParams(keyHeight); } @Override diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index eeaf828a7..4ef36fa46 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -596,7 +596,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null); mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer .findViewById(R.id.more_suggestions_view); - mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView); + mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView); final Resources res = context.getResources(); mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset( |