Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.latin.utils;
     18 
     19 import android.graphics.Paint;
     20 import android.graphics.Rect;
     21 import android.graphics.Typeface;
     22 import android.util.SparseArray;
     23 
     24 public final class TypefaceUtils {
     25     private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
     26     private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
     27 
     28     private TypefaceUtils() {
     29         // This utility class is not publicly instantiable.
     30     }
     31 
     32     // This sparse array caches key label text height in pixel indexed by key label text size.
     33     private static final SparseArray<Float> sTextHeightCache = new SparseArray<>();
     34     // Working variable for the following method.
     35     private static final Rect sTextHeightBounds = new Rect();
     36 
     37     private static float getCharHeight(final char[] referenceChar, final Paint paint) {
     38         final int key = getCharGeometryCacheKey(referenceChar[0], paint);
     39         synchronized (sTextHeightCache) {
     40             final Float cachedValue = sTextHeightCache.get(key);
     41             if (cachedValue != null) {
     42                 return cachedValue;
     43             }
     44 
     45             paint.getTextBounds(referenceChar, 0, 1, sTextHeightBounds);
     46             final float height = sTextHeightBounds.height();
     47             sTextHeightCache.put(key, height);
     48             return height;
     49         }
     50     }
     51 
     52     // This sparse array caches key label text width in pixel indexed by key label text size.
     53     private static final SparseArray<Float> sTextWidthCache = new SparseArray<>();
     54     // Working variable for the following method.
     55     private static final Rect sTextWidthBounds = new Rect();
     56 
     57     private static float getCharWidth(final char[] referenceChar, final Paint paint) {
     58         final int key = getCharGeometryCacheKey(referenceChar[0], paint);
     59         synchronized (sTextWidthCache) {
     60             final Float cachedValue = sTextWidthCache.get(key);
     61             if (cachedValue != null) {
     62                 return cachedValue;
     63             }
     64 
     65             paint.getTextBounds(referenceChar, 0, 1, sTextWidthBounds);
     66             final float width = sTextWidthBounds.width();
     67             sTextWidthCache.put(key, width);
     68             return width;
     69         }
     70     }
     71 
     72     private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) {
     73         final int labelSize = (int)paint.getTextSize();
     74         final Typeface face = paint.getTypeface();
     75         final int codePointOffset = referenceChar << 15;
     76         if (face == Typeface.DEFAULT) {
     77             return codePointOffset + labelSize;
     78         } else if (face == Typeface.DEFAULT_BOLD) {
     79             return codePointOffset + labelSize + 0x1000;
     80         } else if (face == Typeface.MONOSPACE) {
     81             return codePointOffset + labelSize + 0x2000;
     82         } else {
     83             return codePointOffset + labelSize;
     84         }
     85     }
     86 
     87     public static float getReferenceCharHeight(final Paint paint) {
     88         return getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint);
     89     }
     90 
     91     public static float getReferenceCharWidth(final Paint paint) {
     92         return getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint);
     93     }
     94 
     95     public static float getReferenceDigitWidth(final Paint paint) {
     96         return getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint);
     97     }
     98 
     99     // Working variable for the following method.
    100     private static final Rect sStringWidthBounds = new Rect();
    101 
    102     public static float getStringWidth(final String string, final Paint paint) {
    103         synchronized (sStringWidthBounds) {
    104             paint.getTextBounds(string, 0, string.length(), sStringWidthBounds);
    105             return sStringWidthBounds.width();
    106         }
    107     }
    108 }
    109