1 /* 2 * Copyright 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 androidx.core.text; 18 19 import static android.text.TextDirectionHeuristics.LTR; 20 import static android.text.TextDirectionHeuristics.RTL; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 28 import android.graphics.Color; 29 import android.support.test.filters.SdkSuppress; 30 import android.support.test.filters.SmallTest; 31 import android.support.test.runner.AndroidJUnit4; 32 import android.text.Layout; 33 import android.text.Spannable; 34 import android.text.SpannableStringBuilder; 35 import android.text.Spanned; 36 import android.text.TextDirectionHeuristics; 37 import android.text.TextPaint; 38 import android.text.style.BackgroundColorSpan; 39 import android.text.style.TypefaceSpan; 40 41 import androidx.core.text.PrecomputedTextCompat.Params; 42 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 46 @RunWith(AndroidJUnit4.class) 47 @SmallTest 48 public class PrecomputedTextCompatTest { 49 50 private static final CharSequence NULL_CHAR_SEQUENCE = null; 51 private static final String STRING = "Hello, World!"; 52 private static final String MULTIPARA_STRING = "Hello,\nWorld!"; 53 54 private static final int SPAN_START = 3; 55 private static final int SPAN_END = 7; 56 private static final TypefaceSpan SPAN = new TypefaceSpan("serif"); 57 private static final Spanned SPANNED; 58 static { 59 final SpannableStringBuilder ssb = new SpannableStringBuilder(STRING); 60 ssb.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 61 SPANNED = ssb; 62 } 63 64 private static final TextPaint PAINT = new TextPaint(); 65 66 @Test 67 public void testParams_create() { 68 assertNotNull(new Params.Builder(PAINT).build()); 69 assertNotNull(new Params.Builder(PAINT) 70 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build()); 71 assertNotNull(new Params.Builder(PAINT) 72 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 73 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL).build()); 74 assertNotNull(new Params.Builder(PAINT) 75 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 76 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 77 .setTextDirection(LTR).build()); 78 } 79 80 @Test 81 public void testParams_SetGet() { 82 assertEquals(Layout.BREAK_STRATEGY_SIMPLE, new Params.Builder(PAINT) 83 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build().getBreakStrategy()); 84 assertEquals(Layout.HYPHENATION_FREQUENCY_NONE, new Params.Builder(PAINT) 85 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build() 86 .getHyphenationFrequency()); 87 assertEquals(RTL, new Params.Builder(PAINT).setTextDirection(RTL).build() 88 .getTextDirection()); 89 } 90 91 @Test 92 @SdkSuppress(minSdkVersion = 23) 93 public void testParams_GetDefaultValues() { 94 assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, 95 new Params.Builder(PAINT).build().getBreakStrategy()); 96 assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL, 97 new Params.Builder(PAINT).build().getHyphenationFrequency()); 98 } 99 100 @Test 101 @SdkSuppress(minSdkVersion = 18) 102 public void testParams_GetDefaultValues2() { 103 assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR, 104 new Params.Builder(PAINT).build().getTextDirection()); 105 } 106 107 @Test 108 @SdkSuppress(minSdkVersion = 23) 109 public void testParams_equals() { 110 final Params base = new Params.Builder(PAINT) 111 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) 112 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 113 .setTextDirection(LTR).build(); 114 115 assertFalse(base.equals(null)); 116 assertTrue(base.equals(base)); 117 assertFalse(base.equals(new Object())); 118 119 Params other = new Params.Builder(PAINT) 120 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) 121 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 122 .setTextDirection(LTR).build(); 123 assertTrue(base.equals(other)); 124 assertTrue(other.equals(base)); 125 assertEquals(base.hashCode(), other.hashCode()); 126 127 other = new Params.Builder(PAINT) 128 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE) 129 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 130 .setTextDirection(LTR).build(); 131 assertFalse(base.equals(other)); 132 assertFalse(other.equals(base)); 133 134 other = new Params.Builder(PAINT) 135 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) 136 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE) 137 .setTextDirection(LTR).build(); 138 assertFalse(base.equals(other)); 139 assertFalse(other.equals(base)); 140 141 142 other = new Params.Builder(PAINT) 143 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) 144 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 145 .setTextDirection(RTL).build(); 146 assertFalse(base.equals(other)); 147 assertFalse(other.equals(base)); 148 149 150 TextPaint anotherPaint = new TextPaint(PAINT); 151 anotherPaint.setTextSize(PAINT.getTextSize() * 2.0f); 152 other = new Params.Builder(anotherPaint) 153 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) 154 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL) 155 .setTextDirection(LTR).build(); 156 assertFalse(base.equals(other)); 157 assertFalse(other.equals(base)); 158 } 159 160 @Test 161 public void testParams_equals2() { 162 final Params base = new Params.Builder(PAINT).build(); 163 164 assertFalse(base.equals(null)); 165 assertTrue(base.equals(base)); 166 assertFalse(base.equals(new Object())); 167 168 Params other = new Params.Builder(PAINT).build(); 169 assertTrue(base.equals(other)); 170 assertTrue(other.equals(base)); 171 assertEquals(base.hashCode(), other.hashCode()); 172 173 TextPaint paint = new TextPaint(PAINT); 174 paint.setTextSize(paint.getTextSize() * 2.0f + 1.0f); 175 other = new Params.Builder(paint).build(); 176 assertFalse(base.equals(other)); 177 assertFalse(other.equals(base)); 178 } 179 180 @Test 181 public void testCreate_withNull() { 182 final Params param = new Params.Builder(PAINT).build(); 183 try { 184 PrecomputedTextCompat.create(NULL_CHAR_SEQUENCE, param); 185 fail(); 186 } catch (NullPointerException e) { 187 // pass 188 } 189 try { 190 PrecomputedTextCompat.create(STRING, null); 191 fail(); 192 } catch (NullPointerException e) { 193 // pass 194 } 195 } 196 197 @Test 198 public void testCharSequenceInteface() { 199 final Params param = new Params.Builder(PAINT).build(); 200 final CharSequence s = PrecomputedTextCompat.create(STRING, param); 201 assertEquals(STRING.length(), s.length()); 202 assertEquals('H', s.charAt(0)); 203 assertEquals('e', s.charAt(1)); 204 assertEquals('l', s.charAt(2)); 205 assertEquals('l', s.charAt(3)); 206 assertEquals('o', s.charAt(4)); 207 assertEquals(',', s.charAt(5)); 208 assertEquals("Hello, World!", s.toString()); 209 210 final CharSequence s3 = s.subSequence(0, 3); 211 assertEquals(3, s3.length()); 212 assertEquals('H', s3.charAt(0)); 213 assertEquals('e', s3.charAt(1)); 214 assertEquals('l', s3.charAt(2)); 215 216 } 217 218 @Test 219 public void testSpannedInterface_Spanned() { 220 final Params param = new Params.Builder(PAINT).build(); 221 final Spanned s = PrecomputedTextCompat.create(SPANNED, param); 222 final TypefaceSpan[] spans = s.getSpans(0, s.length(), TypefaceSpan.class); 223 assertNotNull(spans); 224 assertEquals(1, spans.length); 225 assertEquals(SPAN, spans[0]); 226 227 assertEquals(SPAN_START, s.getSpanStart(SPAN)); 228 assertEquals(SPAN_END, s.getSpanEnd(SPAN)); 229 assertTrue((s.getSpanFlags(SPAN) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0); 230 231 assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), TypefaceSpan.class)); 232 assertEquals(SPAN_END, s.nextSpanTransition(SPAN_START, s.length(), TypefaceSpan.class)); 233 } 234 235 @Test 236 public void testSpannedInterface_Spannable() { 237 final BackgroundColorSpan span = new BackgroundColorSpan(Color.RED); 238 final Params param = new Params.Builder(PAINT).build(); 239 final Spannable s = PrecomputedTextCompat.create(STRING, param); 240 assertEquals(0, s.getSpans(0, s.length(), BackgroundColorSpan.class).length); 241 242 s.setSpan(span, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 243 244 final BackgroundColorSpan[] spans = s.getSpans(0, s.length(), BackgroundColorSpan.class); 245 assertEquals(SPAN_START, s.getSpanStart(span)); 246 assertEquals(SPAN_END, s.getSpanEnd(span)); 247 assertTrue((s.getSpanFlags(span) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0); 248 249 assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), BackgroundColorSpan.class)); 250 assertEquals(SPAN_END, 251 s.nextSpanTransition(SPAN_START, s.length(), BackgroundColorSpan.class)); 252 253 s.removeSpan(span); 254 assertEquals(0, s.getSpans(0, s.length(), BackgroundColorSpan.class).length); 255 } 256 257 @Test(expected = IllegalArgumentException.class) 258 public void testSpannedInterface_Spannable_setSpan_MetricsAffectingSpan() { 259 final Params param = new Params.Builder(PAINT).build(); 260 final Spannable s = PrecomputedTextCompat.create(SPANNED, param); 261 s.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 262 } 263 264 @Test(expected = IllegalArgumentException.class) 265 public void testSpannedInterface_Spannable_removeSpan_MetricsAffectingSpan() { 266 final Params param = new Params.Builder(PAINT).build(); 267 final Spannable s = PrecomputedTextCompat.create(SPANNED, param); 268 s.removeSpan(SPAN); 269 } 270 271 @Test 272 public void testSpannedInterface_String() { 273 final Params param = new Params.Builder(PAINT).build(); 274 final Spanned s = PrecomputedTextCompat.create(STRING, param); 275 TypefaceSpan[] spans = s.getSpans(0, s.length(), TypefaceSpan.class); 276 assertNotNull(spans); 277 assertEquals(0, spans.length); 278 279 assertEquals(-1, s.getSpanStart(SPAN)); 280 assertEquals(-1, s.getSpanEnd(SPAN)); 281 assertEquals(0, s.getSpanFlags(SPAN)); 282 283 assertEquals(s.length(), s.nextSpanTransition(0, s.length(), TypefaceSpan.class)); 284 } 285 286 @Test 287 public void testGetParagraphCount() { 288 final Params param = new Params.Builder(PAINT).build(); 289 final PrecomputedTextCompat pm = PrecomputedTextCompat.create(STRING, param); 290 assertEquals(1, pm.getParagraphCount()); 291 assertEquals(0, pm.getParagraphStart(0)); 292 assertEquals(STRING.length(), pm.getParagraphEnd(0)); 293 294 final PrecomputedTextCompat pm1 = PrecomputedTextCompat.create(MULTIPARA_STRING, param); 295 assertEquals(2, pm1.getParagraphCount()); 296 assertEquals(0, pm1.getParagraphStart(0)); 297 assertEquals(7, pm1.getParagraphEnd(0)); 298 assertEquals(7, pm1.getParagraphStart(1)); 299 assertEquals(pm1.length(), pm1.getParagraphEnd(1)); 300 } 301 302 } 303