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 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotEquals; 23 import static org.junit.Assert.assertTrue; 24 25 import android.graphics.Bitmap; 26 import android.graphics.Canvas; 27 import android.graphics.Color; 28 import android.graphics.Matrix; 29 import android.graphics.Paint; 30 import android.graphics.Path; 31 import android.graphics.Path.Direction; 32 import android.graphics.PathIterator; 33 import android.graphics.RectF; 34 import android.platform.test.annotations.DisabledOnRavenwood; 35 import android.platform.test.ravenwood.RavenwoodRule; 36 37 import androidx.test.filters.SmallTest; 38 import androidx.test.runner.AndroidJUnit4; 39 40 import com.android.compatibility.common.util.ApiTest; 41 42 import org.junit.Rule; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 46 @SmallTest 47 @RunWith(AndroidJUnit4.class) 48 public class PathTest { 49 @Rule 50 public final RavenwoodRule mRavenwood = new RavenwoodRule(); 51 52 // Test constants 53 private static final float LEFT = 10.0f; 54 private static final float RIGHT = 50.0f; 55 private static final float TOP = 10.0f; 56 private static final float BOTTOM = 50.0f; 57 private static final float XCOORD = 40.0f; 58 private static final float YCOORD = 40.0f; 59 private static final int SQUARE = 10; 60 private static final int WIDTH = 100; 61 private static final int HEIGHT = 100; 62 private static final int START_X = 10; 63 private static final int START_Y = 20; 64 private static final int OFFSET_X = 30; 65 private static final int OFFSET_Y = 40; 66 67 @Test testConstructor()68 public void testConstructor() { 69 // new the Path instance 70 new Path(); 71 72 // another the Path instance with different params 73 new Path(new Path()); 74 } 75 76 @Test testAddRect1()77 public void testAddRect1() { 78 Path path = new Path(); 79 assertTrue(path.isEmpty()); 80 RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM); 81 path.addRect(rect, Path.Direction.CW); 82 assertFalse(path.isEmpty()); 83 } 84 85 @Test testAddRect2()86 public void testAddRect2() { 87 Path path = new Path(); 88 assertTrue(path.isEmpty()); 89 path.addRect(LEFT, TOP, RIGHT, BOTTOM, Path.Direction.CW); 90 assertFalse(path.isEmpty()); 91 } 92 93 @Test testMoveTo()94 public void testMoveTo() { 95 Path path = new Path(); 96 path.moveTo(10.0f, 10.0f); 97 } 98 99 @Test 100 @DisabledOnRavenwood(blockedBy = {Paint.class}) testSet()101 public void testSet() { 102 Path path = new Path(); 103 assertTrue(path.isEmpty()); 104 Path path1 = new Path(); 105 addRectToPath(path1); 106 path.set(path1); 107 verifyPathsAreEquivalent(path, path1); 108 } 109 110 @Test 111 @DisabledOnRavenwood(blockedBy = {Paint.class}) testSetCleanOld()112 public void testSetCleanOld() { 113 Path path = new Path(); 114 addRectToPath(path); 115 path.addRect(new RectF(0, 0, 10, 10), Path.Direction.CW); 116 Path path1 = new Path(); 117 path1.addRect(new RectF(10, 10, 20, 20), Path.Direction.CW); 118 path.set(path1); 119 verifyPathsAreEquivalent(path, path1); 120 } 121 122 @Test 123 @DisabledOnRavenwood(blockedBy = {Paint.class}) testSetEmptyPath()124 public void testSetEmptyPath() { 125 Path path = new Path(); 126 addRectToPath(path); 127 Path path1 = new Path(); 128 path.set(path1); 129 verifyPathsAreEquivalent(path, path1); 130 } 131 132 @Test testAccessFillType()133 public void testAccessFillType() { 134 // set the expected value 135 Path.FillType expected1 = Path.FillType.EVEN_ODD; 136 Path.FillType expected2 = Path.FillType.INVERSE_EVEN_ODD; 137 Path.FillType expected3 = Path.FillType.INVERSE_WINDING; 138 Path.FillType expected4 = Path.FillType.WINDING; 139 140 // new the Path instance 141 Path path = new Path(); 142 // set FillType by {@link Path#setFillType(FillType)} 143 path.setFillType(Path.FillType.EVEN_ODD); 144 assertEquals(expected1, path.getFillType()); 145 path.setFillType(Path.FillType.INVERSE_EVEN_ODD); 146 assertEquals(expected2, path.getFillType()); 147 path.setFillType(Path.FillType.INVERSE_WINDING); 148 assertEquals(expected3, path.getFillType()); 149 path.setFillType(Path.FillType.WINDING); 150 assertEquals(expected4, path.getFillType()); 151 } 152 153 @Test testRQuadTo()154 public void testRQuadTo() { 155 Path path = new Path(); 156 assertTrue(path.isEmpty()); 157 path.rQuadTo(5.0f, 5.0f, 10.0f, 10.0f); 158 assertFalse(path.isEmpty()); 159 } 160 161 @Test testTransform1()162 public void testTransform1() { 163 Path path = new Path(); 164 assertTrue(path.isEmpty()); 165 Path dst = new Path(); 166 addRectToPath(path); 167 path.transform(new Matrix(), dst); 168 assertFalse(dst.isEmpty()); 169 } 170 171 @Test testLineTo()172 public void testLineTo() { 173 Path path = new Path(); 174 assertTrue(path.isEmpty()); 175 path.lineTo(XCOORD, YCOORD); 176 assertFalse(path.isEmpty()); 177 } 178 179 @Test testClose()180 public void testClose() { 181 Path path = new Path(); 182 assertTrue(path.isEmpty()); 183 addRectToPath(path); 184 path.close(); 185 } 186 187 @Test testQuadTo()188 public void testQuadTo() { 189 Path path = new Path(); 190 assertTrue(path.isEmpty()); 191 path.quadTo(20.0f, 20.0f, 40.0f, 40.0f); 192 assertFalse(path.isEmpty()); 193 } 194 195 @Test testAddCircle()196 public void testAddCircle() { 197 // new the Path instance 198 Path path = new Path(); 199 assertTrue(path.isEmpty()); 200 path.addCircle(XCOORD, YCOORD, 10.0f, Path.Direction.CW); 201 assertFalse(path.isEmpty()); 202 } 203 204 @Test testArcTo1()205 public void testArcTo1() { 206 Path path = new Path(); 207 assertTrue(path.isEmpty()); 208 RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM); 209 path.arcTo(oval, 0.0f, 30.0f, true); 210 assertFalse(path.isEmpty()); 211 } 212 213 @Test testArcTo2()214 public void testArcTo2() { 215 Path path = new Path(); 216 assertTrue(path.isEmpty()); 217 RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM); 218 path.arcTo(oval, 0.0f, 30.0f); 219 assertFalse(path.isEmpty()); 220 } 221 222 @Test testDeprecatedComputeBounds1()223 public void testDeprecatedComputeBounds1() { 224 RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f); 225 Path path = new Path(); 226 assertTrue(path.isEmpty()); 227 RectF bounds = new RectF(); 228 path.computeBounds(bounds, true); 229 assertEquals(expected.width(), bounds.width(), 0.0f); 230 assertEquals(expected.height(), bounds.height(), 0.0f); 231 path.computeBounds(bounds, false); 232 assertEquals(expected.width(), bounds.width(), 0.0f); 233 assertEquals(expected.height(), bounds.height(), 0.0f); 234 } 235 236 @Test testDeprecatedComputeBounds2()237 public void testDeprecatedComputeBounds2() { 238 RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM); 239 Path path = new Path(); 240 assertTrue(path.isEmpty()); 241 RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM); 242 path.addRect(bounds, Path.Direction.CW); 243 path.computeBounds(bounds, true); 244 assertEquals(expected.width(), bounds.width(), 0.0f); 245 assertEquals(expected.height(), bounds.height(), 0.0f); 246 path.computeBounds(bounds, false); 247 assertEquals(expected.width(), bounds.width(), 0.0f); 248 assertEquals(expected.height(), bounds.height(), 0.0f); 249 } 250 251 @Test testComputeBounds1()252 public void testComputeBounds1() { 253 RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f); 254 Path path = new Path(); 255 assertTrue(path.isEmpty()); 256 RectF bounds = new RectF(); 257 path.computeBounds(bounds); 258 assertEquals(expected.width(), bounds.width(), 0.0f); 259 assertEquals(expected.height(), bounds.height(), 0.0f); 260 path.computeBounds(bounds); 261 assertEquals(expected.width(), bounds.width(), 0.0f); 262 assertEquals(expected.height(), bounds.height(), 0.0f); 263 } 264 265 @Test testComputeBounds2()266 public void testComputeBounds2() { 267 RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM); 268 Path path = new Path(); 269 assertTrue(path.isEmpty()); 270 RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM); 271 path.addRect(bounds, Path.Direction.CW); 272 path.computeBounds(bounds); 273 assertEquals(expected.width(), bounds.width(), 0.0f); 274 assertEquals(expected.height(), bounds.height(), 0.0f); 275 path.computeBounds(bounds); 276 assertEquals(expected.width(), bounds.width(), 0.0f); 277 assertEquals(expected.height(), bounds.height(), 0.0f); 278 } 279 280 @Test testSetLastPoint()281 public void testSetLastPoint() { 282 Path path = new Path(); 283 path.setLastPoint(10.0f, 10.0f); 284 } 285 286 @Test testRLineTo()287 public void testRLineTo() { 288 Path path = new Path(); 289 assertTrue(path.isEmpty()); 290 path.rLineTo(10.0f, 10.0f); 291 assertFalse(path.isEmpty()); 292 } 293 294 @Test testIsEmpty()295 public void testIsEmpty() { 296 297 Path path = new Path(); 298 assertTrue(path.isEmpty()); 299 addRectToPath(path); 300 assertFalse(path.isEmpty()); 301 } 302 303 @Test testRewind()304 public void testRewind() { 305 Path.FillType expected = Path.FillType.EVEN_ODD; 306 307 Path path = new Path(); 308 assertTrue(path.isEmpty()); 309 addRectToPath(path); 310 path.rewind(); 311 path.setFillType(Path.FillType.EVEN_ODD); 312 assertTrue(path.isEmpty()); 313 assertEquals(expected, path.getFillType()); 314 } 315 316 @Test testAddOval()317 public void testAddOval() { 318 Path path = new Path(); 319 assertTrue(path.isEmpty()); 320 RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM); 321 path.addOval(oval, Path.Direction.CW); 322 assertFalse(path.isEmpty()); 323 } 324 325 @Test testIsRect()326 public void testIsRect() { 327 Path path = new Path(); 328 assertTrue(path.isEmpty()); 329 addRectToPath(path); 330 } 331 332 @Test testAddPath1()333 public void testAddPath1() { 334 Path path = new Path(); 335 assertTrue(path.isEmpty()); 336 Path src = new Path(); 337 addRectToPath(src); 338 path.addPath(src, 10.0f, 10.0f); 339 assertFalse(path.isEmpty()); 340 } 341 342 @Test testAddPath2()343 public void testAddPath2() { 344 Path path = new Path(); 345 assertTrue(path.isEmpty()); 346 Path src = new Path(); 347 addRectToPath(src); 348 path.addPath(src); 349 assertFalse(path.isEmpty()); 350 } 351 352 @Test testAddPath3()353 public void testAddPath3() { 354 Path path = new Path(); 355 assertTrue(path.isEmpty()); 356 Path src = new Path(); 357 addRectToPath(src); 358 Matrix matrix = new Matrix(); 359 path.addPath(src, matrix); 360 assertFalse(path.isEmpty()); 361 } 362 363 @Test testAddRoundRect1()364 public void testAddRoundRect1() { 365 Path path = new Path(); 366 assertTrue(path.isEmpty()); 367 RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM); 368 path.addRoundRect(rect, XCOORD, YCOORD, Path.Direction.CW); 369 assertFalse(path.isEmpty()); 370 } 371 372 @Test testAddRoundRect2()373 public void testAddRoundRect2() { 374 Path path = new Path(); 375 assertTrue(path.isEmpty()); 376 RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM); 377 float[] radii = new float[8]; 378 for (int i = 0; i < 8; i++) { 379 radii[i] = 10.0f + i * 5.0f; 380 } 381 path.addRoundRect(rect, radii, Path.Direction.CW); 382 assertFalse(path.isEmpty()); 383 } 384 385 @Test testIsConvex1()386 public void testIsConvex1() { 387 Path path = new Path(); 388 path.addRect(0, 0, 100, 10, Path.Direction.CW); 389 assertTrue(path.isConvex()); 390 391 path.addRect(0, 0, 10, 100, Path.Direction.CW); 392 assertFalse(path.isConvex()); // path is concave 393 } 394 395 @Test testIsConvex2()396 public void testIsConvex2() { 397 Path path = new Path(); 398 path.addRect(0, 0, 40, 40, Path.Direction.CW); 399 assertTrue(path.isConvex()); 400 401 path.addRect(10, 10, 30, 30, Path.Direction.CCW); 402 assertFalse(path.isConvex()); // path has hole, isn't convex 403 } 404 405 @Test testIsConvex3()406 public void testIsConvex3() { 407 Path path = new Path(); 408 path.addRect(0, 0, 10, 10, Path.Direction.CW); 409 assertTrue(path.isConvex()); 410 411 path.addRect(0, 20, 10, 10, Path.Direction.CW); 412 assertFalse(path.isConvex()); // path isn't one convex shape 413 } 414 415 @Test testIsInverseFillType()416 public void testIsInverseFillType() { 417 Path path = new Path(); 418 assertFalse(path.isInverseFillType()); 419 path.setFillType(Path.FillType.INVERSE_EVEN_ODD); 420 assertTrue(path.isInverseFillType()); 421 } 422 423 @Test testOffset1()424 public void testOffset1() { 425 Path path = new Path(); 426 assertTrue(path.isEmpty()); 427 addRectToPath(path); 428 Path dst = new Path(); 429 path.offset(XCOORD, YCOORD, dst); 430 assertFalse(dst.isEmpty()); 431 } 432 433 @Test testCubicTo()434 public void testCubicTo() { 435 Path path = new Path(); 436 assertTrue(path.isEmpty()); 437 path.cubicTo(10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f); 438 assertFalse(path.isEmpty()); 439 } 440 441 @Test 442 @ApiTest(apis = {"android.graphics.Path#getPathIterator", "android.graphics.PathIterator#next", 443 "android.graphics.PathIterator.Segment#getVerb", 444 "android.graphics.PathIterator.Segment#getPoints", 445 "android.graphics.PathIterator.Segment#getConicWeight", 446 "android.graphics.Path#isEmpty", "android.graphics.Path#conicTo"}) 447 @DisabledOnRavenwood(blockedBy = {PathIterator.class}) testConicTo()448 public void testConicTo() { 449 Path path = new Path(); 450 assertTrue(path.isEmpty()); 451 path.conicTo(10.0f, 10.0f, 20.0f, 20.0f, 2f); 452 assertFalse(path.isEmpty()); 453 int verbIndex = 0; 454 for (PathIterator it = path.getPathIterator(); it.hasNext(); ) { 455 PathIterator.Segment segment = it.next(); 456 int verb = segment.getVerb(); 457 float[] points = segment.getPoints(); 458 float weight = segment.getConicWeight(); 459 switch (verb) { 460 case PathIterator.VERB_CONIC: 461 assertEquals(0f, points[0], 0f); 462 assertEquals(0f, points[1], 0f); 463 assertEquals(10f, points[2], 0f); 464 assertEquals(10f, points[3], 0f); 465 assertEquals(20f, points[4], 0f); 466 assertEquals(20f, points[5], 0f); 467 assertEquals(2f, weight, 0f); 468 break; 469 default: 470 break; 471 } 472 } 473 } 474 475 @Test testReset()476 public void testReset() { 477 Path path = new Path(); 478 assertTrue(path.isEmpty()); 479 Path path1 = new Path(); 480 addRectToPath(path1); 481 path.set(path1); 482 assertFalse(path.isEmpty()); 483 path.reset(); 484 assertTrue(path.isEmpty()); 485 } 486 487 @Test testResetPreservesFillType()488 public void testResetPreservesFillType() { 489 Path path = new Path(); 490 491 final Path.FillType defaultFillType = path.getFillType(); 492 final Path.FillType fillType = Path.FillType.INVERSE_EVEN_ODD; 493 494 // This test is only meaningful if it changes from the default. 495 assertFalse(fillType.equals(defaultFillType)); 496 497 path.setFillType(fillType); 498 path.reset(); 499 assertEquals(path.getFillType(), fillType); 500 } 501 502 @Test testToggleInverseFillType()503 public void testToggleInverseFillType() { 504 Path path = new Path(); 505 assertTrue(path.isEmpty()); 506 path.toggleInverseFillType(); 507 assertTrue(path.isInverseFillType()); 508 } 509 510 @Test testAddArc()511 public void testAddArc() { 512 Path path = new Path(); 513 assertTrue(path.isEmpty()); 514 RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM); 515 path.addArc(oval, 0.0f, 30.0f); 516 assertFalse(path.isEmpty()); 517 } 518 519 @Test testRCubicTo()520 public void testRCubicTo() { 521 Path path = new Path(); 522 assertTrue(path.isEmpty()); 523 path.rCubicTo(10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f); 524 assertFalse(path.isEmpty()); 525 } 526 527 @Test 528 @ApiTest(apis = {"android.graphics.Path#getPathIterator", "android.graphics.PathIterator#next", 529 "android.graphics.PathIterator.Segment#getVerb", 530 "android.graphics.PathIterator.Segment#getPoints", 531 "android.graphics.PathIterator.Segment#getConicWeight", 532 "android.graphics.Path#isEmpty", "android.graphics.Path#rConicTo"}) 533 @DisabledOnRavenwood(blockedBy = {PathIterator.class}) testRConicTo()534 public void testRConicTo() { 535 Path path = new Path(); 536 assertTrue(path.isEmpty()); 537 path.moveTo(5f, 15f); 538 path.rConicTo(10.0f, 10.0f, 20.0f, 20.0f, 2f); 539 assertFalse(path.isEmpty()); 540 int verbIndex = 0; 541 for (PathIterator it = path.getPathIterator(); it.hasNext(); ) { 542 PathIterator.Segment segment = it.next(); 543 int verb = segment.getVerb(); 544 float[] points = segment.getPoints(); 545 float weight = segment.getConicWeight(); 546 switch (verb) { 547 case PathIterator.VERB_MOVE: 548 assertEquals(5f, points[0], 0f); 549 assertEquals(15f, points[1], 0f); 550 break; 551 case PathIterator.VERB_CONIC: 552 assertEquals(5f, points[0], 0f); 553 assertEquals(15f, points[1], 0f); 554 assertEquals(15f, points[2], 0f); 555 assertEquals(25f, points[3], 0f); 556 assertEquals(25f, points[4], 0f); 557 assertEquals(35f, points[5], 0f); 558 assertEquals(2f, weight, 0f); 559 break; 560 default: 561 break; 562 } 563 } 564 } 565 566 @Test 567 @DisabledOnRavenwood(blockedBy = {Paint.class}) testOffsetTextPath()568 public void testOffsetTextPath() { 569 Paint paint = new Paint(); 570 Path path = new Path(); 571 paint.setTextSize(20); 572 String text = "abc"; 573 paint.getTextPath(text, 0, text.length() - 1, 0, 0, path); 574 RectF expectedRect = new RectF(); 575 path.computeBounds(expectedRect); 576 assertFalse(expectedRect.isEmpty()); 577 int offset = 10; 578 expectedRect.offset(offset, offset); 579 580 path.offset(offset, offset); 581 RectF offsettedRect = new RectF(); 582 path.computeBounds(offsettedRect); 583 assertEquals(expectedRect, offsettedRect); 584 } 585 586 @Test(expected=IllegalArgumentException.class) testApproximate_lowError()587 public void testApproximate_lowError() { 588 new Path().approximate(-0.1f); 589 } 590 591 @Test testApproximate_rect_cw()592 public void testApproximate_rect_cw() { 593 Path path = new Path(); 594 path.addRect(0, 0, 100, 100, Path.Direction.CW); 595 assertArrayEquals(new float[] { 596 0, 0, 0, 597 0.25f, 100, 0, 598 0.50f, 100, 100, 599 0.75f, 0, 100, 600 1, 0, 0, 601 }, path.approximate(1f), 0); 602 } 603 604 @Test testApproximate_rect_ccw()605 public void testApproximate_rect_ccw() { 606 Path path = new Path(); 607 path.addRect(0, 0, 100, 100, Path.Direction.CCW); 608 assertArrayEquals(new float[] { 609 0, 0, 0, 610 0.25f, 0, 100, 611 0.50f, 100, 100, 612 0.75f, 100, 0, 613 1, 0, 0, 614 }, path.approximate(1f), 0); 615 } 616 617 @Test testApproximate_empty()618 public void testApproximate_empty() { 619 Path path = new Path(); 620 assertArrayEquals(new float[] { 621 0, 0, 0, 622 1, 0, 0, 623 }, path.approximate(0.5f), 0); 624 } 625 626 @Test testApproximate_circle()627 public void testApproximate_circle() { 628 Path path = new Path(); 629 path.addCircle(0, 0, 50, Path.Direction.CW); 630 assertTrue(path.approximate(0.25f).length > 20); 631 } 632 633 @Test 634 @DisabledOnRavenwood(blockedBy = {Paint.class}) testPathOffset()635 public void testPathOffset() { 636 Path actualPath = new Path(); 637 actualPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW); 638 actualPath.offset(OFFSET_X, OFFSET_Y); 639 640 Path expectedPath = new Path(); 641 expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE, 642 START_Y + OFFSET_Y + SQUARE, Direction.CW); 643 644 verifyPathsAreEquivalent(actualPath, expectedPath); 645 } 646 647 @Test 648 @DisabledOnRavenwood(blockedBy = {Paint.class}) testPathOffset2()649 public void testPathOffset2() { 650 Path actualPath = new Path(); 651 actualPath.moveTo(0, 0); 652 actualPath.offset(OFFSET_X, OFFSET_Y); 653 actualPath.lineTo(OFFSET_X + 20, OFFSET_Y); 654 655 656 Path expectedPath = new Path(); 657 expectedPath.moveTo(OFFSET_X, OFFSET_Y); 658 expectedPath.lineTo(OFFSET_X + 20, OFFSET_Y); 659 660 Paint paint = new Paint(); 661 paint.setColor(Color.RED); 662 paint.setStyle(Paint.Style.STROKE); 663 verifyPathsAreEquivalent(actualPath, expectedPath, paint); 664 } 665 666 @Test 667 @DisabledOnRavenwood(blockedBy = {Paint.class}) testPathOffsetWithDestination()668 public void testPathOffsetWithDestination() { 669 Path initialPath = new Path(); 670 initialPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW); 671 Path actualPath = new Path(); 672 initialPath.offset(OFFSET_X, OFFSET_Y, actualPath); 673 674 Path expectedPath = new Path(); 675 expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE, 676 START_Y + OFFSET_Y + SQUARE, Direction.CW); 677 678 verifyPathsAreEquivalent(actualPath, expectedPath); 679 } 680 681 /** This test just ensures the process doesn't crash. The actual output is not interesting 682 * hence the lack of asserts, as the only behavior that's being asserted is that it 683 * doesn't crash. 684 */ 685 @Test testUseAfterFinalize()686 public void testUseAfterFinalize() throws Throwable { 687 PathAbuser pathAbuser = new PathAbuser(); 688 689 // Basic test that we created a path successfully 690 assertTrue(pathAbuser.isEmpty()); 691 addRectToPath(pathAbuser); 692 assertTrue(pathAbuser.isRect(null)); 693 assertFalse(pathAbuser.isEmpty()); 694 695 // Now use-after-finalize. 696 pathAbuser.destroy(); 697 pathAbuser.isEmpty(); 698 pathAbuser.isRect(null); 699 pathAbuser.destroy(); 700 pathAbuser.isEmpty(); 701 pathAbuser.isRect(null); 702 pathAbuser.destroy(); 703 } 704 705 @Test 706 @ApiTest(apis = {"android.graphics.Path#moveTo", "android.graphics.Path#lineTo", 707 "android.graphics.Path#quadTo", "android.graphics.Path#conicTo", 708 "android.graphics.Path#cubicTo", "android.graphics.Path#close", 709 "android.graphics.Path#getGenerationId", 710 }) testGenerationId()711 public void testGenerationId() { 712 Path path = new Path(); 713 path.moveTo(1f, 2f); 714 int generationId = path.getGenerationId(); 715 716 path.lineTo(3f, 4f); 717 assertNotEquals(generationId, path.getGenerationId()); 718 generationId = path.getGenerationId(); 719 720 path.moveTo(5f, 6f); 721 assertNotEquals(generationId, path.getGenerationId()); 722 generationId = path.getGenerationId(); 723 724 path.quadTo(7f, 8f, 9f, 10f); 725 assertNotEquals(generationId, path.getGenerationId()); 726 generationId = path.getGenerationId(); 727 728 path.conicTo(11f, 12f, 13f, 14f, 2f); 729 assertNotEquals(generationId, path.getGenerationId()); 730 generationId = path.getGenerationId(); 731 732 path.cubicTo(15f, 16f, 17f, 18f, 19f, 20f); 733 assertNotEquals(generationId, path.getGenerationId()); 734 generationId = path.getGenerationId(); 735 736 path.close(); 737 assertNotEquals(generationId, path.getGenerationId()); 738 } 739 740 @Test 741 @ApiTest(apis = {"android.graphics.Path#moveTo", "android.graphics.Path#lineTo", 742 "android.graphics.PathIterator#next", 743 "android.graphics.Path#isInterpolatable", 744 "android.graphics.Path#interpolate", 745 }) 746 @DisabledOnRavenwood(blockedBy = {Paint.class}) testPathInterpolation()747 public void testPathInterpolation() { 748 Path startPath = new Path(); 749 Path endPath = new Path(); 750 startPath.moveTo(100f, 100f); 751 startPath.lineTo(200f, 300f); 752 endPath.moveTo(200f, 200f); 753 endPath.lineTo(600f, 700f); 754 755 Path interpolatedPath = new Path(); 756 assertTrue(startPath.isInterpolatable(endPath)); 757 758 startPath.interpolate(endPath, .5f, interpolatedPath); 759 PathIterator iterator = interpolatedPath.getPathIterator(); 760 float[] points = new float[8]; 761 int verb = iterator.next(points, 0); 762 assertEquals(PathIterator.VERB_MOVE, verb); 763 assertEquals(150f, points[0], .001f); 764 assertEquals(150f, points[1], .001f); 765 verb = iterator.next(points, 0); 766 assertEquals(PathIterator.VERB_LINE, verb); 767 assertEquals(400f, points[2], .001f); 768 assertEquals(500f, points[3], .001f); 769 } 770 assertPointsEqual(float[] points1, float[] points2, int numToCheck)771 private void assertPointsEqual(float[] points1, float[] points2, int numToCheck) { 772 for (int i = 0; i < numToCheck; ++i) { 773 assertEquals("point " + i + "not equal", points1[i], points2[i], 0f); 774 } 775 } 776 777 private static final class PathAbuser extends Path { destroy()778 public void destroy() throws Throwable { 779 finalize(); 780 } 781 } 782 verifyPathsAreEquivalent(Path actual, Path expected)783 private static void verifyPathsAreEquivalent(Path actual, Path expected) { 784 Paint paint = new Paint(); 785 paint.setColor(Color.RED); 786 verifyPathsAreEquivalent(actual, expected, paint); 787 } 788 verifyPathsAreEquivalent(Path actual, Path expected, Paint paint)789 private static void verifyPathsAreEquivalent(Path actual, Path expected, Paint paint) { 790 Bitmap actualBitmap = drawAndGetBitmap(actual, paint); 791 Bitmap expectedBitmap = drawAndGetBitmap(expected, paint); 792 assertTrue(actualBitmap.sameAs(expectedBitmap)); 793 } 794 drawAndGetBitmap(Path path, Paint paint)795 private static Bitmap drawAndGetBitmap(Path path, Paint paint) { 796 Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888); 797 bitmap.eraseColor(Color.BLACK); 798 Canvas canvas = new Canvas(bitmap); 799 canvas.drawPath(path, paint); 800 return bitmap; 801 } 802 addRectToPath(Path path)803 private static void addRectToPath(Path path) { 804 RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM); 805 path.addRect(rect, Path.Direction.CW); 806 } 807 } 808