Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2015 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 android.graphics;
     18 
     19 import android.graphics.Paint;
     20 import android.test.InstrumentationTestCase;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 
     23 import java.util.Arrays;
     24 import java.util.HashSet;
     25 
     26 /**
     27  * PaintTest tests {@link Paint}.
     28  */
     29 public class PaintTest extends InstrumentationTestCase {
     30     private static final String FONT_PATH = "fonts/HintedAdvanceWidthTest-Regular.ttf";
     31 
     32     static void assertEquals(String message, float[] expected, float[] actual) {
     33         if (expected.length != actual.length) {
     34             fail(message + " expected array length:<" + expected.length + "> but was:<"
     35                     + actual.length + ">");
     36         }
     37         for (int i = 0; i < expected.length; ++i) {
     38             if (expected[i] != actual[i]) {
     39                 fail(message + " expected array element[" +i + "]:<" + expected[i] + ">but was:<"
     40                         + actual[i] + ">");
     41             }
     42         }
     43     }
     44 
     45     static class HintingTestCase {
     46         public final String mText;
     47         public final float mTextSize;
     48         public final float[] mWidthWithoutHinting;
     49         public final float[] mWidthWithHinting;
     50 
     51         public HintingTestCase(String text, float textSize, float[] widthWithoutHinting,
     52                                float[] widthWithHinting) {
     53             mText = text;
     54             mTextSize = textSize;
     55             mWidthWithoutHinting = widthWithoutHinting;
     56             mWidthWithHinting = widthWithHinting;
     57         }
     58     }
     59 
     60     // Following test cases are only valid for HintedAdvanceWidthTest-Regular.ttf in assets/fonts.
     61     HintingTestCase[] HINTING_TESTCASES = {
     62         new HintingTestCase("H", 11f, new float[] { 7f }, new float[] { 13f }),
     63         new HintingTestCase("O", 11f, new float[] { 7f }, new float[] { 13f }),
     64 
     65         new HintingTestCase("H", 13f, new float[] { 8f }, new float[] { 14f }),
     66         new HintingTestCase("O", 13f, new float[] { 9f }, new float[] { 15f }),
     67 
     68         new HintingTestCase("HO", 11f, new float[] { 7f, 7f }, new float[] { 13f, 13f }),
     69         new HintingTestCase("OH", 11f, new float[] { 7f, 7f }, new float[] { 13f, 13f }),
     70 
     71         new HintingTestCase("HO", 13f, new float[] { 8f, 9f }, new float[] { 14f, 15f }),
     72         new HintingTestCase("OH", 13f, new float[] { 9f, 8f }, new float[] { 15f, 14f }),
     73     };
     74 
     75     @SmallTest
     76     public void testHintingWidth() {
     77         final Typeface fontTypeface = Typeface.createFromAsset(
     78                 getInstrumentation().getContext().getAssets(), FONT_PATH);
     79         Paint paint = new Paint();
     80         paint.setTypeface(fontTypeface);
     81 
     82         for (int i = 0; i < HINTING_TESTCASES.length; ++i) {
     83             HintingTestCase testCase = HINTING_TESTCASES[i];
     84 
     85             paint.setTextSize(testCase.mTextSize);
     86 
     87             float[] widths = new float[testCase.mText.length()];
     88 
     89             paint.setHinting(Paint.HINTING_OFF);
     90             paint.getTextWidths(String.valueOf(testCase.mText), widths);
     91             assertEquals("Text width of '" + testCase.mText + "' without hinting is not expected.",
     92                     testCase.mWidthWithoutHinting, widths);
     93 
     94             paint.setHinting(Paint.HINTING_ON);
     95             paint.getTextWidths(String.valueOf(testCase.mText), widths);
     96             assertEquals("Text width of '" + testCase.mText + "' with hinting is not expected.",
     97                     testCase.mWidthWithHinting, widths);
     98         }
     99     }
    100 
    101     private static class HasGlyphTestCase {
    102         public final int mBaseCodepoint;
    103         public final HashSet<Integer> mVariationSelectors;
    104 
    105         public HasGlyphTestCase(int baseCodepoint, Integer[] variationSelectors) {
    106             mBaseCodepoint = baseCodepoint;
    107             mVariationSelectors = new HashSet<>(Arrays.asList(variationSelectors));
    108         }
    109     }
    110 
    111     private static String codePointsToString(int[] codepoints) {
    112         StringBuilder sb = new StringBuilder();
    113         for (int codepoint : codepoints) {
    114             sb.append(Character.toChars(codepoint));
    115         }
    116         return sb.toString();
    117     }
    118 
    119     public void testHasGlyph_variationSelectors() {
    120         final Typeface fontTypeface = Typeface.createFromAsset(
    121                 getInstrumentation().getContext().getAssets(), "fonts/hasGlyphTestFont.ttf");
    122         Paint p = new Paint();
    123         p.setTypeface(fontTypeface);
    124 
    125         // Usually latin letters U+0061..U+0064 and Mahjong Tiles U+1F000..U+1F003 don't have
    126         // variation selectors.  This test may fail if system pre-installed fonts have a variation
    127         // selector support for U+0061..U+0064 and U+1F000..U+1F003.
    128         HasGlyphTestCase[] HAS_GLYPH_TEST_CASES = {
    129             new HasGlyphTestCase(0x0061, new Integer[] {0xFE00, 0xE0100, 0xE0101, 0xE0102}),
    130             new HasGlyphTestCase(0x0062, new Integer[] {0xFE01, 0xE0101, 0xE0102, 0xE0103}),
    131             new HasGlyphTestCase(0x0063, new Integer[] {}),
    132             new HasGlyphTestCase(0x0064, new Integer[] {0xFE02, 0xE0102, 0xE0103}),
    133 
    134             new HasGlyphTestCase(0x1F000, new Integer[] {0xFE00, 0xE0100, 0xE0101, 0xE0102}),
    135             new HasGlyphTestCase(0x1F001, new Integer[] {0xFE01, 0xE0101, 0xE0102, 0xE0103}),
    136             new HasGlyphTestCase(0x1F002, new Integer[] {}),
    137             new HasGlyphTestCase(0x1F003, new Integer[] {0xFE02, 0xE0102, 0xE0103}),
    138         };
    139 
    140         for (HasGlyphTestCase testCase : HAS_GLYPH_TEST_CASES) {
    141             for (int vs = 0xFE00; vs <= 0xE01EF; ++vs) {
    142                 // Move to variation selector supplements after variation selectors.
    143                 if (vs == 0xFF00) {
    144                     vs = 0xE0100;
    145                 }
    146                 final String signature =
    147                         "hasGlyph(U+" + Integer.toHexString(testCase.mBaseCodepoint) +
    148                         " U+" + Integer.toHexString(vs) + ")";
    149                 final String testString =
    150                         codePointsToString(new int[] {testCase.mBaseCodepoint, vs});
    151                 if (testCase.mVariationSelectors.contains(vs)) {
    152                     assertTrue(signature + " is expected to be true", p.hasGlyph(testString));
    153                 } else {
    154                     assertFalse(signature + " is expected to be false", p.hasGlyph(testString));
    155                 }
    156             }
    157         }
    158     }
    159 }
    160