Home | History | Annotate | Download | only in cts
      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.assertTrue;
     23 
     24 import android.graphics.Bitmap;
     25 import android.graphics.Canvas;
     26 import android.graphics.Color;
     27 import android.graphics.Matrix;
     28 import android.graphics.Paint;
     29 import android.graphics.Path;
     30 import android.graphics.RectF;
     31 
     32 import androidx.test.filters.SmallTest;
     33 import androidx.test.runner.AndroidJUnit4;
     34 
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 
     38 @SmallTest
     39 @RunWith(AndroidJUnit4.class)
     40 public class PathTest {
     41 
     42     // Test constants
     43     private static final float LEFT = 10.0f;
     44     private static final float RIGHT = 50.0f;
     45     private static final float TOP = 10.0f;
     46     private static final float BOTTOM = 50.0f;
     47     private static final float XCOORD = 40.0f;
     48     private static final float YCOORD = 40.0f;
     49 
     50     @Test
     51     public void testConstructor() {
     52         // new the Path instance
     53         new Path();
     54 
     55         // another the Path instance with different params
     56         new Path(new Path());
     57     }
     58 
     59     @Test
     60     public void testAddRect1() {
     61         Path path = new Path();
     62         assertTrue(path.isEmpty());
     63         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
     64         path.addRect(rect, Path.Direction.CW);
     65         assertFalse(path.isEmpty());
     66     }
     67 
     68     @Test
     69     public void testAddRect2() {
     70         Path path = new Path();
     71         assertTrue(path.isEmpty());
     72         path.addRect(LEFT, TOP, RIGHT, BOTTOM, Path.Direction.CW);
     73         assertFalse(path.isEmpty());
     74     }
     75 
     76     @Test
     77     public void testMoveTo() {
     78         Path path = new Path();
     79         path.moveTo(10.0f, 10.0f);
     80     }
     81 
     82     @Test
     83     public void testSet() {
     84         Path path = new Path();
     85         assertTrue(path.isEmpty());
     86         Path path1 = new Path();
     87         addRectToPath(path1);
     88         path.set(path1);
     89         verifyPathsAreEquivalent(path, path1);
     90     }
     91 
     92     @Test
     93     public void testSetCleanOld() {
     94         Path path = new Path();
     95         addRectToPath(path);
     96         path.addRect(new RectF(0, 0, 10, 10), Path.Direction.CW);
     97         Path path1 = new Path();
     98         path1.addRect(new RectF(10, 10, 20, 20), Path.Direction.CW);
     99         path.set(path1);
    100         verifyPathsAreEquivalent(path, path1);
    101     }
    102 
    103     @Test
    104     public void testSetEmptyPath() {
    105         Path path = new Path();
    106         addRectToPath(path);
    107         Path path1 = new Path();
    108         path.set(path1);
    109         verifyPathsAreEquivalent(path, path1);
    110     }
    111 
    112     @Test
    113     public void testAccessFillType() {
    114         // set the expected value
    115         Path.FillType expected1 = Path.FillType.EVEN_ODD;
    116         Path.FillType expected2 = Path.FillType.INVERSE_EVEN_ODD;
    117         Path.FillType expected3 = Path.FillType.INVERSE_WINDING;
    118         Path.FillType expected4 = Path.FillType.WINDING;
    119 
    120         // new the Path instance
    121         Path path = new Path();
    122         // set FillType by {@link Path#setFillType(FillType)}
    123         path.setFillType(Path.FillType.EVEN_ODD);
    124         assertEquals(expected1, path.getFillType());
    125         path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
    126         assertEquals(expected2, path.getFillType());
    127         path.setFillType(Path.FillType.INVERSE_WINDING);
    128         assertEquals(expected3, path.getFillType());
    129         path.setFillType(Path.FillType.WINDING);
    130         assertEquals(expected4, path.getFillType());
    131     }
    132 
    133     @Test
    134     public void testRQuadTo() {
    135         Path path = new Path();
    136         assertTrue(path.isEmpty());
    137         path.rQuadTo(5.0f, 5.0f, 10.0f, 10.0f);
    138         assertFalse(path.isEmpty());
    139     }
    140 
    141     @Test
    142     public void testTransform1() {
    143         Path path = new Path();
    144         assertTrue(path.isEmpty());
    145         Path dst = new Path();
    146         addRectToPath(path);
    147         path.transform(new Matrix(), dst);
    148         assertFalse(dst.isEmpty());
    149     }
    150 
    151     @Test
    152     public void testLineTo() {
    153         Path path = new Path();
    154         assertTrue(path.isEmpty());
    155         path.lineTo(XCOORD, YCOORD);
    156         assertFalse(path.isEmpty());
    157     }
    158 
    159     @Test
    160     public void testClose() {
    161         Path path = new Path();
    162         assertTrue(path.isEmpty());
    163         addRectToPath(path);
    164         path.close();
    165     }
    166 
    167     @Test
    168     public void testQuadTo() {
    169         Path path = new Path();
    170         assertTrue(path.isEmpty());
    171         path.quadTo(20.0f, 20.0f, 40.0f, 40.0f);
    172         assertFalse(path.isEmpty());
    173     }
    174 
    175     @Test
    176     public void testAddCircle() {
    177         // new the Path instance
    178         Path path = new Path();
    179         assertTrue(path.isEmpty());
    180         path.addCircle(XCOORD, YCOORD, 10.0f, Path.Direction.CW);
    181         assertFalse(path.isEmpty());
    182     }
    183 
    184     @Test
    185     public void testArcTo1() {
    186         Path path = new Path();
    187         assertTrue(path.isEmpty());
    188         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    189         path.arcTo(oval, 0.0f, 30.0f, true);
    190         assertFalse(path.isEmpty());
    191     }
    192 
    193     @Test
    194     public void testArcTo2() {
    195         Path path = new Path();
    196         assertTrue(path.isEmpty());
    197         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    198         path.arcTo(oval, 0.0f, 30.0f);
    199         assertFalse(path.isEmpty());
    200     }
    201 
    202     @Test
    203     public void testComputeBounds1() {
    204         RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f);
    205         Path path = new Path();
    206         assertTrue(path.isEmpty());
    207         RectF bounds = new RectF();
    208         path.computeBounds(bounds, true);
    209         assertEquals(expected.width(), bounds.width(), 0.0f);
    210         assertEquals(expected.height(), bounds.height(), 0.0f);
    211         path.computeBounds(bounds, false);
    212         assertEquals(expected.width(), bounds.width(), 0.0f);
    213         assertEquals(expected.height(), bounds.height(), 0.0f);
    214     }
    215 
    216     @Test
    217     public void testComputeBounds2() {
    218         RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    219         Path path = new Path();
    220         assertTrue(path.isEmpty());
    221         RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    222         path.addRect(bounds, Path.Direction.CW);
    223         path.computeBounds(bounds, true);
    224         assertEquals(expected.width(), bounds.width(), 0.0f);
    225         assertEquals(expected.height(), bounds.height(), 0.0f);
    226         path.computeBounds(bounds, false);
    227         assertEquals(expected.width(), bounds.width(), 0.0f);
    228         assertEquals(expected.height(), bounds.height(), 0.0f);
    229     }
    230 
    231     @Test
    232     public void testSetLastPoint() {
    233         Path path = new Path();
    234         path.setLastPoint(10.0f, 10.0f);
    235     }
    236 
    237     @Test
    238     public void testRLineTo() {
    239         Path path = new Path();
    240         assertTrue(path.isEmpty());
    241         path.rLineTo(10.0f, 10.0f);
    242         assertFalse(path.isEmpty());
    243     }
    244 
    245     @Test
    246     public void testIsEmpty() {
    247 
    248         Path path = new Path();
    249         assertTrue(path.isEmpty());
    250         addRectToPath(path);
    251         assertFalse(path.isEmpty());
    252     }
    253 
    254     @Test
    255     public void testRewind() {
    256         Path.FillType expected = Path.FillType.EVEN_ODD;
    257 
    258         Path path = new Path();
    259         assertTrue(path.isEmpty());
    260         addRectToPath(path);
    261         path.rewind();
    262         path.setFillType(Path.FillType.EVEN_ODD);
    263         assertTrue(path.isEmpty());
    264         assertEquals(expected, path.getFillType());
    265     }
    266 
    267     @Test
    268     public void testAddOval() {
    269         Path path = new Path();
    270         assertTrue(path.isEmpty());
    271         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    272         path.addOval(oval, Path.Direction.CW);
    273         assertFalse(path.isEmpty());
    274     }
    275 
    276     @Test
    277     public void testIsRect() {
    278         Path path = new Path();
    279         assertTrue(path.isEmpty());
    280         addRectToPath(path);
    281     }
    282 
    283     @Test
    284     public void testAddPath1() {
    285         Path path = new Path();
    286         assertTrue(path.isEmpty());
    287         Path src = new Path();
    288         addRectToPath(src);
    289         path.addPath(src, 10.0f, 10.0f);
    290         assertFalse(path.isEmpty());
    291     }
    292 
    293     @Test
    294     public void testAddPath2() {
    295         Path path = new Path();
    296         assertTrue(path.isEmpty());
    297         Path src = new Path();
    298         addRectToPath(src);
    299         path.addPath(src);
    300         assertFalse(path.isEmpty());
    301     }
    302 
    303     @Test
    304     public void testAddPath3() {
    305         Path path = new Path();
    306         assertTrue(path.isEmpty());
    307         Path src = new Path();
    308         addRectToPath(src);
    309         Matrix matrix = new Matrix();
    310         path.addPath(src, matrix);
    311         assertFalse(path.isEmpty());
    312     }
    313 
    314     @Test
    315     public void testAddRoundRect1() {
    316         Path path = new Path();
    317         assertTrue(path.isEmpty());
    318         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    319         path.addRoundRect(rect, XCOORD, YCOORD, Path.Direction.CW);
    320         assertFalse(path.isEmpty());
    321     }
    322 
    323     @Test
    324     public void testAddRoundRect2() {
    325         Path path = new Path();
    326         assertTrue(path.isEmpty());
    327         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    328         float[] radii = new float[8];
    329         for (int i = 0; i < 8; i++) {
    330             radii[i] = 10.0f + i * 5.0f;
    331         }
    332         path.addRoundRect(rect, radii, Path.Direction.CW);
    333         assertFalse(path.isEmpty());
    334     }
    335 
    336     @Test
    337     public void testIsConvex1() {
    338         Path path = new Path();
    339         path.addRect(0, 0, 100, 10, Path.Direction.CW);
    340         assertTrue(path.isConvex());
    341 
    342         path.addRect(0, 0, 10, 100, Path.Direction.CW);
    343         assertFalse(path.isConvex()); // path is concave
    344     }
    345 
    346     @Test
    347     public void testIsConvex2() {
    348         Path path = new Path();
    349         path.addRect(0, 0, 40, 40, Path.Direction.CW);
    350         assertTrue(path.isConvex());
    351 
    352         path.addRect(10, 10, 30, 30, Path.Direction.CCW);
    353         assertFalse(path.isConvex()); // path has hole, isn't convex
    354     }
    355 
    356     @Test
    357     public void testIsConvex3() {
    358         Path path = new Path();
    359         path.addRect(0, 0, 10, 10, Path.Direction.CW);
    360         assertTrue(path.isConvex());
    361 
    362         path.addRect(0, 20, 10, 10, Path.Direction.CW);
    363         assertFalse(path.isConvex()); // path isn't one convex shape
    364     }
    365 
    366     @Test
    367     public void testIsInverseFillType() {
    368         Path path = new Path();
    369         assertFalse(path.isInverseFillType());
    370         path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
    371         assertTrue(path.isInverseFillType());
    372     }
    373 
    374     @Test
    375     public void testOffset1() {
    376         Path path = new Path();
    377         assertTrue(path.isEmpty());
    378         addRectToPath(path);
    379         Path dst = new Path();
    380         path.offset(XCOORD, YCOORD, dst);
    381         assertFalse(dst.isEmpty());
    382     }
    383 
    384     @Test
    385     public void testCubicTo() {
    386         Path path = new Path();
    387         assertTrue(path.isEmpty());
    388         path.cubicTo(10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f);
    389         assertFalse(path.isEmpty());
    390     }
    391 
    392     @Test
    393     public void testReset() {
    394         Path path = new Path();
    395         assertTrue(path.isEmpty());
    396         Path path1 = new Path();
    397         addRectToPath(path1);
    398         path.set(path1);
    399         assertFalse(path.isEmpty());
    400         path.reset();
    401         assertTrue(path.isEmpty());
    402     }
    403 
    404     @Test
    405     public void testToggleInverseFillType() {
    406         Path path = new Path();
    407         assertTrue(path.isEmpty());
    408         path.toggleInverseFillType();
    409         assertTrue(path.isInverseFillType());
    410     }
    411 
    412     @Test
    413     public void testAddArc() {
    414         Path path = new Path();
    415         assertTrue(path.isEmpty());
    416         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    417         path.addArc(oval, 0.0f, 30.0f);
    418         assertFalse(path.isEmpty());
    419     }
    420 
    421     @Test
    422     public void testRCubicTo() {
    423         Path path = new Path();
    424         assertTrue(path.isEmpty());
    425         path.rCubicTo(10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f);
    426         assertFalse(path.isEmpty());
    427     }
    428 
    429     @Test
    430     public void testOffsetTextPath() {
    431         Paint paint = new Paint();
    432         Path path = new Path();
    433         paint.setTextSize(20);
    434         String text = "abc";
    435         paint.getTextPath(text, 0, text.length() - 1, 0, 0, path);
    436         RectF expectedRect = new RectF();
    437         path.computeBounds(expectedRect, false);
    438         assertFalse(expectedRect.isEmpty());
    439         int offset = 10;
    440         expectedRect.offset(offset, offset);
    441 
    442         path.offset(offset, offset);
    443         RectF offsettedRect = new RectF();
    444         path.computeBounds(offsettedRect, false);
    445         assertEquals(expectedRect, offsettedRect);
    446     }
    447 
    448     @Test(expected=IllegalArgumentException.class)
    449     public void testApproximate_lowError() {
    450         new Path().approximate(-0.1f);
    451     }
    452 
    453     @Test
    454     public void testApproximate_rect_cw() {
    455         Path path = new Path();
    456         path.addRect(0, 0, 100, 100, Path.Direction.CW);
    457         assertArrayEquals(new float[] {
    458                 0, 0, 0,
    459                 0.25f, 100, 0,
    460                 0.50f, 100, 100,
    461                 0.75f, 0, 100,
    462                 1, 0, 0,
    463         }, path.approximate(1f), 0);
    464     }
    465 
    466     @Test
    467     public void testApproximate_rect_ccw() {
    468         Path path = new Path();
    469         path.addRect(0, 0, 100, 100, Path.Direction.CCW);
    470         assertArrayEquals(new float[] {
    471                 0, 0, 0,
    472                 0.25f, 0, 100,
    473                 0.50f, 100, 100,
    474                 0.75f, 100, 0,
    475                 1, 0, 0,
    476         }, path.approximate(1f), 0);
    477     }
    478 
    479     @Test
    480     public void testApproximate_empty() {
    481         Path path = new Path();
    482         assertArrayEquals(new float[] {
    483                 0, 0, 0,
    484                 1, 0, 0,
    485         }, path.approximate(0.5f), 0);
    486     }
    487 
    488     @Test
    489     public void testApproximate_circle() {
    490         Path path = new Path();
    491         path.addCircle(0, 0, 50, Path.Direction.CW);
    492         assertTrue(path.approximate(0.25f).length > 20);
    493     }
    494 
    495     /** This test just ensures the process doesn't crash. The actual output is not interesting
    496      *  hence the lack of asserts, as the only behavior that's being asserted is that it
    497      *  doesn't crash.
    498      */
    499     @Test
    500     public void testUseAfterFinalize() throws Throwable {
    501         PathAbuser pathAbuser = new PathAbuser();
    502 
    503         // Basic test that we created a path successfully
    504         assertTrue(pathAbuser.isEmpty());
    505         addRectToPath(pathAbuser);
    506         assertTrue(pathAbuser.isRect(null));
    507         assertFalse(pathAbuser.isEmpty());
    508 
    509         // Now use-after-finalize.
    510         pathAbuser.destroy();
    511         pathAbuser.isEmpty();
    512         pathAbuser.isRect(null);
    513         pathAbuser.destroy();
    514         pathAbuser.isEmpty();
    515         pathAbuser.isRect(null);
    516         pathAbuser.destroy();
    517     }
    518 
    519     private static final class PathAbuser extends Path {
    520         public void destroy() throws Throwable {
    521             finalize();
    522         }
    523     }
    524 
    525     private static void verifyPathsAreEquivalent(Path actual, Path expected) {
    526         Bitmap actualBitmap = drawAndGetBitmap(actual);
    527         Bitmap expectedBitmap = drawAndGetBitmap(expected);
    528         assertTrue(actualBitmap.sameAs(expectedBitmap));
    529     }
    530 
    531     private static final int WIDTH = 100;
    532     private static final int HEIGHT = 100;
    533 
    534     private static Bitmap drawAndGetBitmap(Path path) {
    535         Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888);
    536         bitmap.eraseColor(Color.BLACK);
    537         Paint paint = new Paint();
    538         paint.setColor(Color.RED);
    539         Canvas canvas = new Canvas(bitmap);
    540         canvas.drawPath(path, paint);
    541         return bitmap;
    542     }
    543 
    544     private void addRectToPath(Path path) {
    545         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
    546         path.addRect(rect, Path.Direction.CW);
    547     }
    548 }
    549