From 08ae0d5ca03ed455827e82222df249d1cafb5d71 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 11 Apr 2013 12:08:36 +0900 Subject: [PATCH] Add TypefaceUtils Change-Id: I2d939bc1e3279253902b28ff12bbf7861716b64d --- .../inputmethod/keyboard/KeyboardView.java | 146 +++++++----------- .../keyboard/MainKeyboardView.java | 19 +-- .../keyboard/MoreKeysKeyboard.java | 26 ++-- .../keyboard/MoreKeysKeyboardView.java | 2 +- .../inputmethod/keyboard/TypefaceUtils.java | 91 +++++++++++ .../latin/suggestions/MoreSuggestions.java | 18 +-- .../suggestions/MoreSuggestionsView.java | 2 +- .../suggestions/SuggestionStripView.java | 2 +- 8 files changed, 178 insertions(+), 128 deletions(-) create mode 100644 java/src/com/android/inputmethod/keyboard/TypefaceUtils.java 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 sTextHeightCache = CollectionUtils.newSparseArray(); - // This sparse array caches key label text width in pixel indexed by key label text size. - private static final SparseArray 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..c2a9bfe3c 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; @@ -257,7 +258,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,10 +289,10 @@ 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; } else { - width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth); + width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth, + context.getResources()); height = parentKeyboard.mMostCommonKeyHeight; } final int dividerWidth; @@ -310,22 +310,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 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 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/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(