1 /* 2 * Copyright (C) 2008 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.cts; 18 19 20 import android.graphics.ColorFilter; 21 import android.graphics.MaskFilter; 22 import android.graphics.Matrix; 23 import android.graphics.Paint; 24 import android.graphics.Paint.Align; 25 import android.graphics.Paint.Cap; 26 import android.graphics.Paint.Join; 27 import android.graphics.Paint.Style; 28 import android.graphics.Path; 29 import android.graphics.PathEffect; 30 import android.graphics.Rasterizer; 31 import android.graphics.Rect; 32 import android.graphics.Shader; 33 import android.graphics.Bitmap; 34 import android.graphics.BitmapShader; 35 import android.graphics.Typeface; 36 import android.graphics.Xfermode; 37 import android.os.Build; 38 import android.os.LocaleList; 39 import android.test.AndroidTestCase; 40 import android.text.SpannedString; 41 import android.util.Log; 42 43 import java.util.Locale; 44 45 public class PaintTest extends AndroidTestCase { 46 47 private static final Typeface[] TYPEFACES = new Typeface[] { 48 Typeface.DEFAULT, 49 Typeface.DEFAULT_BOLD, 50 Typeface.MONOSPACE, 51 Typeface.SANS_SERIF, 52 Typeface.SERIF, 53 }; 54 testConstructor()55 public void testConstructor() { 56 new Paint(); 57 58 new Paint(1); 59 60 Paint p = new Paint(); 61 new Paint(p); 62 } 63 testBreakText()64 public void testBreakText() { 65 String text = "HIJKLMN"; 66 char[] textChars = text.toCharArray(); 67 SpannedString textSpan = new SpannedString(text); 68 69 Paint p = new Paint(); 70 71 // We need to turn off kerning in order to get accurate comparisons 72 p.setFlags(p.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG); 73 74 float[] widths = new float[text.length()]; 75 assertEquals(text.length(), p.getTextWidths(text, widths)); 76 77 float totalWidth = 0.0f; 78 for (int i = 0; i < text.length(); i++) { 79 totalWidth += widths[i]; 80 } 81 82 float[] measured = new float[1]; 83 for (int i = 0; i < text.length(); i++) { 84 assertBreakText(text, textChars, textSpan, i, i + 1, true, totalWidth, 1, widths[i]); 85 } 86 87 // Measure empty string 88 assertBreakText(text, textChars, textSpan, 0, 0, true, totalWidth, 0, 0); 89 90 // Measure substring from front: "HIJ" 91 assertBreakText(text, textChars, textSpan, 0, 3, true, totalWidth, 92 3, widths[0] + widths[1] + widths[2]); 93 94 // Reverse measure substring from front: "HIJ" 95 assertBreakText(text, textChars, textSpan, 0, 3, false, totalWidth, 96 3, widths[0] + widths[1] + widths[2]); 97 98 // Measure substring from back: "MN" 99 assertBreakText(text, textChars, textSpan, 5, 7, true, totalWidth, 100 2, widths[5] + widths[6]); 101 102 // Reverse measure substring from back: "MN" 103 assertBreakText(text, textChars, textSpan, 5, 7, false, totalWidth, 104 2, widths[5] + widths[6]); 105 106 // Measure substring in the middle: "JKL" 107 assertBreakText(text, textChars, textSpan, 2, 5, true, totalWidth, 108 3, widths[2] + widths[3] + widths[4]); 109 110 // Reverse measure substring in the middle: "JKL" 111 assertBreakText(text, textChars, textSpan, 2, 5, false, totalWidth, 112 3, widths[2] + widths[3] + widths[4]); 113 114 // Measure substring in the middle and restrict width to the first 2 characters. 115 assertBreakText(text, textChars, textSpan, 2, 5, true, widths[2] + widths[3], 116 2, widths[2] + widths[3]); 117 118 // Reverse measure substring in the middle and restrict width to the last 2 characters. 119 assertBreakText(text, textChars, textSpan, 2, 5, false, widths[3] + widths[4], 120 2, widths[3] + widths[4]); 121 122 // a single Emoji (U+1f601) 123 String emoji = "\ud83d\ude01"; 124 char[] emojiChars = emoji.toCharArray(); 125 SpannedString emojiSpan = new SpannedString(emoji); 126 127 float[] emojiWidths = new float[emoji.length()]; 128 assertEquals(emoji.length(), p.getTextWidths(emoji, emojiWidths)); 129 130 // Measure substring with a cluster 131 assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, true, 0, 132 0, 0); 133 134 // Measure substring with a cluster 135 assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, true, emojiWidths[0], 136 2, emojiWidths[0]); 137 138 // Reverse measure substring with a cluster 139 assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, false, 0, 140 0, 0); 141 142 // Measure substring with a cluster 143 assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, false, emojiWidths[0], 144 2, emojiWidths[0]); 145 } 146 assertBreakText(String text, char[] textChars, SpannedString textSpan, int start, int end, boolean measureForwards, float maxWidth, int expectedCount, float expectedWidth)147 private void assertBreakText(String text, char[] textChars, SpannedString textSpan, 148 int start, int end, boolean measureForwards, float maxWidth, int expectedCount, 149 float expectedWidth) { 150 Paint p = new Paint(); 151 152 // We need to turn off kerning in order to get accurate comparisons 153 p.setFlags(p.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG); 154 155 int count = end - start; 156 if (!measureForwards) { 157 count = -count; 158 } 159 160 float[][] measured = new float[][] { 161 new float[1], 162 new float[1], 163 new float[1] 164 }; 165 String textSlice = text.substring(start, end); 166 assertEquals(expectedCount, p.breakText(textSlice, measureForwards, maxWidth, measured[0])); 167 assertEquals(expectedCount, p.breakText(textChars, start, count, maxWidth, measured[1])); 168 assertEquals(expectedCount, p.breakText(textSpan, start, end, measureForwards, maxWidth, 169 measured[2])); 170 171 for (int i = 0; i < measured.length; i++) { 172 assertEquals("i: " + i, expectedWidth, measured[i][0]); 173 } 174 } 175 testSet()176 public void testSet() { 177 Paint p = new Paint(); 178 Paint p2 = new Paint(); 179 ColorFilter c = new ColorFilter(); 180 MaskFilter m = new MaskFilter(); 181 PathEffect e = new PathEffect(); 182 Rasterizer r = new Rasterizer(); 183 Shader s = new Shader(); 184 Typeface t = Typeface.DEFAULT; 185 Xfermode x = new Xfermode(); 186 187 p.setColorFilter(c); 188 p.setMaskFilter(m); 189 p.setPathEffect(e); 190 p.setRasterizer(r); 191 p.setShader(s); 192 p.setTypeface(t); 193 p.setXfermode(x); 194 p2.set(p); 195 assertEquals(c, p2.getColorFilter()); 196 assertEquals(m, p2.getMaskFilter()); 197 assertEquals(e, p2.getPathEffect()); 198 assertEquals(r, p2.getRasterizer()); 199 assertEquals(s, p2.getShader()); 200 assertEquals(t, p2.getTypeface()); 201 assertEquals(x, p2.getXfermode()); 202 203 p2.set(p2); 204 assertEquals(c, p2.getColorFilter()); 205 assertEquals(m, p2.getMaskFilter()); 206 assertEquals(e, p2.getPathEffect()); 207 assertEquals(r, p2.getRasterizer()); 208 assertEquals(s, p2.getShader()); 209 assertEquals(t, p2.getTypeface()); 210 assertEquals(x, p2.getXfermode()); 211 212 p.setColorFilter(null); 213 p.setMaskFilter(null); 214 p.setPathEffect(null); 215 p.setRasterizer(null); 216 p.setShader(null); 217 p.setTypeface(null); 218 p.setXfermode(null); 219 p2.set(p); 220 assertNull(p2.getColorFilter()); 221 assertNull(p2.getMaskFilter()); 222 assertNull(p2.getPathEffect()); 223 assertNull(p2.getRasterizer()); 224 assertNull(p2.getShader()); 225 assertNull(p2.getTypeface()); 226 assertNull(p2.getXfermode()); 227 228 p2.set(p2); 229 assertNull(p2.getColorFilter()); 230 assertNull(p2.getMaskFilter()); 231 assertNull(p2.getPathEffect()); 232 assertNull(p2.getRasterizer()); 233 assertNull(p2.getShader()); 234 assertNull(p2.getTypeface()); 235 assertNull(p2.getXfermode()); 236 } 237 testAccessStrokeCap()238 public void testAccessStrokeCap() { 239 Paint p = new Paint(); 240 241 p.setStrokeCap(Cap.BUTT); 242 assertEquals(Cap.BUTT, p.getStrokeCap()); 243 244 p.setStrokeCap(Cap.ROUND); 245 assertEquals(Cap.ROUND, p.getStrokeCap()); 246 247 p.setStrokeCap(Cap.SQUARE); 248 assertEquals(Cap.SQUARE, p.getStrokeCap()); 249 250 try { 251 p.setStrokeCap(null); 252 fail("Should throw an Exception"); 253 } catch (RuntimeException e) { 254 //except here 255 } 256 } 257 testAccessXfermode()258 public void testAccessXfermode() { 259 Paint p = new Paint(); 260 Xfermode x = new Xfermode(); 261 262 assertEquals(x, p.setXfermode(x)); 263 assertEquals(x, p.getXfermode()); 264 265 assertNull(p.setXfermode(null)); 266 assertNull(p.getXfermode()); 267 } 268 testAccessShader()269 public void testAccessShader() { 270 Paint p = new Paint(); 271 Shader s = new Shader(); 272 273 assertEquals(s, p.setShader(s)); 274 assertEquals(s, p.getShader()); 275 276 assertNull(p.setShader(null)); 277 assertNull(p.getShader()); 278 } 279 testShaderLocalMatrix()280 public void testShaderLocalMatrix() { 281 int width = 80; 282 int height = 120; 283 int[] color = new int[width * height]; 284 Bitmap bitmap = Bitmap.createBitmap(color, width, height, Bitmap.Config.RGB_565); 285 286 Paint p = new Paint(); 287 Matrix m = new Matrix(); 288 Shader s = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 289 290 // set the shaders matrix to a non identity value and attach to paint 291 m.setScale(10, 0); 292 s.setLocalMatrix(m); 293 p.setShader(s); 294 295 Matrix m2 = new Matrix(); 296 assertTrue(p.getShader().getLocalMatrix(m2)); 297 assertEquals(m, m2); 298 299 // updated the matrix again and set it on the shader but NOT the paint 300 m.setScale(0, 10); 301 s.setLocalMatrix(m); 302 303 // assert that the matrix on the paint's shader also changed 304 Matrix m3 = new Matrix(); 305 assertTrue(p.getShader().getLocalMatrix(m3)); 306 assertEquals(m, m3); 307 } 308 testSetAntiAlias()309 public void testSetAntiAlias() { 310 Paint p = new Paint(); 311 312 p.setAntiAlias(true); 313 assertTrue(p.isAntiAlias()); 314 315 p.setAntiAlias(false); 316 assertFalse(p.isAntiAlias()); 317 318 } 319 320 testAccessTypeface()321 public void testAccessTypeface() { 322 Paint p = new Paint(); 323 324 assertEquals(Typeface.DEFAULT, p.setTypeface(Typeface.DEFAULT)); 325 assertEquals(Typeface.DEFAULT, p.getTypeface()); 326 327 assertEquals(Typeface.DEFAULT_BOLD, p.setTypeface(Typeface.DEFAULT_BOLD)); 328 assertEquals(Typeface.DEFAULT_BOLD, p.getTypeface()); 329 330 assertEquals(Typeface.MONOSPACE, p.setTypeface(Typeface.MONOSPACE)); 331 assertEquals(Typeface.MONOSPACE, p.getTypeface()); 332 333 assertNull(p.setTypeface(null)); 334 assertNull(p.getTypeface()); 335 } 336 testAccessPathEffect()337 public void testAccessPathEffect() { 338 Paint p = new Paint(); 339 PathEffect e = new PathEffect(); 340 341 assertEquals(e, p.setPathEffect(e)); 342 assertEquals(e, p.getPathEffect()); 343 344 assertNull(p.setPathEffect(null)); 345 assertNull(p.getPathEffect()); 346 } 347 testSetFakeBoldText()348 public void testSetFakeBoldText() { 349 Paint p = new Paint(); 350 351 p.setFakeBoldText(true); 352 assertTrue(p.isFakeBoldText()); 353 354 p.setFakeBoldText(false); 355 assertFalse(p.isFakeBoldText()); 356 } 357 testAccessStrokeJoin()358 public void testAccessStrokeJoin() { 359 Paint p = new Paint(); 360 361 p.setStrokeJoin(Join.BEVEL); 362 assertEquals(Join.BEVEL, p.getStrokeJoin()); 363 364 p.setStrokeJoin(Join.MITER); 365 assertEquals(Join.MITER, p.getStrokeJoin()); 366 367 p.setStrokeJoin(Join.ROUND); 368 assertEquals(Join.ROUND, p.getStrokeJoin()); 369 370 try { 371 p.setStrokeJoin(null); 372 fail("Should throw an Exception"); 373 } catch (RuntimeException e) { 374 //except here 375 } 376 } 377 testAccessStyle()378 public void testAccessStyle() { 379 Paint p = new Paint(); 380 381 p.setStyle(Style.FILL); 382 assertEquals(Style.FILL, p.getStyle()); 383 384 p.setStyle(Style.FILL_AND_STROKE); 385 assertEquals(Style.FILL_AND_STROKE, p.getStyle()); 386 387 p.setStyle(Style.STROKE); 388 assertEquals(Style.STROKE, p.getStyle()); 389 390 try { 391 p.setStyle(null); 392 fail("Should throw an Exception"); 393 } catch (RuntimeException e) { 394 //except here 395 } 396 } 397 testGetFontSpacing()398 public void testGetFontSpacing() { 399 Paint p = new Paint(); 400 401 for (Typeface typeface : TYPEFACES) { 402 p.setTypeface(typeface); 403 404 p.setTextSize(10); 405 float spacing10 = p.getFontSpacing(); 406 assertTrue(spacing10 > 0); 407 408 p.setTextSize(20); 409 float spacing20 = p.getFontSpacing(); 410 assertTrue(spacing20 > spacing10); 411 } 412 } 413 testSetSubpixelText()414 public void testSetSubpixelText() { 415 Paint p = new Paint(); 416 417 p.setSubpixelText(true); 418 assertTrue(p.isSubpixelText()); 419 420 p.setSubpixelText(false); 421 assertFalse(p.isSubpixelText()); 422 } 423 testAccessTextScaleX()424 public void testAccessTextScaleX() { 425 Paint p = new Paint(); 426 427 p.setTextScaleX(2.0f); 428 assertEquals(2.0f, p.getTextScaleX()); 429 430 p.setTextScaleX(1.0f); 431 assertEquals(1.0f, p.getTextScaleX()); 432 433 p.setTextScaleX(0.0f); 434 assertEquals(0.0f, p.getTextScaleX()); 435 436 } 437 testAccessMaskFilter()438 public void testAccessMaskFilter() { 439 Paint p = new Paint(); 440 MaskFilter m = new MaskFilter(); 441 442 assertEquals(m, p.setMaskFilter(m)); 443 assertEquals(m, p.getMaskFilter()); 444 445 assertNull(p.setMaskFilter(null)); 446 assertNull(p.getMaskFilter()); 447 } 448 testAccessColorFilter()449 public void testAccessColorFilter() { 450 Paint p = new Paint(); 451 ColorFilter c = new ColorFilter(); 452 453 assertEquals(c, p.setColorFilter(c)); 454 assertEquals(c, p.getColorFilter()); 455 456 assertNull(p.setColorFilter(null)); 457 assertNull(p.getColorFilter()); 458 } 459 testAccessRasterizer()460 public void testAccessRasterizer() { 461 Paint p = new Paint(); 462 Rasterizer r = new Rasterizer(); 463 464 assertEquals(r, p.setRasterizer(r)); 465 assertEquals(r, p.getRasterizer()); 466 467 assertNull(p.setRasterizer(null)); 468 assertNull(p.getRasterizer()); 469 } 470 testSetARGB()471 public void testSetARGB() { 472 Paint p = new Paint(); 473 474 p.setARGB(0, 0, 0, 0); 475 assertEquals(0, p.getColor()); 476 477 p.setARGB(3, 3, 3, 3); 478 assertEquals((3 << 24) | (3 << 16) | (3 << 8) | 3, p.getColor()); 479 480 } 481 testAscent()482 public void testAscent() { 483 Paint p = new Paint(); 484 485 for (Typeface typeface : TYPEFACES) { 486 p.setTypeface(typeface); 487 488 p.setTextSize(10); 489 float ascent10 = p.ascent(); 490 assertTrue(ascent10 < 0); 491 492 p.setTextSize(20); 493 float ascent20 = p.ascent(); 494 assertTrue(ascent20 < ascent10); 495 } 496 } 497 498 public void testAccessTextSkewX() { 499 Paint p = new Paint(); 500 501 p.setTextSkewX(1.0f); 502 assertEquals(1.0f, p.getTextSkewX()); 503 504 p.setTextSkewX(0.0f); 505 assertEquals(0.0f, p.getTextSkewX()); 506 507 p.setTextSkewX(-0.25f); 508 assertEquals(-0.25f, p.getTextSkewX()); 509 } 510 511 public void testAccessTextSize() { 512 Paint p = new Paint(); 513 514 p.setTextSize(1.0f); 515 assertEquals(1.0f, p.getTextSize()); 516 517 p.setTextSize(2.0f); 518 assertEquals(2.0f, p.getTextSize()); 519 520 // text size should be greater than 0, so set -1 has no effect 521 p.setTextSize(-1.0f); 522 assertEquals(2.0f, p.getTextSize()); 523 524 // text size should be greater than or equals to 0 525 p.setTextSize(0.0f); 526 assertEquals(0.0f, p.getTextSize()); 527 } 528 529 public void testGetTextWidths() throws Exception { 530 String text = "HIJKLMN"; 531 char[] textChars = text.toCharArray(); 532 SpannedString textSpan = new SpannedString(text); 533 534 // Test measuring the widths of the entire text 535 assertGetTextWidths(text, textChars, textSpan, 0, 7); 536 537 // Test measuring a substring of the text 538 assertGetTextWidths(text, textChars, textSpan, 1, 3); 539 540 // Test measuring a substring of zero length. 541 assertGetTextWidths(text, textChars, textSpan, 3, 3); 542 543 // Test measuring substrings from the front and back 544 assertGetTextWidths(text, textChars, textSpan, 0, 2); 545 assertGetTextWidths(text, textChars, textSpan, 4, 7); 546 } 547 548 /** Tests all four overloads of getTextWidths are the same. */ 549 private void assertGetTextWidths(String text, char[] textChars, SpannedString textSpan, 550 int start, int end) { 551 Paint p = new Paint(); 552 int count = end - start; 553 float[][] widths = new float[][] { 554 new float[count], 555 new float[count], 556 new float[count], 557 new float[count] 558 }; 559 560 String textSlice = text.substring(start, end); 561 assertEquals(count, p.getTextWidths(textSlice, widths[0])); 562 assertEquals(count, p.getTextWidths(textChars, start, count, widths[1])); 563 assertEquals(count, p.getTextWidths(textSpan, start, end, widths[2])); 564 assertEquals(count, p.getTextWidths(text, start, end, widths[3])); 565 566 // Check that the widths returned by the overloads are the same. 567 for (int i = 0; i < count; i++) { 568 assertEquals(widths[0][i], widths[1][i]); 569 assertEquals(widths[1][i], widths[2][i]); 570 assertEquals(widths[2][i], widths[3][i]); 571 } 572 } 573 574 public void testSetStrikeThruText() { 575 Paint p = new Paint(); 576 577 p.setStrikeThruText(true); 578 assertTrue(p.isStrikeThruText()); 579 580 p.setStrikeThruText(false); 581 assertFalse(p.isStrikeThruText()); 582 } 583 584 public void testAccessTextAlign() { 585 Paint p = new Paint(); 586 587 p.setTextAlign(Align.CENTER); 588 assertEquals(Align.CENTER, p.getTextAlign()); 589 590 p.setTextAlign(Align.LEFT); 591 assertEquals(Align.LEFT, p.getTextAlign()); 592 593 p.setTextAlign(Align.RIGHT); 594 assertEquals(Align.RIGHT, p.getTextAlign()); 595 } 596 597 public void testAccessTextLocale() { 598 Paint p = new Paint(); 599 600 final Locale defaultLocale = Locale.getDefault(); 601 602 // Check default 603 assertEquals(defaultLocale, p.getTextLocale()); 604 605 // Check setter / getters 606 p.setTextLocale(Locale.US); 607 assertEquals(Locale.US, p.getTextLocale()); 608 assertEquals(new LocaleList(Locale.US), p.getTextLocales()); 609 610 p.setTextLocale(Locale.CHINESE); 611 assertEquals(Locale.CHINESE, p.getTextLocale()); 612 assertEquals(new LocaleList(Locale.CHINESE), p.getTextLocales()); 613 614 p.setTextLocale(Locale.JAPANESE); 615 assertEquals(Locale.JAPANESE, p.getTextLocale()); 616 assertEquals(new LocaleList(Locale.JAPANESE), p.getTextLocales()); 617 618 p.setTextLocale(Locale.KOREAN); 619 assertEquals(Locale.KOREAN, p.getTextLocale()); 620 assertEquals(new LocaleList(Locale.KOREAN), p.getTextLocales()); 621 622 // Check reverting back to default 623 p.setTextLocale(defaultLocale); 624 assertEquals(defaultLocale, p.getTextLocale()); 625 assertEquals(new LocaleList(defaultLocale), p.getTextLocales()); 626 627 // Check that we cannot pass a null locale 628 try { 629 p.setTextLocale(null); 630 fail("Setting the text locale to null should throw"); 631 } catch (Throwable e) { 632 assertEquals(IllegalArgumentException.class, e.getClass()); 633 } 634 } 635 636 public void testAccessTextLocales() { 637 Paint p = new Paint(); 638 639 final LocaleList defaultLocales = LocaleList.getDefault(); 640 641 // Check default 642 assertEquals(defaultLocales, p.getTextLocales()); 643 644 // Check setter / getters for a one-member locale list 645 p.setTextLocales(new LocaleList(Locale.CHINESE)); 646 assertEquals(Locale.CHINESE, p.getTextLocale()); 647 assertEquals(new LocaleList(Locale.CHINESE), p.getTextLocales()); 648 649 // Check setter / getters for a two-member locale list 650 p.setTextLocales(LocaleList.forLanguageTags("fr,de")); 651 assertEquals(Locale.forLanguageTag("fr"), p.getTextLocale()); 652 assertEquals(LocaleList.forLanguageTags("fr,de"), p.getTextLocales()); 653 654 // Check reverting back to default 655 p.setTextLocales(defaultLocales); 656 assertEquals(defaultLocales, p.getTextLocales()); 657 658 // Check that we cannot pass a null locale list 659 try { 660 p.setTextLocales(null); 661 fail("Setting the text locale list to null should throw"); 662 } catch (Throwable e) { 663 assertEquals(IllegalArgumentException.class, e.getClass()); 664 } 665 666 // Check that we cannot pass an empty locale list 667 try { 668 p.setTextLocales(new LocaleList()); 669 fail("Setting the text locale list to an empty list should throw"); 670 } catch (Throwable e) { 671 assertEquals(IllegalArgumentException.class, e.getClass()); 672 } 673 } 674 675 public void testGetFillPath() { 676 Paint p = new Paint(); 677 Path path1 = new Path(); 678 Path path2 = new Path(); 679 680 assertTrue(path1.isEmpty()); 681 assertTrue(path2.isEmpty()); 682 p.getFillPath(path1, path2); 683 assertTrue(path1.isEmpty()); 684 assertTrue(path2.isEmpty()); 685 686 // No setter 687 688 } 689 690 public void testAccessAlpha() { 691 Paint p = new Paint(); 692 693 p.setAlpha(0); 694 assertEquals(0, p.getAlpha()); 695 696 p.setAlpha(255); 697 assertEquals(255, p.getAlpha()); 698 699 // set value should between 0 and 255, so 266 is rounded to 10 700 p.setAlpha(266); 701 assertEquals(10, p.getAlpha()); 702 703 // set value should between 0 and 255, so -20 is rounded to 236 704 p.setAlpha(-20); 705 assertEquals(236, p.getAlpha()); 706 } 707 708 public void testSetFilterBitmap() { 709 Paint p = new Paint(); 710 711 p.setFilterBitmap(true); 712 assertTrue(p.isFilterBitmap()); 713 714 p.setFilterBitmap(false); 715 assertFalse(p.isFilterBitmap()); 716 } 717 718 public void testAccessColor() { 719 Paint p = new Paint(); 720 721 p.setColor(1); 722 assertEquals(1, p.getColor()); 723 724 p.setColor(0); 725 assertEquals(0, p.getColor()); 726 727 p.setColor(255); 728 assertEquals(255, p.getColor()); 729 730 p.setColor(-1); 731 assertEquals(-1, p.getColor()); 732 733 p.setColor(256); 734 assertEquals(256, p.getColor()); 735 } 736 737 public void testSetShadowLayer() { 738 new Paint().setShadowLayer(10, 1, 1, 0); 739 } 740 741 public void testGetFontMetrics1() { 742 Paint p = new Paint(); 743 Paint.FontMetrics fm = new Paint.FontMetrics(); 744 745 for (Typeface typeface : TYPEFACES) { 746 p.setTypeface(typeface); 747 748 p.setTextSize(10); 749 float spacing10 = p.getFontMetrics(fm); 750 assertEquals(p.ascent(), fm.ascent); 751 assertEquals(p.descent(), fm.descent); 752 753 p.setTextSize(20); 754 float spacing20 = p.getFontMetrics(fm); 755 assertEquals(p.ascent(), fm.ascent); 756 assertEquals(p.descent(), fm.descent); 757 } 758 } 759 760 public void testGetFontMetrics2() { 761 Paint p = new Paint(); 762 763 for (Typeface typeface : TYPEFACES) { 764 p.setTypeface(typeface); 765 766 p.setTextSize(10); 767 Paint.FontMetrics fm = p.getFontMetrics(); 768 assertEquals(p.ascent(), fm.ascent); 769 assertEquals(p.descent(), fm.descent); 770 771 p.setTextSize(20); 772 fm = p.getFontMetrics(); 773 assertEquals(p.ascent(), fm.ascent); 774 assertEquals(p.descent(), fm.descent); 775 } 776 } 777 778 public void testAccessStrokeMiter() { 779 Paint p = new Paint(); 780 781 p.setStrokeMiter(0.0f); 782 assertEquals(0.0f, p.getStrokeMiter()); 783 784 p.setStrokeMiter(10.0f); 785 assertEquals(10.0f, p.getStrokeMiter()); 786 787 // set value should be greater or equal to 0, set to -10.0f has no effect 788 p.setStrokeMiter(-10.0f); 789 assertEquals(10.0f, p.getStrokeMiter()); 790 } 791 792 public void testClearShadowLayer() { 793 new Paint().clearShadowLayer(); 794 } 795 796 public void testSetUnderlineText() { 797 Paint p = new Paint(); 798 799 p.setUnderlineText(true); 800 assertTrue(p.isUnderlineText()); 801 802 p.setUnderlineText(false); 803 assertFalse(p.isUnderlineText()); 804 } 805 806 public void testSetDither() { 807 Paint p = new Paint(); 808 809 p.setDither(true); 810 assertTrue(p.isDither()); 811 812 p.setDither(false); 813 assertFalse(p.isDither()); 814 } 815 816 public void testDescent() { 817 Paint p = new Paint(); 818 819 for (Typeface typeface : TYPEFACES) { 820 p.setTypeface(typeface); 821 822 p.setTextSize(10); 823 float descent10 = p.descent(); 824 assertTrue(descent10 > 0); 825 826 p.setTextSize(20); 827 float descent20 = p.descent(); 828 assertTrue(descent20 > descent10); 829 } 830 } 831 832 public void testAccessFlags() { 833 Paint p = new Paint(); 834 835 p.setFlags(Paint.ANTI_ALIAS_FLAG); 836 assertEquals(Paint.ANTI_ALIAS_FLAG, p.getFlags()); 837 838 p.setFlags(Paint.DEV_KERN_TEXT_FLAG); 839 assertEquals(Paint.DEV_KERN_TEXT_FLAG, p.getFlags()); 840 } 841 842 public void testAccessStrokeWidth() { 843 Paint p = new Paint(); 844 845 p.setStrokeWidth(0.0f); 846 assertEquals(0.0f, p.getStrokeWidth()); 847 848 p.setStrokeWidth(10.0f); 849 assertEquals(10.0f, p.getStrokeWidth()); 850 851 // set value must greater or equal to 0, set -10.0f has no effect 852 p.setStrokeWidth(-10.0f); 853 assertEquals(10.0f, p.getStrokeWidth()); 854 } 855 856 public void testSetFontFeatureSettings() { 857 Paint p = new Paint(); 858 // Roboto font (system default) has "fi" ligature 859 String text = "fi"; 860 float[] widths = new float[text.length()]; 861 p.getTextWidths(text, widths); 862 assertTrue(widths[0] > 0.0f); 863 assertEquals(0.0f, widths[1]); 864 865 // Disable ligature using OpenType feature 866 p.setFontFeatureSettings("'liga' off"); 867 p.getTextWidths(text, widths); 868 assertTrue(widths[0] > 0.0f); 869 assertTrue(widths[1] > 0.0f); 870 871 // Re-enable ligature 872 p.setFontFeatureSettings("'liga' on"); 873 p.getTextWidths(text, widths); 874 assertTrue(widths[0] > 0.0f); 875 assertEquals(0.0f, widths[1]); 876 } 877 testGetTextBounds()878 public void testGetTextBounds() { 879 Paint p = new Paint(); 880 p.setTextSize(10); 881 String text1 = "hello"; 882 Rect bounds1 = new Rect(); 883 Rect bounds2 = new Rect(); 884 p.getTextBounds(text1, 0, text1.length(), bounds1); 885 char[] textChars1 = text1.toCharArray(); 886 p.getTextBounds(textChars1, 0, textChars1.length, bounds2); 887 // verify that string and char array methods produce consistent results 888 assertEquals(bounds1, bounds2); 889 String text2 = "hello world"; 890 891 // verify substring produces consistent results 892 p.getTextBounds(text2, 0, text1.length(), bounds2); 893 assertEquals(bounds1, bounds2); 894 895 // longer string is expected to have same left edge but be wider 896 p.getTextBounds(text2, 0, text2.length(), bounds2); 897 assertEquals(bounds1.left, bounds2.left); 898 assertTrue(bounds2.right > bounds1.right); 899 900 // bigger size implies bigger bounding rect 901 p.setTextSize(20); 902 p.getTextBounds(text1, 0, text1.length(), bounds2); 903 assertTrue(bounds2.right > bounds1.right); 904 assertTrue(bounds2.bottom - bounds2.top > bounds1.bottom - bounds1.top); 905 } 906 testReset()907 public void testReset() { 908 Paint p = new Paint(); 909 ColorFilter c = new ColorFilter(); 910 MaskFilter m = new MaskFilter(); 911 PathEffect e = new PathEffect(); 912 Rasterizer r = new Rasterizer(); 913 Shader s = new Shader(); 914 Typeface t = Typeface.DEFAULT; 915 Xfermode x = new Xfermode(); 916 917 p.setColorFilter(c); 918 p.setMaskFilter(m); 919 p.setPathEffect(e); 920 p.setRasterizer(r); 921 p.setShader(s); 922 p.setTypeface(t); 923 p.setXfermode(x); 924 p.setFlags(Paint.ANTI_ALIAS_FLAG); 925 assertEquals(c, p.getColorFilter()); 926 assertEquals(m, p.getMaskFilter()); 927 assertEquals(e, p.getPathEffect()); 928 assertEquals(r, p.getRasterizer()); 929 assertEquals(s, p.getShader()); 930 assertEquals(t, p.getTypeface()); 931 assertEquals(x, p.getXfermode()); 932 assertEquals(Paint.ANTI_ALIAS_FLAG, p.getFlags()); 933 934 p.reset(); 935 assertEquals(Paint.DEV_KERN_TEXT_FLAG | Paint.EMBEDDED_BITMAP_TEXT_FLAG, p.getFlags()); 936 assertEquals(null, p.getColorFilter()); 937 assertEquals(null, p.getMaskFilter()); 938 assertEquals(null, p.getPathEffect()); 939 assertEquals(null, p.getRasterizer()); 940 assertEquals(null, p.getShader()); 941 assertEquals(null, p.getTypeface()); 942 assertEquals(null, p.getXfermode()); 943 } 944 testSetLinearText()945 public void testSetLinearText() { 946 Paint p = new Paint(); 947 948 p.setLinearText(true); 949 assertTrue(p.isLinearText()); 950 951 p.setLinearText(false); 952 assertFalse(p.isLinearText()); 953 } 954 testGetFontMetricsInt1()955 public void testGetFontMetricsInt1() { 956 Paint p = new Paint(); 957 Paint.FontMetricsInt fmi = new Paint.FontMetricsInt(); 958 959 for (Typeface typeface : TYPEFACES) { 960 p.setTypeface(typeface); 961 962 p.setTextSize(10); 963 p.getFontMetricsInt(fmi); 964 assertEquals(Math.round(p.ascent()), fmi.ascent); 965 assertEquals(Math.round(p.descent()), fmi.descent); 966 967 p.setTextSize(20); 968 p.getFontMetricsInt(fmi); 969 assertEquals(Math.round(p.ascent()), fmi.ascent); 970 assertEquals(Math.round(p.descent()), fmi.descent); 971 } 972 } 973 testGetFontMetricsInt2()974 public void testGetFontMetricsInt2() { 975 Paint p = new Paint(); 976 Paint.FontMetricsInt fmi; 977 978 for (Typeface typeface : TYPEFACES) { 979 p.setTypeface(typeface); 980 981 p.setTextSize(10); 982 fmi = p.getFontMetricsInt(); 983 assertEquals(Math.round(p.ascent()), fmi.ascent); 984 assertEquals(Math.round(p.descent()), fmi.descent); 985 986 p.setTextSize(20); 987 fmi = p.getFontMetricsInt(); 988 assertEquals(Math.round(p.ascent()), fmi.ascent); 989 assertEquals(Math.round(p.descent()), fmi.descent); 990 } 991 } 992 testMeasureText()993 public void testMeasureText() { 994 String text = "HIJKLMN"; 995 char[] textChars = text.toCharArray(); 996 SpannedString textSpan = new SpannedString(text); 997 998 Paint p = new Paint(); 999 1000 // We need to turn off kerning in order to get accurate comparisons 1001 p.setFlags(p.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG); 1002 1003 float[] widths = new float[text.length()]; 1004 for (int i = 0; i < widths.length; i++) { 1005 widths[i] = p.measureText(text, i, i + 1); 1006 } 1007 1008 float totalWidth = 0; 1009 for (int i = 0; i < widths.length; i++) { 1010 totalWidth += widths[i]; 1011 } 1012 1013 // Test measuring the widths of the entire text 1014 assertMeasureText(text, textChars, textSpan, 0, 7, totalWidth); 1015 1016 // Test measuring a substring of the text 1017 assertMeasureText(text, textChars, textSpan, 1, 3, widths[1] + widths[2]); 1018 1019 // Test measuring a substring of zero length. 1020 assertMeasureText(text, textChars, textSpan, 3, 3, 0); 1021 1022 // Test measuring substrings from the front and back 1023 assertMeasureText(text, textChars, textSpan, 0, 2, widths[0] + widths[1]); 1024 assertMeasureText(text, textChars, textSpan, 4, 7, widths[4] + widths[5] + widths[6]); 1025 } 1026 testMeasureTextContext()1027 public void testMeasureTextContext() { 1028 Paint p = new Paint(); 1029 // Arabic LAM, which is different width depending on context 1030 String shortString = "\u0644"; 1031 String longString = "\u0644\u0644\u0644"; 1032 char[] longChars = longString.toCharArray(); 1033 SpannedString longSpanned = new SpannedString(longString); 1034 float width = p.measureText(shortString); 1035 // Verify that measurement of substring is consistent no matter what surrounds it. 1036 assertMeasureText(longString, longChars, longSpanned, 0, 1, width); 1037 assertMeasureText(longString, longChars, longSpanned, 1, 2, width); 1038 assertMeasureText(longString, longChars, longSpanned, 2, 3, width); 1039 } 1040 testMeasureTextWithLongText()1041 public void testMeasureTextWithLongText() { 1042 // This test is not compatible with 4.0.3 1043 if ("4.0.3".equals(Build.VERSION.RELEASE)) { 1044 return; 1045 } 1046 1047 final int MAX_COUNT = 65535; 1048 char[] longText = new char[MAX_COUNT]; 1049 for (int n = 0; n < MAX_COUNT; n++) { 1050 longText[n] = 'm'; 1051 } 1052 1053 Paint p = new Paint(); 1054 float width = p.measureText(longText, 0, 1); 1055 assertEquals(true, width > 0); 1056 } 1057 1058 /** Tests that all four overloads of measureText are the same and match some value. */ assertMeasureText(String text, char[] textChars, SpannedString textSpan, int start, int end, float expectedWidth)1059 private void assertMeasureText(String text, char[] textChars, SpannedString textSpan, 1060 int start, int end, float expectedWidth) { 1061 Paint p = new Paint(); 1062 1063 // We need to turn off kerning in order to get accurate comparisons 1064 p.setFlags(p.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG); 1065 1066 int count = end - start; 1067 float[] widths = new float[] {-1, -1, -1, -1}; 1068 1069 String textSlice = text.substring(start, end); 1070 widths[0] = p.measureText(textSlice); 1071 widths[1] = p.measureText(textChars, start, count); 1072 widths[2] = p.measureText(textSpan, start, end); 1073 widths[3] = p.measureText(text, start, end); 1074 1075 // Check that the widths returned by the overloads are the same. 1076 assertEquals(widths[0], widths[1]); 1077 assertEquals(widths[1], widths[2]); 1078 assertEquals(widths[2], widths[3]); 1079 assertEquals(widths[3], expectedWidth); 1080 } 1081 testGetTextPath1()1082 public void testGetTextPath1() { 1083 Paint p = new Paint(); 1084 char[] chars = {'H', 'I', 'J', 'K', 'L', 'M', 'N'}; 1085 Path path = new Path(); 1086 1087 assertTrue(path.isEmpty()); 1088 p.getTextPath(chars, 0, 7, 0, 0, path); 1089 assertFalse(path.isEmpty()); 1090 1091 try { 1092 p.getTextPath(chars, -2, 7, 0, 0, path); 1093 fail("Should throw an exception here"); 1094 } catch (RuntimeException e) { 1095 } 1096 1097 try { 1098 p.getTextPath(chars, 0, -3, 0, 0, path); 1099 fail("Should throw an exception here"); 1100 } catch (RuntimeException e) { 1101 } 1102 1103 try { 1104 p.getTextPath(chars, 3, 7, 0, 0, path); 1105 fail("Should throw an exception here"); 1106 } catch (RuntimeException e) { 1107 } 1108 1109 } 1110 testGetTextPath2()1111 public void testGetTextPath2() { 1112 Paint p = new Paint(); 1113 String string = "HIJKLMN"; 1114 Path path = new Path(); 1115 1116 assertTrue(path.isEmpty()); 1117 p.getTextPath(string, 0, 7, 0, 0, path); 1118 assertFalse(path.isEmpty()); 1119 1120 try { 1121 p.getTextPath(string, -2, 7, 0, 0, path); 1122 fail("Should throw an exception here"); 1123 } catch (RuntimeException e) { 1124 } 1125 1126 try { 1127 p.getTextPath(string, 0, -3, 0, 0, path); 1128 fail("Should throw an exception here"); 1129 } catch (RuntimeException e) { 1130 } 1131 1132 try { 1133 p.getTextPath(string, 7, 3, 0, 0, path); 1134 fail("Should throw an exception here"); 1135 } catch (RuntimeException e) { 1136 } 1137 1138 try { 1139 p.getTextPath(string, 3, 9, 0, 0, path); 1140 fail("Should throw an exception here"); 1141 } catch (RuntimeException e) { 1142 } 1143 } 1144 testHasGlyph()1145 public void testHasGlyph() { 1146 Paint p = new Paint(); 1147 1148 // This method tests both the logic of hasGlyph and the sanity of fonts present 1149 // on the device. 1150 assertTrue(p.hasGlyph("A")); 1151 assertFalse(p.hasGlyph("\uFFFE")); // U+FFFE is guaranteed to be a noncharacter 1152 1153 // Roboto 2 (the default typeface) does have an "fi" glyph and is mandated by CDD 1154 assertTrue(p.hasGlyph("fi")); 1155 assertFalse(p.hasGlyph("ab")); // but it does not contain an "ab" glyph 1156 assertTrue(p.hasGlyph("\u02E5\u02E9")); // IPA tone mark ligature 1157 1158 // variation selectors 1159 assertFalse(p.hasGlyph("a\uFE0F")); 1160 assertFalse(p.hasGlyph("a\uDB40\uDDEF")); // UTF-16 encoding of U+E01EF 1161 assertFalse(p.hasGlyph("\u2229\uFE0F")); // base character is in mathematical symbol font 1162 // Note: U+FE0F is variation selection, unofficially reserved for emoji 1163 1164 // regional indicator symbols 1165 assertTrue(p.hasGlyph("\uD83C\uDDEF\uD83C\uDDF5")); // "JP" U+1F1EF U+1F1F5 1166 assertFalse(p.hasGlyph("\uD83C\uDDFF\uD83C\uDDFF")); // "ZZ" U+1F1FF U+1F1FF 1167 1168 // Mongolian, which is an optional font, but if present, should support FVS 1169 if (p.hasGlyph("\u182D")) { 1170 assertTrue(p.hasGlyph("\u182D\u180B")); 1171 } 1172 1173 // TODO: when we support variation selectors, add positive tests 1174 1175 // Unicode 7.0, 8.0, and 9.0 emoji should be supported. 1176 assertTrue(p.hasGlyph("\uD83D\uDD75")); // SLEUTH OR SPY is introduced in Unicode 7.0 1177 assertTrue(p.hasGlyph("\uD83C\uDF2E")); // TACO is introduced in Unicode 8.0 1178 assertTrue(p.hasGlyph("\uD83E\uDD33")); // SELFIE is introduced in Unicode 9.0 1179 } 1180 testGetRunAdvance()1181 public void testGetRunAdvance() { 1182 Paint p = new Paint(); 1183 { 1184 // LTR 1185 String string = "abcdef"; 1186 { 1187 final float width = p.getRunAdvance(string, 0, string.length(), 0, 1188 string.length(), false, 0); 1189 assertEquals(0.0f, width); 1190 } 1191 { 1192 for (int i = 0; i < string.length(); i++) { 1193 final float width = p.getRunAdvance(string, i, i + 1, 0, string.length(), 1194 false, i); 1195 assertEquals(0.0f, width); 1196 } 1197 } 1198 { 1199 final float widthToMid = p.getRunAdvance(string, 0, string.length(), 0, 1200 string.length(), false, string.length() / 2); 1201 final float widthToTail = p.getRunAdvance(string, 0, string.length(), 0, 1202 string.length(), false, string.length()); 1203 assertTrue(widthToMid > 0.0f); 1204 assertTrue(widthToTail > widthToMid); 1205 } 1206 { 1207 final float widthFromHead = p.getRunAdvance(string, 0, string.length(), 0, 1208 string.length(), false, string.length()); 1209 final float widthFromSecond = p.getRunAdvance(string, 1, string.length(), 0, 1210 string.length(), false, string.length()); 1211 assertTrue(widthFromHead > widthFromSecond); 1212 } 1213 { 1214 float width = 0.0f; 1215 for (int i = 0; i < string.length(); i++) { 1216 width += p.getRunAdvance(string, i, i + 1, 0, string.length(), false, i + 1); 1217 } 1218 final float totalWidth = p.getRunAdvance(string, 0, string.length(), 0, 1219 string.length(), false, string.length()); 1220 assertEquals(totalWidth, width, 1.0f); 1221 } 1222 } 1223 { 1224 // RTL 1225 String string = "\u0644\u063A\u0629 \u0639\u0631\u0628\u064A\u0629"; // Arabic 1226 { 1227 final float width = p.getRunAdvance(string, 0, string.length(), 0, 1228 string.length(), true, 0); 1229 assertEquals(0.0f, width); 1230 } 1231 { 1232 for (int i = 0; i < string.length(); i++) { 1233 final float width = p.getRunAdvance(string, i, i + 1, 0, string.length(), 1234 true, i); 1235 assertEquals(0.0f, width); 1236 } 1237 } 1238 { 1239 final float widthToMid = p.getRunAdvance(string, 0, string.length(), 0, 1240 string.length(), true, string.length() / 2); 1241 final float widthToTail = p.getRunAdvance(string, 0, string.length(), 0, 1242 string.length(), true, string.length()); 1243 assertTrue(widthToMid > 0.0f); 1244 assertTrue(widthToTail > widthToMid); 1245 } 1246 { 1247 final float widthFromHead = p.getRunAdvance(string, 0, string.length(), 0, 1248 string.length(), true, string.length()); 1249 final float widthFromSecond = p.getRunAdvance(string, 1, string.length(), 0, 1250 string.length(), true, string.length()); 1251 assertTrue(widthFromHead > widthFromSecond); 1252 } 1253 } 1254 } 1255 testGetRunAdvance_invalidArguments()1256 public void testGetRunAdvance_invalidArguments() { 1257 Paint p = new Paint(); 1258 try { 1259 p.getRunAdvance((CharSequence)null, 0, 0, 0, 0, false, 0); 1260 fail("Should throw an IllegalArgumentException."); 1261 } catch (IllegalArgumentException e) { 1262 } catch (Exception e) { 1263 fail("Should throw an IllegalArgumentException."); 1264 } 1265 1266 try { 1267 p.getRunAdvance((char[])null, 0, 0, 0, 0, false, 0); 1268 fail("Should throw an IllegalArgumentException."); 1269 } catch (IllegalArgumentException e) { 1270 } catch (Exception e) { 1271 fail("Should throw an IllegalArgumentException."); 1272 } 1273 1274 final String string = "abcde"; 1275 1276 try { 1277 // text length < context end 1278 p.getRunAdvance(string, 0, string.length(), 0, string.length() + 1, false, 1279 string.length()); 1280 fail("Should throw an IndexOutOfBoundsException."); 1281 } catch (IndexOutOfBoundsException e) { 1282 } catch (Exception e) { 1283 fail("Should throw an IndexOutOfBoundsException."); 1284 } 1285 try { 1286 // context end < end 1287 p.getRunAdvance(string, 0, string.length(), 0, string.length() - 1, false, 0); 1288 fail("Should throw an IndexOutOfBoundsException."); 1289 } catch (IndexOutOfBoundsException e) { 1290 } catch (Exception e) { 1291 fail("Should throw an IndexOutOfBoundsException."); 1292 } 1293 try { 1294 // end < offset 1295 p.getRunAdvance(string, 0, string.length() - 1, 0, string.length() - 1, false, 1296 string.length()); 1297 fail("Should throw an IndexOutOfBoundsException."); 1298 } catch (IndexOutOfBoundsException e) { 1299 } catch (Exception e) { 1300 fail("Should throw an IndexOutOfBoundsException."); 1301 } 1302 try { 1303 // offset < start 1304 p.getRunAdvance(string, 1, string.length(), 1, string.length(), false, 0); 1305 fail("Should throw an IndexOutOfBoundsException."); 1306 } catch (IndexOutOfBoundsException e) { 1307 } catch (Exception e) { 1308 fail("Should throw an IndexOutOfBoundsException."); 1309 } 1310 try { 1311 // start < context start 1312 p.getRunAdvance(string, 0, string.length(), 1, string.length(), false, 1); 1313 fail("Should throw an IndexOutOfBoundsException."); 1314 } catch (IndexOutOfBoundsException e) { 1315 } catch (Exception e) { 1316 fail("Should throw an IndexOutOfBoundsException."); 1317 } 1318 try { 1319 // context start < 0 1320 p.getRunAdvance(string, 0, string.length(), -1, string.length(), false, 0); 1321 fail("Should throw an IndexOutOfBoundsException."); 1322 } catch (IndexOutOfBoundsException e) { 1323 } catch (Exception e) { 1324 fail("Should throw an IndexOutOfBoundsException."); 1325 } 1326 } 1327 testGetRunAdvance_nonzeroIndex()1328 public void testGetRunAdvance_nonzeroIndex() { 1329 Paint p = new Paint(); 1330 final String text = "Android powers hundreds of millions of mobile " + 1331 "devices in more than 190 countries around the world. It's" + 1332 "the largest installed base of any mobile platform and" + 1333 "growing fast—every day another million users power up their" + 1334 "Android devices for the first time and start looking for" + 1335 "apps, games, and other digital content."; 1336 // Test offset index does not affect width. 1337 final float widthAndroidFirst = p.getRunAdvance( 1338 text, 0, 7, 0, text.length(), false, 7); 1339 final float widthAndroidSecond = p.getRunAdvance( 1340 text, 215, 222, 0, text.length(), false, 222); 1341 assertTrue(Math.abs(widthAndroidFirst - widthAndroidSecond) < 1); 1342 } 1343 1344 public void testGetRunAdvance_glyphDependingContext() { 1345 Paint p = new Paint(); 1346 // Test the context change the character shape. 1347 // First character should be isolated form because the context ends at index 1. 1348 final float isolatedFormWidth = p.getRunAdvance("\u0644\u0644", 0, 1, 0, 1, true, 1); 1349 // First character should be initial form because the context ends at index 2. 1350 final float initialFormWidth = p.getRunAdvance("\u0644\u0644", 0, 1, 0, 2, true, 1); 1351 assertTrue(isolatedFormWidth > initialFormWidth); 1352 } 1353 testGetRunAdvance_arabic()1354 public void testGetRunAdvance_arabic() { 1355 Paint p = new Paint(); 1356 // Test total width is equals to sum of each character's width. 1357 // "What is Unicode?" in Arabic. 1358 final String text = 1359 "\u0645\u0627\u0020\u0647\u064A\u0020\u0627\u0644\u0634" + 1360 "\u0641\u0631\u0629\u0020\u0627\u0644\u0645\u0648\u062D" + 1361 "\u062F\u0629\u0020\u064A\u0648\u0646\u064A\u0643\u0648" + 1362 "\u062F\u061F"; 1363 final float totalWidth = p.getRunAdvance( 1364 text, 0, text.length(), 0, text.length(), true, text.length()); 1365 float sumOfCharactersWidth = 0; 1366 for (int i = 0; i < text.length(); i++) { 1367 sumOfCharactersWidth += p.getRunAdvance( 1368 text, i, i + 1, 0, text.length(), true, i + 1); 1369 } 1370 assertTrue(Math.abs(totalWidth - sumOfCharactersWidth) < 1); 1371 } 1372 1373 public void testGetOffsetForAdvance() { 1374 Paint p = new Paint(); 1375 { 1376 // LTR 1377 String string = "abcdef"; 1378 { 1379 for (int offset = 0; offset <= string.length(); ++offset) { 1380 final float widthToOffset = p.getRunAdvance(string, 0, 1381 string.length(), 0, string.length(), false, offset); 1382 final int restoredOffset = p.getOffsetForAdvance(string, 0, 1383 string.length(), 0, string.length(), false, widthToOffset); 1384 assertEquals(offset, restoredOffset); 1385 } 1386 } 1387 { 1388 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1389 string.length(), false, -10.0f); 1390 assertEquals(0, offset); 1391 } 1392 { 1393 final float widthToEnd = p.getRunAdvance(string, 0, string.length(), 0, 1394 string.length(), true, string.length()); 1395 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1396 string.length(), true, widthToEnd + 10.0f); 1397 assertEquals(string.length(), offset); 1398 } 1399 } 1400 { 1401 // RTL 1402 String string = "\u0639\u0631\u0628\u0649"; // Arabic 1403 { 1404 for (int offset = 0; offset <= string.length(); ++offset) { 1405 final float widthToOffset = p.getRunAdvance(string, 0, 1406 string.length(), 0, string.length(), true, offset); 1407 final int restoredOffset = p.getOffsetForAdvance(string, 0, 1408 string.length(), 0, string.length(), true, widthToOffset); 1409 assertEquals(offset, restoredOffset); 1410 } 1411 } 1412 { 1413 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1414 string.length(), true, -10.0f); 1415 assertEquals(0, offset); 1416 } 1417 { 1418 final float widthToEnd = p.getRunAdvance(string, 0, string.length(), 0, 1419 string.length(), true, string.length()); 1420 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1421 string.length(), true, widthToEnd + 10.0f); 1422 assertEquals(string.length(), offset); 1423 } 1424 } 1425 } 1426 1427 public void testGetOffsetForAdvance_invalidArguments() { 1428 Paint p = new Paint(); 1429 try { 1430 p.getOffsetForAdvance((CharSequence)null, 0, 0, 0, 0, false, 0.0f); 1431 fail("Should throw an IllegalArgumentException."); 1432 } catch (IllegalArgumentException e) { 1433 } catch (Exception e) { 1434 fail("Should throw an IllegalArgumentException."); 1435 } 1436 try { 1437 p.getOffsetForAdvance((char[])null, 0, 0, 0, 0, false, 0.0f); 1438 fail("Should throw an IllegalArgumentException."); 1439 } catch (IllegalArgumentException e) { 1440 } catch (Exception e) { 1441 fail("Should throw an IllegalArgumentException."); 1442 } 1443 1444 final String string = "abcde"; 1445 1446 try { 1447 // context start < 0 1448 p.getOffsetForAdvance(string, -1, string.length(), 0, string.length(), false, 0.0f); 1449 fail("Should throw an IndexOutOfBoundsException."); 1450 } catch (IndexOutOfBoundsException e) { 1451 } catch (Exception e) { 1452 fail("Should throw an IndexOutOfBoundsException."); 1453 } 1454 1455 try { 1456 // start < context start 1457 p.getOffsetForAdvance(string, 0, string.length(), 1, string.length(), false, 0.0f); 1458 fail("Should throw an IndexOutOfBoundsException."); 1459 } catch (IndexOutOfBoundsException e) { 1460 } catch (Exception e) { 1461 fail("Should throw an IndexOutOfBoundsException."); 1462 } 1463 1464 try { 1465 // end < start 1466 p.getOffsetForAdvance(string, 1, 0, 0, 0, false, 0); 1467 fail("Should throw an IndexOutOfBoundsException."); 1468 } catch (IndexOutOfBoundsException e) { 1469 } catch (Exception e) { 1470 fail("Should throw an IndexOutOfBoundsException."); 1471 } 1472 1473 try { 1474 // context end < end 1475 p.getOffsetForAdvance(string, 0, string.length(), 0, string.length() - 1, false, 0.0f); 1476 fail("Should throw an IndexOutOfBoundsException."); 1477 } catch (IndexOutOfBoundsException e) { 1478 } catch (Exception e) { 1479 fail("Should throw an IndexOutOfBoundsException."); 1480 } 1481 1482 try { 1483 // text length < context end 1484 p.getOffsetForAdvance(string, 0, string.length(), 0, string.length() + 1, false, 0.0f); 1485 fail("Should throw an IndexOutOfBoundsException."); 1486 } catch (IndexOutOfBoundsException e) { 1487 } catch (Exception e) { 1488 fail("Should throw an IndexOutOfBoundsException."); 1489 } 1490 } 1491 1492 public void testGetOffsetForAdvance_grahpemeCluster() { 1493 Paint p = new Paint(); 1494 { 1495 String string = "\uD83C\uDF37"; // U+1F337: TULIP 1496 { 1497 final float widthToOffset = p.getRunAdvance(string, 0, 1498 string.length(), 0, string.length(), false, 1); 1499 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1500 string.length(), false, widthToOffset); 1501 assertFalse(1 == offset); 1502 assertTrue(0 == offset || string.length() == offset); 1503 } 1504 } 1505 { 1506 String string = "\uD83C\uDDFA\uD83C\uDDF8"; // US flag 1507 { 1508 final float widthToOffset = p.getRunAdvance(string, 0, 1509 string.length(), 0, string.length(), false, 2); 1510 final int offset = p.getOffsetForAdvance(string, 0, string.length(), 0, 1511 string.length(), false, widthToOffset); 1512 assertFalse(2 == offset); 1513 assertTrue(0 == offset || string.length() == offset); 1514 } 1515 { 1516 final float widthToOffset = p.getRunAdvance(string, 0, 2, 0, 2, false, 2); 1517 final int offset = p.getOffsetForAdvance(string, 0, 2, 1518 0, 2, false, widthToOffset); 1519 assertEquals(2, offset); 1520 } 1521 } 1522 { 1523 // HANGUL CHOSEONG KIYEOK, HANGUL JUNGSEONG A, HANDUL JONGSEONG KIYEOK 1524 String string = "\u1100\u1161\u11A8"; 1525 { 1526 for (int offset = 0; offset <= string.length(); ++offset) { 1527 final float widthToOffset = p.getRunAdvance(string, 0, 1528 string.length(), 0, string.length(), false, offset); 1529 final int offsetForAdvance = p.getOffsetForAdvance(string, 0, string.length(), 1530 0, string.length(), false, widthToOffset); 1531 assertTrue(0 == offsetForAdvance || string.length() == offsetForAdvance); 1532 } 1533 for (int offset = 0; offset <= string.length(); ++offset) { 1534 final float widthToOffset = p.getRunAdvance(string, 0, offset, 0, offset, 1535 false, offset); 1536 final int offsetForAdvance = p.getOffsetForAdvance(string, 0, string.length(), 1537 0, string.length(), false, widthToOffset); 1538 assertTrue(0 == offsetForAdvance || string.length() == offsetForAdvance); 1539 } 1540 for (int offset = 0; offset <= string.length(); ++offset) { 1541 final float widthToOffset = p.getRunAdvance(string, 0, offset, 0, offset, 1542 false, offset); 1543 final int offsetForAdvance = p.getOffsetForAdvance(string, 0, offset, 0, 1544 offset, false, widthToOffset); 1545 assertEquals(offset, offsetForAdvance); 1546 } 1547 } 1548 } 1549 } 1550 } 1551