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