Loading java/src/com/android/inputmethod/keyboard/KeyboardView.java +55 −91 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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' }; Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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); } Loading @@ -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. Loading @@ -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); Loading @@ -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); Loading @@ -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) { Loading @@ -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); } } Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); Loading @@ -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, Loading @@ -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, Loading @@ -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); if (key == null) { paint.setTypeface(mKeyDrawParams.mTypeface); paint.setTextSize(mKeyDrawParams.mLabelSize); } else { paint.setTypeface(key.selectTypeface(mKeyDrawParams)); paint.setTextSize(key.selectTextSize(mKeyDrawParams)); } return paint; } Loading java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +10 −9 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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); } } Loading @@ -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; } Loading @@ -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)) { Loading java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +11 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -258,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}. Loading Loading @@ -290,10 +290,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; Loading @@ -311,22 +311,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; Loading java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading java/src/com/android/inputmethod/keyboard/TypefaceUtils.java 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * 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(); } } Loading
java/src/com/android/inputmethod/keyboard/KeyboardView.java +55 −91 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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' }; Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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); } Loading @@ -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. Loading @@ -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); Loading @@ -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); Loading @@ -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) { Loading @@ -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); } } Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); Loading @@ -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, Loading @@ -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, Loading @@ -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); if (key == null) { paint.setTypeface(mKeyDrawParams.mTypeface); paint.setTextSize(mKeyDrawParams.mLabelSize); } else { paint.setTypeface(key.selectTypeface(mKeyDrawParams)); paint.setTextSize(key.selectTextSize(mKeyDrawParams)); } return paint; } Loading
java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +10 −9 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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); } } Loading @@ -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; } Loading @@ -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)) { Loading
java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +11 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -258,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}. Loading Loading @@ -290,10 +290,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; Loading @@ -311,22 +311,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; Loading
java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
java/src/com/android/inputmethod/keyboard/TypefaceUtils.java 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * 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(); } }