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