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.graphics.fonts; 18 19 import static com.google.common.truth.Truth.assertWithMessage; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotEquals; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertNull; 26 import static org.junit.Assert.assertTrue; 27 28 import android.content.Context; 29 import android.content.res.AssetManager; 30 import android.content.res.Resources; 31 import android.content.res.Resources.NotFoundException; 32 import android.graphics.Paint; 33 import android.graphics.RectF; 34 import android.graphics.Typeface; 35 import android.graphics.cts.R; 36 import android.graphics.text.PositionedGlyphs; 37 import android.graphics.text.TextRunShaper; 38 import android.os.ParcelFileDescriptor; 39 import android.util.Log; 40 import android.util.Pair; 41 42 import androidx.test.InstrumentationRegistry; 43 import androidx.test.filters.SmallTest; 44 import androidx.test.runner.AndroidJUnit4; 45 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 49 import java.io.File; 50 import java.io.FileInputStream; 51 import java.io.FileOutputStream; 52 import java.io.IOException; 53 import java.io.InputStream; 54 import java.nio.ByteBuffer; 55 import java.nio.channels.FileChannel; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.Comparator; 59 60 @SmallTest 61 @RunWith(AndroidJUnit4.class) 62 public class FontTest { 63 private static final String TAG = "FontFileUtilTest"; 64 private static final String CACHE_FILE_PREFIX = ".font"; 65 66 /** 67 * Create new temporary file. 68 * 69 * Caller must delete the file after used. 70 */ getTempFile()71 private static File getTempFile() { 72 Context ctx = InstrumentationRegistry.getTargetContext(); 73 final String prefix = CACHE_FILE_PREFIX; 74 for (int i = 0; i < 100; ++i) { 75 final File file = new File(ctx.getCacheDir(), prefix + i); 76 try { 77 if (file.createNewFile()) { 78 return file; 79 } 80 } catch (IOException e) { 81 // ignore. Try next file. 82 } 83 } 84 return null; 85 } 86 mmap(AssetManager am, String path)87 private static ByteBuffer mmap(AssetManager am, String path) { 88 File file = getTempFile(); 89 try (InputStream is = am.open(path)) { 90 if (!copyToFile(file, is)) { 91 return null; 92 } 93 return mmap(file); 94 } catch (IOException e) { 95 Log.e(TAG, "Failed to open assets"); 96 return null; 97 } finally { 98 file.delete(); 99 } 100 } 101 mmap(File file)102 private static ByteBuffer mmap(File file) { 103 try (FileInputStream fis = new FileInputStream(file)) { 104 FileChannel channel = fis.getChannel(); 105 return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 106 } catch (IOException e) { 107 return null; 108 } 109 } 110 copyToFile(File file, InputStream is)111 private static boolean copyToFile(File file, InputStream is) { 112 return copyToFile(file, is, null, null); 113 } 114 copyToFile(File file, InputStream is, byte[] prepend, byte[] append)115 private static boolean copyToFile(File file, InputStream is, byte[] prepend, byte[] append) { 116 try (FileOutputStream os = new FileOutputStream(file, false)) { 117 byte[] buffer = new byte[1024]; 118 int readLen; 119 if (prepend != null) { 120 os.write(prepend, 0, prepend.length); 121 } 122 while ((readLen = is.read(buffer)) != -1) { 123 os.write(buffer, 0, readLen); 124 } 125 if (append != null) { 126 os.write(append, 0, append.length); 127 } 128 return true; 129 } catch (IOException e) { 130 Log.e(TAG, "Error copying resource contents to temp file: " + e.getMessage()); 131 return false; 132 } 133 } 134 openTypeValueFromTag(String tag)135 private int openTypeValueFromTag(String tag) { 136 assertEquals(4, tag.length()); 137 return ((int) tag.charAt(0)) << 24 | ((int) tag.charAt(1)) << 16 138 | ((int) tag.charAt(2)) << 8 | ((int) tag.charAt(3)); 139 } 140 assertAxesEquals(String msg, FontVariationAxis[] left, FontVariationAxis[] right)141 private void assertAxesEquals(String msg, FontVariationAxis[] left, FontVariationAxis[] right) { 142 if (left == right) { 143 return; 144 } 145 146 if (left == null) { 147 assertWithMessage(msg).that(right).isEmpty(); 148 } else if (right == null) { 149 assertWithMessage(msg).that(left).isEmpty(); 150 } else { 151 // Sort both font variation settings because the font variation axes are unordered. 152 Comparator<FontVariationAxis> axisComparator = 153 (l, r) -> openTypeValueFromTag(l.getTag()) - openTypeValueFromTag(r.getTag()); 154 Arrays.sort(left, axisComparator); 155 Arrays.sort(right, axisComparator); 156 157 assertWithMessage(msg).that(left).isEqualTo(right); 158 } 159 } 160 assertNullOrEmpty(String msg, FontVariationAxis[] actual)161 private void assertNullOrEmpty(String msg, FontVariationAxis[] actual) { 162 assertWithMessage(msg).that(actual == null || actual.length == 0).isTrue(); 163 } 164 165 @Test testBuilder_buffer()166 public void testBuilder_buffer() throws IOException { 167 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 168 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 169 int weight = style.first.intValue(); 170 boolean italic = style.second.booleanValue(); 171 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 172 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 173 174 ByteBuffer buffer = mmap(am, path); 175 176 Font font = new Font.Builder(buffer).build(); 177 assertEquals(path, weight, font.getStyle().getWeight()); 178 assertEquals(path, slant, font.getStyle().getSlant()); 179 assertEquals(path, 0, font.getTtcIndex()); 180 assertNullOrEmpty(path, font.getAxes()); 181 assertNotNull(font.getBuffer()); 182 assertNull(font.getFile()); 183 } 184 } 185 186 @Test testBuilder_buffer_ttc()187 public void testBuilder_buffer_ttc() throws IOException { 188 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 189 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 190 int weight = style.first.intValue(); 191 boolean italic = style.second.booleanValue(); 192 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 193 String path = FontTestUtil.getTtcFontFileInAsset(); 194 195 ByteBuffer buffer = mmap(am, path); 196 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 197 198 Font font = new Font.Builder(buffer).setTtcIndex(ttcIndex).build(); 199 assertEquals(path, weight, font.getStyle().getWeight()); 200 assertEquals(path, slant, font.getStyle().getSlant()); 201 assertEquals(path, ttcIndex, font.getTtcIndex()); 202 assertNullOrEmpty(path, font.getAxes()); 203 assertNotNull(font.getBuffer()); 204 assertNull(font.getFile()); 205 } 206 } 207 208 @Test testBuilder_buffer_vf()209 public void testBuilder_buffer_vf() throws IOException { 210 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 211 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 212 int weight = style.first.intValue(); 213 boolean italic = style.second.booleanValue(); 214 String path = FontTestUtil.getVFFontInAsset(); 215 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 216 217 ByteBuffer buffer = mmap(am, path); 218 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 219 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 220 221 Font font = new Font.Builder(buffer).setFontVariationSettings(axes).build(); 222 assertEquals(path, weight, font.getStyle().getWeight()); 223 assertEquals(path, slant, font.getStyle().getSlant()); 224 assertEquals(path, 0, font.getTtcIndex()); 225 assertAxesEquals(path, axes, font.getAxes()); 226 assertNotNull(font.getBuffer()); 227 assertNull(font.getFile()); 228 } 229 } 230 231 @Test testBuilder_buffer_override()232 public void testBuilder_buffer_override() throws IOException { 233 int customWeight = 350; 234 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 235 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 236 int weight = style.first.intValue(); 237 boolean italic = style.second.booleanValue(); 238 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 239 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 240 241 ByteBuffer buffer = mmap(am, path); 242 243 Font font = new Font.Builder(buffer).setWeight(customWeight).build(); 244 assertEquals(path, customWeight, font.getStyle().getWeight()); 245 assertEquals(path, slant, font.getStyle().getSlant()); 246 assertEquals(path, 0, font.getTtcIndex()); 247 assertNullOrEmpty(path, font.getAxes()); 248 assertNotNull(font.getBuffer()); 249 assertNull(font.getFile()); 250 } 251 252 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 253 int weight = style.first.intValue(); 254 boolean italic = style.second.booleanValue(); 255 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 256 257 ByteBuffer buffer = mmap(am, path); 258 259 Font font = new Font.Builder(buffer).setSlant(FontStyle.FONT_SLANT_ITALIC).build(); 260 assertEquals(path, weight, font.getStyle().getWeight()); 261 assertEquals(path, FontStyle.FONT_SLANT_ITALIC, font.getStyle().getSlant()); 262 assertEquals(path, 0, font.getTtcIndex()); 263 assertNullOrEmpty(path, font.getAxes()); 264 assertNotNull(font.getBuffer()); 265 assertNull(font.getFile()); 266 } 267 } 268 269 @Test(expected = NullPointerException.class) testBuilder_buffer_invalid_null()270 public void testBuilder_buffer_invalid_null() throws IOException { 271 ByteBuffer buf = null; 272 new Font.Builder(buf); 273 } 274 275 @Test(expected = IllegalArgumentException.class) testBuilder_buffer_invalid_not_direct()276 public void testBuilder_buffer_invalid_not_direct() throws IOException { 277 ByteBuffer buf = ByteBuffer.allocate(1024); 278 new Font.Builder(buf); 279 } 280 281 @Test testBuilder_file()282 public void testBuilder_file() throws IOException { 283 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 284 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 285 int weight = style.first.intValue(); 286 boolean italic = style.second.booleanValue(); 287 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 288 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 289 290 File file = getTempFile(); 291 try (InputStream is = am.open(path)) { 292 assertTrue(copyToFile(file, is)); 293 294 Font font = new Font.Builder(file).build(); 295 assertEquals(path, weight, font.getStyle().getWeight()); 296 assertEquals(path, slant, font.getStyle().getSlant()); 297 assertEquals(path, 0, font.getTtcIndex()); 298 assertNullOrEmpty(path, font.getAxes()); 299 assertNotNull(font.getBuffer()); 300 assertNotNull(font.getFile()); 301 } finally { 302 file.delete(); 303 } 304 } 305 } 306 307 @Test testBuilder_file_ttc()308 public void testBuilder_file_ttc() throws IOException { 309 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 310 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 311 int weight = style.first.intValue(); 312 boolean italic = style.second.booleanValue(); 313 String path = FontTestUtil.getTtcFontFileInAsset(); 314 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 315 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 316 317 File file = getTempFile(); 318 try (InputStream is = am.open(path)) { 319 assertTrue(copyToFile(file, is)); 320 321 Font font = new Font.Builder(file).setTtcIndex(ttcIndex).build(); 322 assertEquals(path, weight, font.getStyle().getWeight()); 323 assertEquals(path, slant, font.getStyle().getSlant()); 324 assertEquals(path, ttcIndex, font.getTtcIndex()); 325 assertNullOrEmpty(path, font.getAxes()); 326 assertNotNull(font.getBuffer()); 327 assertNotNull(font.getFile()); 328 } finally { 329 file.delete(); 330 } 331 } 332 } 333 334 @Test testBuilder_file_vf()335 public void testBuilder_file_vf() throws IOException { 336 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 337 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 338 int weight = style.first.intValue(); 339 boolean italic = style.second.booleanValue(); 340 String path = FontTestUtil.getVFFontInAsset(); 341 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 342 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 343 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 344 345 File file = getTempFile(); 346 try (InputStream is = am.open(path)) { 347 assertTrue(copyToFile(file, is)); 348 349 Font font = new Font.Builder(file).setFontVariationSettings(axes).build(); 350 assertEquals(path, weight, font.getStyle().getWeight()); 351 assertEquals(path, slant, font.getStyle().getSlant()); 352 assertEquals(path, 0, font.getTtcIndex()); 353 assertAxesEquals(path, axes, font.getAxes()); 354 assertNotNull(font.getBuffer()); 355 assertNotNull(font.getFile()); 356 } finally { 357 file.delete(); 358 } 359 } 360 } 361 362 @Test testBuilder_file_override()363 public void testBuilder_file_override() throws IOException { 364 int customWeight = 350; 365 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 366 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 367 int weight = style.first.intValue(); 368 boolean italic = style.second.booleanValue(); 369 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 370 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 371 372 File file = getTempFile(); 373 try (InputStream is = am.open(path)) { 374 assertTrue(copyToFile(file, is)); 375 376 Font font = new Font.Builder(file).setWeight(customWeight).build(); 377 assertEquals(path, customWeight, font.getStyle().getWeight()); 378 assertEquals(path, slant, font.getStyle().getSlant()); 379 assertEquals(path, 0, font.getTtcIndex()); 380 assertNullOrEmpty(path, font.getAxes()); 381 assertNotNull(font.getBuffer()); 382 assertNotNull(font.getFile()); 383 } finally { 384 file.delete(); 385 } 386 } 387 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 388 int weight = style.first.intValue(); 389 boolean italic = style.second.booleanValue(); 390 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 391 392 File file = getTempFile(); 393 try (InputStream is = am.open(path)) { 394 assertTrue(copyToFile(file, is)); 395 396 Font font = new Font.Builder(file).setSlant(FontStyle.FONT_SLANT_ITALIC).build(); 397 assertEquals(path, weight, font.getStyle().getWeight()); 398 assertEquals(path, FontStyle.FONT_SLANT_ITALIC, font.getStyle().getSlant()); 399 assertEquals(path, 0, font.getTtcIndex()); 400 assertNullOrEmpty(path, font.getAxes()); 401 assertNotNull(font.getBuffer()); 402 assertNotNull(font.getFile()); 403 } finally { 404 file.delete(); 405 } 406 } 407 } 408 409 @Test(expected = NullPointerException.class) testBuilder_file_invalid_null_file()410 public void testBuilder_file_invalid_null_file() throws IOException { 411 File file = null; 412 new Font.Builder(file); 413 } 414 415 @Test(expected = IOException.class) testBuilder_file_invalid_not_found_file()416 public void testBuilder_file_invalid_not_found_file() throws IOException { 417 File file = new File("/no/such/file"); 418 new Font.Builder(file).build(); 419 } 420 421 @Test testBuilder_fd()422 public void testBuilder_fd() throws IOException { 423 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 424 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 425 int weight = style.first.intValue(); 426 boolean italic = style.second.booleanValue(); 427 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 428 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 429 430 File file = getTempFile(); 431 try (InputStream is = am.open(path)) { 432 assertTrue(copyToFile(file, is)); 433 434 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 435 ParcelFileDescriptor.MODE_READ_ONLY)) { 436 Font font = new Font.Builder(fd).build(); 437 assertEquals(path, weight, font.getStyle().getWeight()); 438 assertEquals(path, slant, font.getStyle().getSlant()); 439 assertEquals(path, 0, font.getTtcIndex()); 440 assertNullOrEmpty(path, font.getAxes()); 441 assertNotNull(font.getBuffer()); 442 assertNull(font.getFile()); 443 } 444 } finally { 445 file.delete(); 446 } 447 } 448 } 449 450 @Test testBuilder_fd_ttc()451 public void testBuilder_fd_ttc() throws IOException { 452 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 453 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 454 int weight = style.first.intValue(); 455 boolean italic = style.second.booleanValue(); 456 String path = FontTestUtil.getTtcFontFileInAsset(); 457 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 458 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 459 460 File file = getTempFile(); 461 try (InputStream is = am.open(path)) { 462 assertTrue(copyToFile(file, is)); 463 464 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 465 ParcelFileDescriptor.MODE_READ_ONLY)) { 466 Font font = new Font.Builder(fd).setTtcIndex(ttcIndex).build(); 467 assertEquals(path, weight, font.getStyle().getWeight()); 468 assertEquals(path, slant, font.getStyle().getSlant()); 469 assertEquals(path, ttcIndex, font.getTtcIndex()); 470 assertNullOrEmpty(path, font.getAxes()); 471 assertNotNull(font.getBuffer()); 472 assertNull(font.getFile()); 473 } 474 } finally { 475 file.delete(); 476 } 477 } 478 } 479 480 @Test testBuilder_fd_vf()481 public void testBuilder_fd_vf() throws IOException { 482 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 483 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 484 int weight = style.first.intValue(); 485 boolean italic = style.second.booleanValue(); 486 String path = FontTestUtil.getVFFontInAsset(); 487 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 488 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 489 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 490 491 File file = getTempFile(); 492 try (InputStream is = am.open(path)) { 493 assertTrue(copyToFile(file, is)); 494 495 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 496 ParcelFileDescriptor.MODE_READ_ONLY)) { 497 Font font = new Font.Builder(fd).setFontVariationSettings(axes) 498 .build(); 499 assertEquals(path, weight, font.getStyle().getWeight()); 500 assertEquals(path, slant, font.getStyle().getSlant()); 501 assertEquals(path, 0, font.getTtcIndex()); 502 assertAxesEquals(path, axes, font.getAxes()); 503 assertNotNull(font.getBuffer()); 504 assertNull(font.getFile()); 505 } 506 } finally { 507 file.delete(); 508 } 509 } 510 } 511 512 @Test testBuilder_fd_override()513 public void testBuilder_fd_override() throws IOException { 514 int customWeight = 350; 515 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 516 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 517 int weight = style.first.intValue(); 518 boolean italic = style.second.booleanValue(); 519 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 520 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 521 522 File file = getTempFile(); 523 try (InputStream is = am.open(path)) { 524 assertTrue(copyToFile(file, is)); 525 526 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 527 ParcelFileDescriptor.MODE_READ_ONLY)) { 528 Font font = new Font.Builder(fd).setWeight(customWeight).build(); 529 assertEquals(path, customWeight, font.getStyle().getWeight()); 530 assertEquals(path, slant, font.getStyle().getSlant()); 531 assertEquals(path, 0, font.getTtcIndex()); 532 assertNullOrEmpty(path, font.getAxes()); 533 assertNotNull(font.getBuffer()); 534 assertNull(font.getFile()); 535 } 536 } finally { 537 file.delete(); 538 } 539 } 540 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 541 int weight = style.first.intValue(); 542 boolean italic = style.second.booleanValue(); 543 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 544 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 545 546 File file = getTempFile(); 547 try (InputStream is = am.open(path)) { 548 assertTrue(copyToFile(file, is)); 549 550 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 551 ParcelFileDescriptor.MODE_READ_ONLY)) { 552 Font font = new Font.Builder(fd).setSlant( 553 FontStyle.FONT_SLANT_ITALIC).build(); 554 assertEquals(path, weight, font.getStyle().getWeight()); 555 assertEquals(path, FontStyle.FONT_SLANT_ITALIC, font.getStyle().getSlant()); 556 assertEquals(path, 0, font.getTtcIndex()); 557 assertNullOrEmpty(path, font.getAxes()); 558 assertNotNull(font.getBuffer()); 559 assertNull(font.getFile()); 560 } 561 } finally { 562 file.delete(); 563 } 564 } 565 } 566 567 @Test testBuilder_fd_subdata()568 public void testBuilder_fd_subdata() throws IOException { 569 byte[] placeHolderData = { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef }; 570 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 571 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 572 int weight = style.first.intValue(); 573 boolean italic = style.second.booleanValue(); 574 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 575 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 576 577 File file = getTempFile(); 578 try (InputStream is = am.open(path)) { 579 assertTrue(copyToFile(file, is, placeHolderData, placeHolderData)); 580 581 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 582 ParcelFileDescriptor.MODE_READ_ONLY)) { 583 Font font = new Font.Builder(fd, placeHolderData.length, 584 file.length() - placeHolderData.length * 2).build(); 585 assertEquals(path, weight, font.getStyle().getWeight()); 586 assertEquals(path, slant, font.getStyle().getSlant()); 587 assertEquals(path, 0, font.getTtcIndex()); 588 assertNullOrEmpty(path, font.getAxes()); 589 assertNotNull(font.getBuffer()); 590 assertNull(font.getFile()); 591 } 592 } finally { 593 file.delete(); 594 } 595 } 596 } 597 598 @Test testBuilder_fd_subdata_ttc()599 public void testBuilder_fd_subdata_ttc() throws IOException { 600 byte[] placeHolderData = { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef }; 601 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 602 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 603 int weight = style.first.intValue(); 604 boolean italic = style.second.booleanValue(); 605 String path = FontTestUtil.getTtcFontFileInAsset(); 606 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 607 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 608 609 File file = getTempFile(); 610 try (InputStream is = am.open(path)) { 611 assertTrue(copyToFile(file, is, placeHolderData, placeHolderData)); 612 613 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 614 ParcelFileDescriptor.MODE_READ_ONLY)) { 615 Font font = new Font.Builder( 616 fd, placeHolderData.length, file.length() - placeHolderData.length * 2) 617 .setTtcIndex(ttcIndex).build(); 618 assertEquals(path, weight, font.getStyle().getWeight()); 619 assertEquals(path, slant, font.getStyle().getSlant()); 620 assertEquals(path, ttcIndex, font.getTtcIndex()); 621 assertNullOrEmpty(path, font.getAxes()); 622 assertNotNull(font.getBuffer()); 623 assertNull(font.getFile()); 624 } 625 } finally { 626 file.delete(); 627 } 628 } 629 } 630 631 @Test testBuilder_fd_subdata_vf()632 public void testBuilder_fd_subdata_vf() throws IOException { 633 byte[] placeHolderData = { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef }; 634 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 635 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 636 int weight = style.first.intValue(); 637 boolean italic = style.second.booleanValue(); 638 String path = FontTestUtil.getVFFontInAsset(); 639 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 640 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 641 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 642 643 File file = getTempFile(); 644 try (InputStream is = am.open(path)) { 645 assertTrue(copyToFile(file, is, placeHolderData, placeHolderData)); 646 647 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 648 ParcelFileDescriptor.MODE_READ_ONLY)) { 649 Font font = new Font.Builder( 650 fd, placeHolderData.length, file.length() - placeHolderData.length * 2) 651 .setFontVariationSettings(axes).build(); 652 assertEquals(path, weight, font.getStyle().getWeight()); 653 assertEquals(path, slant, font.getStyle().getSlant()); 654 assertEquals(path, 0, font.getTtcIndex()); 655 assertAxesEquals(path, axes, font.getAxes()); 656 assertNotNull(font.getBuffer()); 657 assertNull(font.getFile()); 658 } 659 } finally { 660 file.delete(); 661 } 662 } 663 } 664 665 @Test testBuilder_fd_subdata_override()666 public void testBuilder_fd_subdata_override() throws IOException { 667 int customWeight = 350; 668 byte[] placeHolderData = { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef }; 669 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 670 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 671 int weight = style.first.intValue(); 672 boolean italic = style.second.booleanValue(); 673 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 674 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 675 676 File file = getTempFile(); 677 try (InputStream is = am.open(path)) { 678 assertTrue(copyToFile(file, is, placeHolderData, placeHolderData)); 679 680 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 681 ParcelFileDescriptor.MODE_READ_ONLY)) { 682 Font font = new Font.Builder( 683 fd, placeHolderData.length, file.length() - placeHolderData.length * 2) 684 .setWeight(customWeight).build(); 685 assertEquals(path, customWeight, font.getStyle().getWeight()); 686 assertEquals(path, slant, font.getStyle().getSlant()); 687 assertEquals(path, 0, font.getTtcIndex()); 688 assertNullOrEmpty(path, font.getAxes()); 689 assertNotNull(font.getBuffer()); 690 assertNull(font.getFile()); 691 } 692 } finally { 693 file.delete(); 694 } 695 } 696 697 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 698 int weight = style.first.intValue(); 699 boolean italic = style.second.booleanValue(); 700 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 701 702 File file = getTempFile(); 703 try (InputStream is = am.open(path)) { 704 assertTrue(copyToFile(file, is, placeHolderData, placeHolderData)); 705 706 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 707 ParcelFileDescriptor.MODE_READ_ONLY)) { 708 Font font = new Font.Builder( 709 fd, placeHolderData.length, file.length() - placeHolderData.length * 2) 710 .setSlant(FontStyle.FONT_SLANT_ITALIC).build(); 711 assertEquals(path, weight, font.getStyle().getWeight()); 712 assertEquals(path, FontStyle.FONT_SLANT_ITALIC, font.getStyle().getSlant()); 713 assertEquals(path, 0, font.getTtcIndex()); 714 assertNullOrEmpty(path, font.getAxes()); 715 assertNotNull(font.getBuffer()); 716 assertNull(font.getFile()); 717 } 718 } finally { 719 file.delete(); 720 } 721 } 722 } 723 724 @Test(expected = NullPointerException.class) testBuilder_fd_invalid_null()725 public void testBuilder_fd_invalid_null() throws IOException { 726 ParcelFileDescriptor fd = null; 727 new Font.Builder(fd); 728 } 729 730 @Test(expected = NullPointerException.class) testBuilder_fd_subadata_invalid_null()731 public void testBuilder_fd_subadata_invalid_null() throws IOException { 732 ParcelFileDescriptor fd = null; 733 new Font.Builder(fd, 0, -1); 734 } 735 736 @Test(expected = IOException.class) testBuilder_fd_subadata_invalid_invalid_size()737 public void testBuilder_fd_subadata_invalid_invalid_size() throws IOException { 738 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 739 String path = FontTestUtil.getFontPathFromStyle(400, false); 740 741 File file = getTempFile(); 742 try (InputStream is = am.open(path)) { 743 assertTrue(copyToFile(file, is)); 744 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 745 ParcelFileDescriptor.MODE_READ_ONLY)) { 746 new Font.Builder(fd, 0, Integer.MAX_VALUE).build(); 747 } 748 } 749 } 750 751 @Test(expected = IOException.class) testBuilder_fd_subadata_invalid_invalid_offset()752 public void testBuilder_fd_subadata_invalid_invalid_offset() throws IOException { 753 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 754 String path = FontTestUtil.getFontPathFromStyle(400, false); 755 756 File file = getTempFile(); 757 try (InputStream is = am.open(path)) { 758 assertTrue(copyToFile(file, is)); 759 try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 760 ParcelFileDescriptor.MODE_READ_ONLY)) { 761 new Font.Builder(fd, Integer.MAX_VALUE, file.length()).build(); 762 } 763 } 764 } 765 766 @Test testBuilder_asset()767 public void testBuilder_asset() throws IOException { 768 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 769 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 770 int weight = style.first.intValue(); 771 boolean italic = style.second.booleanValue(); 772 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 773 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 774 775 Font font = new Font.Builder(am, path).build(); 776 assertEquals(path, weight, font.getStyle().getWeight()); 777 assertEquals(path, slant, font.getStyle().getSlant()); 778 assertEquals(path, 0, font.getTtcIndex()); 779 assertNullOrEmpty(path, font.getAxes()); 780 assertNotNull(font.getBuffer()); 781 assertNull(font.getFile()); 782 } 783 } 784 785 @Test testBuilder_asset_ttc()786 public void testBuilder_asset_ttc() throws IOException { 787 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 788 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 789 int weight = style.first.intValue(); 790 boolean italic = style.second.booleanValue(); 791 String path = FontTestUtil.getTtcFontFileInAsset(); 792 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 793 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 794 795 Font font = new Font.Builder(am, path).setTtcIndex(ttcIndex).build(); 796 assertEquals(path, weight, font.getStyle().getWeight()); 797 assertEquals(path, slant, font.getStyle().getSlant()); 798 assertEquals(path, ttcIndex, font.getTtcIndex()); 799 assertNullOrEmpty(path, font.getAxes()); 800 assertNotNull(font.getBuffer()); 801 assertNull(font.getFile()); 802 } 803 } 804 805 @Test testBuilder_asset_vf()806 public void testBuilder_asset_vf() throws IOException { 807 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 808 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 809 int weight = style.first.intValue(); 810 boolean italic = style.second.booleanValue(); 811 String path = FontTestUtil.getVFFontInAsset(); 812 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 813 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 814 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 815 816 Font font = new Font.Builder(am, path).setFontVariationSettings(axes).build(); 817 assertEquals(path, weight, font.getStyle().getWeight()); 818 assertEquals(path, slant, font.getStyle().getSlant()); 819 assertEquals(path, 0, font.getTtcIndex()); 820 assertAxesEquals(path, axes, font.getAxes()); 821 assertNotNull(font.getBuffer()); 822 assertNull(font.getFile()); 823 } 824 } 825 826 @Test testBuilder_asset_override()827 public void testBuilder_asset_override() throws IOException { 828 int customWeight = 350; 829 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 830 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 831 int weight = style.first.intValue(); 832 boolean italic = style.second.booleanValue(); 833 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 834 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 835 836 Font font = new Font.Builder(am, path).setWeight(customWeight).build(); 837 assertEquals(path, customWeight, font.getStyle().getWeight()); 838 assertEquals(path, slant, font.getStyle().getSlant()); 839 assertEquals(path, 0, font.getTtcIndex()); 840 assertNullOrEmpty(path, font.getAxes()); 841 assertNotNull(font.getBuffer()); 842 assertNull(font.getFile()); 843 } 844 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 845 int weight = style.first.intValue(); 846 boolean italic = style.second.booleanValue(); 847 String path = FontTestUtil.getFontPathFromStyle(weight, italic); 848 849 Font font = new Font.Builder(am, path).setSlant(FontStyle.FONT_SLANT_ITALIC).build(); 850 assertEquals(path, weight, font.getStyle().getWeight()); 851 assertEquals(path, FontStyle.FONT_SLANT_ITALIC, font.getStyle().getSlant()); 852 assertEquals(path, 0, font.getTtcIndex()); 853 assertNullOrEmpty(path, font.getAxes()); 854 assertNotNull(font.getBuffer()); 855 assertNull(font.getFile()); 856 } 857 } 858 859 @Test(expected = NullPointerException.class) testBuilder_asset_invalid_null_asset()860 public void testBuilder_asset_invalid_null_asset() throws IOException { 861 AssetManager am = null; 862 new Font.Builder(am, "/some/path"); 863 } 864 865 @Test(expected = IOException.class) testBuilder_asset_invalid_not_found()866 public void testBuilder_asset_invalid_not_found() throws IOException { 867 AssetManager am = InstrumentationRegistry.getTargetContext().getAssets(); 868 new Font.Builder(am, "/no/such/file").build(); 869 } 870 871 @Test testBuilder_resource()872 public void testBuilder_resource() throws IOException { 873 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 874 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 875 int weight = style.first.intValue(); 876 boolean italic = style.second.booleanValue(); 877 int resId = FontTestUtil.getFontResourceIdFromStyle(weight, italic); 878 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 879 880 Font font = new Font.Builder(res, resId).build(); 881 assertEquals("ResId=#" + resId, weight, font.getStyle().getWeight()); 882 assertEquals("ResId=#" + resId, slant, font.getStyle().getSlant()); 883 assertEquals("ResId=#" + resId, 0, font.getTtcIndex()); 884 assertNullOrEmpty("ResId=#" + resId, font.getAxes()); 885 assertNotNull("ResId=#" + resId, font.getBuffer()); 886 assertNull("ResId=#" + resId, font.getFile()); 887 } 888 } 889 890 @Test testBuilder_resource_ttc()891 public void testBuilder_resource_ttc() throws IOException { 892 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 893 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 894 int weight = style.first.intValue(); 895 boolean italic = style.second.booleanValue(); 896 int resId = FontTestUtil.getTtcFontFileResourceId(); 897 int ttcIndex = FontTestUtil.getTtcIndexFromStyle(weight, italic); 898 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 899 900 Font font = new Font.Builder(res, resId).setTtcIndex(ttcIndex).build(); 901 assertEquals("ResId=#" + resId, weight, font.getStyle().getWeight()); 902 assertEquals("ResId=#" + resId, slant, font.getStyle().getSlant()); 903 assertEquals("ResId=#" + resId, ttcIndex, font.getTtcIndex()); 904 assertNullOrEmpty("ResId=#" + resId, font.getAxes()); 905 assertNotNull("ResId=#" + resId, font.getBuffer()); 906 assertNull("ResId=#" + resId, font.getFile()); 907 } 908 } 909 910 @Test testBuilder_resource_vf()911 public void testBuilder_resource_vf() throws IOException { 912 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 913 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 914 int weight = style.first.intValue(); 915 boolean italic = style.second.booleanValue(); 916 int resId = FontTestUtil.getVFFontResourceId(); 917 FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings( 918 FontTestUtil.getVarSettingsFromStyle(weight, italic)); 919 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 920 921 Font font = new Font.Builder(res, resId).setFontVariationSettings(axes).build(); 922 assertEquals("ResId=#" + resId, weight, font.getStyle().getWeight()); 923 assertEquals("ResId=#" + resId, slant, font.getStyle().getSlant()); 924 assertEquals("ResId=#" + resId, 0, font.getTtcIndex()); 925 assertAxesEquals("ResId=#" + resId, axes, font.getAxes()); 926 assertNotNull("ResId=#" + font.getBuffer()); 927 assertNull("ResId=#" + resId, font.getFile()); 928 } 929 } 930 931 @Test testBuilder_resource_override()932 public void testBuilder_resource_override() throws IOException { 933 int customWeight = 350; 934 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 935 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 936 int weight = style.first.intValue(); 937 boolean italic = style.second.booleanValue(); 938 int resId = FontTestUtil.getFontResourceIdFromStyle(weight, italic); 939 final int slant = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT; 940 941 Font font = new Font.Builder(res, resId).setWeight(customWeight).build(); 942 assertEquals("ResId=#" + resId, customWeight, font.getStyle().getWeight()); 943 assertEquals("ResId=#" + resId, slant, font.getStyle().getSlant()); 944 assertEquals("ResId=#" + resId, 0, font.getTtcIndex()); 945 assertNullOrEmpty("ResId=#" + resId, font.getAxes()); 946 assertNotNull("ResId=#" + resId, font.getBuffer()); 947 assertNull("ResId=#" + resId, font.getFile()); 948 } 949 950 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 951 int weight = style.first.intValue(); 952 boolean italic = style.second.booleanValue(); 953 int resId = FontTestUtil.getFontResourceIdFromStyle(weight, italic); 954 955 Font font = new Font.Builder(res, resId).setSlant(FontStyle.FONT_SLANT_ITALIC).build(); 956 assertEquals("ResId=#" + resId, weight, font.getStyle().getWeight()); 957 assertEquals("ResId=#" + resId, FontStyle.FONT_SLANT_ITALIC, 958 font.getStyle().getSlant()); 959 assertEquals("ResId=#" + resId, 0, font.getTtcIndex()); 960 assertNullOrEmpty("ResId=#" + resId, font.getAxes()); 961 assertNotNull("ResId=#" + resId, font.getBuffer()); 962 assertNull("ResId=#" + resId, font.getFile()); 963 } 964 } 965 966 @Test(expected = NullPointerException.class) testBuilder_resource_invalid_null_resource()967 public void testBuilder_resource_invalid_null_resource() throws IOException { 968 Resources res = null; 969 new Font.Builder(res, R.font.ascii); 970 } 971 972 @Test(expected = NotFoundException.class) testBuilder_resource_invalid_res_id()973 public void testBuilder_resource_invalid_res_id() throws IOException { 974 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 975 new Font.Builder(res, -1).build(); 976 } 977 978 @Test(expected = IOException.class) testBuilder_asset_invalid_xml_font()979 public void testBuilder_asset_invalid_xml_font() throws IOException { 980 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 981 new Font.Builder(res, R.font.multiweight_family /* XML font */).build(); 982 } 983 984 @Test testEquals()985 public void testEquals() throws IOException { 986 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 987 ArrayList<Font> fonts1 = new ArrayList<>(); 988 ArrayList<Font> fonts2 = new ArrayList<>(); 989 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 990 int weight = style.first.intValue(); 991 boolean italic = style.second.booleanValue(); 992 int resId = FontTestUtil.getFontResourceIdFromStyle(weight, italic); 993 994 fonts1.add(new Font.Builder(res, resId).build()); 995 fonts2.add(new Font.Builder(res, resId).build()); 996 } 997 998 for (int i = 0; i < fonts1.size(); ++i) { 999 assertTrue(fonts1.get(i).equals(fonts1.get(i))); 1000 assertTrue(fonts1.get(i).equals(fonts2.get(i))); 1001 assertTrue(fonts2.get(i).equals(fonts1.get(i))); 1002 } 1003 1004 for (int i = 0; i < fonts1.size(); ++i) { 1005 for (int j = i + 1; j < fonts1.size(); ++j) { 1006 assertFalse(fonts1.get(i).equals(fonts1.get(j))); 1007 assertFalse(fonts1.get(j).equals(fonts1.get(i))); 1008 } 1009 } 1010 } 1011 1012 @Test testHashCode()1013 public void testHashCode() throws IOException { 1014 Resources res = InstrumentationRegistry.getTargetContext().getResources(); 1015 ArrayList<Font> fonts1 = new ArrayList<>(); 1016 ArrayList<Font> fonts2 = new ArrayList<>(); 1017 for (Pair<Integer, Boolean> style : FontTestUtil.getAllStyles()) { 1018 int weight = style.first.intValue(); 1019 boolean italic = style.second.booleanValue(); 1020 int resId = FontTestUtil.getFontResourceIdFromStyle(weight, italic); 1021 1022 fonts1.add(new Font.Builder(res, resId).build()); 1023 fonts2.add(new Font.Builder(res, resId).build()); 1024 } 1025 1026 for (int i = 0; i < fonts1.size(); ++i) { 1027 assertEquals(fonts1.get(i).hashCode(), fonts1.get(i).hashCode()); 1028 assertEquals(fonts1.get(i).hashCode(), fonts2.get(i).hashCode()); 1029 } 1030 } 1031 1032 @Test(expected = IllegalArgumentException.class) testMaxFontWeight()1033 public void testMaxFontWeight() throws IOException { 1034 final Resources res = InstrumentationRegistry.getTargetContext().getResources(); 1035 new Font.Builder(res, R.font.ascii).setWeight(FontStyle.FONT_WEIGHT_MAX + 1).build(); 1036 } 1037 1038 @Test(expected = IllegalArgumentException.class) testMinFontWeight()1039 public void testMinFontWeight() throws IOException { 1040 final Resources res = InstrumentationRegistry.getTargetContext().getResources(); 1041 new Font.Builder(res, R.font.ascii).setWeight(FontStyle.FONT_WEIGHT_MIN - 1).build(); 1042 } 1043 1044 @Test builder_with_font_with_axis()1045 public void builder_with_font_with_axis() throws IOException { 1046 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1047 1048 // WeightEqualsEmVariableFont adjust glyph advance as follows 1049 // glyph advance = 'wght' value / 1000 1050 // Thus, by setting text size to 1000px, the glyph advance will equals to passed wght value. 1051 Font baseFont = new Font.Builder(assets, "fonts/var_fonts/WidthEqualsEmVariableFont.ttf") 1052 .build(); 1053 1054 FontStyle style = new FontStyle(123, FontStyle.FONT_SLANT_ITALIC); 1055 1056 for (int width = 50; width < 1000; width += 50) { 1057 Font clonedFont = new Font.Builder(baseFont) 1058 .setWeight(style.getWeight()) 1059 .setSlant(style.getSlant()) 1060 .setFontVariationSettings("'wdth' " + width) 1061 .build(); 1062 1063 // New font should have the same style passed. 1064 assertEquals(style.getWeight(), clonedFont.getStyle().getWeight()); 1065 assertEquals(style.getSlant(), clonedFont.getStyle().getSlant()); 1066 1067 Paint p = new Paint(); 1068 p.setTextSize(1000); // make 1em = 1000px = weight 1069 p.setTypeface(new Typeface.CustomFallbackBuilder( 1070 new FontFamily.Builder(clonedFont).build() 1071 ).build()); 1072 assertEquals(width, p.measureText("a"), 0); 1073 } 1074 } 1075 1076 @Test builder_with_explicit_style()1077 public void builder_with_explicit_style() throws IOException { 1078 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1079 1080 Font baseFont = new Font.Builder(assets, "fonts/others/samplefont.ttf").build(); 1081 FontStyle style = new FontStyle(123, FontStyle.FONT_SLANT_ITALIC); 1082 Font clonedFont = new Font.Builder(baseFont) 1083 .setWeight(style.getWeight()) 1084 .setSlant(style.getSlant()) 1085 .build(); 1086 1087 assertEquals(style.getWeight(), clonedFont.getStyle().getWeight()); 1088 assertEquals(style.getSlant(), clonedFont.getStyle().getSlant()); 1089 } 1090 1091 @Test builder_style_resolve_default()1092 public void builder_style_resolve_default() throws IOException { 1093 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1094 1095 Font baseFont = new Font.Builder(assets, 1096 "fonts/family_selection/ttf/ascii_l3em_weight600_italic.ttf").build(); 1097 Font clonedFont = new Font.Builder(baseFont).build(); 1098 1099 assertEquals(600, clonedFont.getStyle().getWeight()); 1100 assertEquals(FontStyle.FONT_SLANT_ITALIC, clonedFont.getStyle().getSlant()); 1101 } 1102 1103 @Test getBoundingBox()1104 public void getBoundingBox() throws IOException { 1105 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1106 1107 Font font = new Font.Builder(assets, "fonts/measurement/a3em.ttf").build(); 1108 Paint paint = new Paint(); 1109 paint.setTextSize(100); // make 1em = 100px 1110 1111 int glyphID = 1; // See a3em.ttx file for the Glyph ID. 1112 1113 RectF rect = new RectF(); 1114 float advance = font.getGlyphBounds(glyphID, paint, rect); 1115 1116 assertEquals(100f, advance, 0f); 1117 // Glyph bbox is 0.1em shifted to right. See lsb value in hmtx in ttx file. 1118 assertEquals(rect.left, 10f, 0f); 1119 assertEquals(rect.top, -100f, 0f); 1120 assertEquals(rect.right, 110f, 0f); 1121 assertEquals(rect.bottom, 0f, 0f); 1122 } 1123 1124 @Test getFontMetrics()1125 public void getFontMetrics() throws IOException { 1126 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1127 1128 Font font = new Font.Builder(assets, "fonts/measurement/a3em.ttf").build(); 1129 Paint paint = new Paint(); 1130 paint.setTextSize(100); // make 1em = 100px 1131 1132 Paint.FontMetrics metrics = new Paint.FontMetrics(); 1133 font.getMetrics(paint, metrics); 1134 1135 assertEquals(-100f, metrics.ascent, 0f); 1136 assertEquals(20f, metrics.descent, 0f); 1137 // This refers head.yMax which is not explicitly visible in ttx file. 1138 assertEquals(-300f, metrics.top, 0f); 1139 // This refers head.yMin which is not explicitly visible in ttx file. 1140 assertEquals(0f, metrics.bottom, 0f); 1141 } 1142 1143 @Test byteBufferEquality()1144 public void byteBufferEquality() throws IOException { 1145 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1146 1147 Font aFont = new Font.Builder(assets, "fonts/others/samplefont.ttf").build(); 1148 // Copied font must be equals to original one. 1149 Font bFont = new Font.Builder(aFont).build(); 1150 assertEquals(aFont, bFont); 1151 assertEquals(bFont, aFont); 1152 1153 // Same source font must be equal. 1154 Font cFont = new Font.Builder(assets, "fonts/others/samplefont.ttf").build(); 1155 assertEquals(aFont, cFont); 1156 assertEquals(cFont, aFont); 1157 1158 // Created font from duplicated buffers must be equal. 1159 Font dFont = new Font.Builder(aFont.getBuffer().duplicate()).build(); 1160 Font eFont = new Font.Builder(aFont.getBuffer().duplicate()).build(); 1161 assertEquals(dFont, eFont); 1162 assertEquals(eFont, dFont); 1163 1164 // Different parameter should be unequal but sameSource returns true. 1165 Font fFont = new Font.Builder(aFont.getBuffer().duplicate()) 1166 .setFontVariationSettings("'wght' 400").build(); 1167 assertNotEquals(aFont, fFont); 1168 assertNotEquals(fFont, aFont); 1169 1170 // Different source must be not equals. 1171 Font gFont = new Font.Builder(assets, "fonts/others/samplefont2.ttf").build(); 1172 assertNotEquals(aFont, gFont); 1173 } 1174 1175 @Test fontIdentifier()1176 public void fontIdentifier() throws IOException { 1177 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1178 1179 Font aFont = new Font.Builder(assets, "fonts/others/samplefont.ttf").build(); 1180 // Copied font must be equals to original one. 1181 Font bFont = new Font.Builder(aFont).build(); 1182 assertEquals(aFont.getSourceIdentifier(), bFont.getSourceIdentifier()); 1183 1184 // Different parameter should be unequal but sameSource returns true. 1185 Font dFont = new Font.Builder(aFont) 1186 .setFontVariationSettings("'wght' 400") 1187 .setWeight(123) 1188 .build(); 1189 assertEquals(aFont.getSourceIdentifier(), dFont.getSourceIdentifier()); 1190 1191 // Different source must be not equals. 1192 Font gFont = new Font.Builder(assets, "fonts/others/samplefont2.ttf").build(); 1193 assertNotEquals(aFont.getSourceIdentifier(), gFont.getSourceIdentifier()); 1194 1195 Typeface typeface = new Typeface.CustomFallbackBuilder( 1196 new FontFamily.Builder( 1197 aFont 1198 ).build() 1199 ).build(); 1200 1201 Paint paint = new Paint(); 1202 paint.setTypeface(typeface); 1203 PositionedGlyphs glyphs = TextRunShaper.shapeTextRun("a", 0, 1, 0, 1, 0f, 0f, false, paint); 1204 assertEquals(aFont, glyphs.getFont(0)); 1205 assertEquals(aFont.getSourceIdentifier(), glyphs.getFont(0).getSourceIdentifier()); 1206 } 1207 1208 @Test byteBufferSameHash()1209 public void byteBufferSameHash() throws IOException { 1210 AssetManager assets = InstrumentationRegistry.getTargetContext().getAssets(); 1211 1212 Font aFont = new Font.Builder(assets, "fonts/others/samplefont.ttf").build(); 1213 // Copied font must be equals to original one. 1214 assertEquals(new Font.Builder(aFont).build().hashCode(), aFont.hashCode()); 1215 1216 // Same source font must be equal. 1217 assertEquals(new Font.Builder(assets, "fonts/others/samplefont.ttf").build().hashCode(), 1218 aFont.hashCode()); 1219 1220 // Created font from duplicated buffers must be equal. 1221 int cFontHash = new Font.Builder(aFont.getBuffer().duplicate()).build().hashCode(); 1222 int dFontHash = new Font.Builder(aFont.getBuffer().duplicate()).build().hashCode(); 1223 assertEquals(cFontHash, dFontHash); 1224 } 1225 } 1226