1 /* 2 * Copyright (C) 2018 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.text.cts; 18 19 import static org.junit.Assert.assertEquals; 20 21 import android.text.Layout; 22 import android.text.Layout.Alignment; 23 import android.text.SpannableString; 24 import android.text.Spanned; 25 import android.text.StaticLayout; 26 import android.text.TextDirectionHeuristic; 27 import android.text.TextDirectionHeuristics; 28 import android.text.TextPaint; 29 import android.text.style.LeadingMarginSpan; 30 31 import androidx.test.filters.SmallTest; 32 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.Parameterized; 36 37 import java.util.ArrayList; 38 import java.util.Collection; 39 40 @SmallTest 41 @RunWith(Parameterized.class) 42 public final class StaticLayoutGetLineLeftRightTest { 43 44 // Here we should have a string without any space in case layout omit the 45 // space, which will cause troubles for us to verify the length of each line. 46 // And in this test, we assume TEST_STR is LTR. It's initialized in setUp() 47 static final String TEST_STR; 48 49 static { 50 String test_str = ""; 51 for (int i = 0; i < 100; ++i) { 52 test_str += "a"; 53 } 54 TEST_STR = test_str; 55 } 56 // Because Alignment.LEFT and Alignment.RIGHT are hidden, 57 // following integers are used to represent alignment. 58 static final int ALIGN_LEFT = 0; 59 static final int ALIGN_RIGHT = 1; 60 static final int ALIGN_CENTER = 2; 61 62 final CharSequence mText; 63 final TextPaint mPaint; 64 final int mWidth; 65 final Layout mLayout; 66 67 final int mLeadingMargin; 68 final Alignment mAlign; 69 final TextDirectionHeuristic mDir; 70 final int mExpectedAlign; 71 72 @Parameterized.Parameters(name = "leadingMargin {0} align {1} dir {2}") cases()73 public static Collection<Object[]> cases() { 74 final Alignment[] aligns = new Alignment[]{Alignment.ALIGN_NORMAL, Alignment.ALIGN_OPPOSITE, 75 Alignment.ALIGN_CENTER, null}; 76 // Use String to generate a meaningful test name, 77 final TextDirectionHeuristic[] dirs = new TextDirectionHeuristic[] 78 {TextDirectionHeuristics.LTR, TextDirectionHeuristics.RTL}; 79 final int[] leadingMargins = new int[] {0, 17, 23, 37}; 80 81 final ArrayList<Object[]> params = new ArrayList<>(); 82 for (int leadingMargin: leadingMargins) { 83 for (Alignment align: aligns) { 84 for (TextDirectionHeuristic dir: dirs) { 85 final String dirName = 86 dir == TextDirectionHeuristics.LTR ? "DIR_LTR" : "DIR_RTL"; 87 params.add(new Object[] {leadingMargin, align, dirName, dir}); 88 } 89 } 90 } 91 return params; 92 } 93 StaticLayoutGetLineLeftRightTest(int leadingMargin, Alignment align, String dirName, TextDirectionHeuristic dir)94 public StaticLayoutGetLineLeftRightTest(int leadingMargin, Alignment align, 95 String dirName, TextDirectionHeuristic dir) { 96 mLeadingMargin = leadingMargin; 97 mAlign = align; 98 mDir = dir; 99 100 if (mLeadingMargin > 0) { 101 final SpannableString ss = new SpannableString(TEST_STR); 102 ss.setSpan(new LeadingMarginSpan.Standard(mLeadingMargin), 103 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 104 mText = ss; 105 } else { 106 mText = TEST_STR; 107 } 108 109 mPaint = new TextPaint(); 110 // Set TextSize to 32 in case the default is too small. 111 mPaint.setTextSize(32); 112 // Try to make 10 lines. 113 mWidth = mLeadingMargin + (int) mPaint.measureText(mText, 0, mText.length()) / 10; 114 mLayout = StaticLayout.Builder.obtain(mText, 0, mText.length(), mPaint, mWidth) 115 .setAlignment(mAlign) 116 .setTextDirection(mDir) 117 .build(); 118 119 if (mAlign == null) { 120 mExpectedAlign = ALIGN_CENTER; 121 return; 122 } 123 switch (mAlign) { 124 case ALIGN_NORMAL: 125 if (dir == TextDirectionHeuristics.RTL) { 126 mExpectedAlign = ALIGN_RIGHT; 127 } else { 128 mExpectedAlign = ALIGN_LEFT; 129 } 130 break; 131 case ALIGN_OPPOSITE: 132 if (dir == TextDirectionHeuristics.RTL) { 133 mExpectedAlign = ALIGN_LEFT; 134 } else { 135 mExpectedAlign = ALIGN_RIGHT; 136 } 137 break; 138 default: /* mAlign == Alignment.ALIGN_CENTER */ 139 mExpectedAlign = ALIGN_CENTER; 140 } 141 } 142 143 @Test testGetLineLeft()144 public void testGetLineLeft() { 145 final int lineCount = mLayout.getLineCount(); 146 for (int line = 0; line < lineCount; ++line) { 147 final int start = mLayout.getLineStart(line); 148 final int end = mLayout.getLineEnd(line); 149 final float textWidth = mPaint.measureText(mText, start, end); 150 final float expectedLeft; 151 if (mExpectedAlign == ALIGN_LEFT) { 152 expectedLeft = 0.0f; 153 } else if (mExpectedAlign == ALIGN_RIGHT) { 154 expectedLeft = mWidth - textWidth - mLeadingMargin; 155 } else { 156 if (mDir == TextDirectionHeuristics.RTL) { 157 expectedLeft = (float) Math.floor((mWidth - mLeadingMargin - textWidth) / 2); 158 } else { 159 expectedLeft = (float) Math.floor(mLeadingMargin 160 + (mWidth - mLeadingMargin - textWidth) / 2); 161 } 162 } 163 assertEquals(expectedLeft, mLayout.getLineLeft(line), 0.0f); 164 } 165 } 166 167 @Test testGetLineRight()168 public void testGetLineRight() { 169 final int lineCount = mLayout.getLineCount(); 170 for (int line = 0; line < lineCount; ++line) { 171 final int start = mLayout.getLineStart(line); 172 final int end = mLayout.getLineEnd(line); 173 final float textWidth = mPaint.measureText(mText, start, end); 174 final float expectedRight; 175 if (mExpectedAlign == ALIGN_LEFT) { 176 expectedRight = mLeadingMargin + textWidth; 177 } else if (mExpectedAlign == ALIGN_RIGHT) { 178 expectedRight = mWidth; 179 } else { 180 if (mDir == TextDirectionHeuristics.RTL) { 181 expectedRight = (float) Math.ceil(mWidth - mLeadingMargin 182 - (mWidth - mLeadingMargin - textWidth) / 2); 183 } else { 184 expectedRight = (float) Math.ceil(mWidth 185 - (mWidth - mLeadingMargin - textWidth) / 2); 186 } 187 } 188 assertEquals(expectedRight, mLayout.getLineRight(line), 0.0f); 189 } 190 } 191 } 192