blob: 90882c02c2af7900cf645dc1aae342ad65d1bfaf [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.graphics.cts;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PathTest {
// Test constants
private static final float LEFT = 10.0f;
private static final float RIGHT = 50.0f;
private static final float TOP = 10.0f;
private static final float BOTTOM = 50.0f;
private static final float XCOORD = 40.0f;
private static final float YCOORD = 40.0f;
@Test
public void testConstructor() {
// new the Path instance
new Path();
// another the Path instance with different params
new Path(new Path());
}
@Test
public void testAddRect1() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRect(rect, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testAddRect2() {
Path path = new Path();
assertTrue(path.isEmpty());
path.addRect(LEFT, TOP, RIGHT, BOTTOM, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testMoveTo() {
Path path = new Path();
path.moveTo(10.0f, 10.0f);
}
@Test
public void testSet() {
Path path = new Path();
assertTrue(path.isEmpty());
Path path1 = new Path();
addRectToPath(path1);
path.set(path1);
verifyPathsAreEquivalent(path, path1);
}
@Test
public void testSetCleanOld() {
Path path = new Path();
addRectToPath(path);
path.addRect(new RectF(0, 0, 10, 10), Path.Direction.CW);
Path path1 = new Path();
path1.addRect(new RectF(10, 10, 20, 20), Path.Direction.CW);
path.set(path1);
verifyPathsAreEquivalent(path, path1);
}
@Test
public void testSetEmptyPath() {
Path path = new Path();
addRectToPath(path);
Path path1 = new Path();
path.set(path1);
verifyPathsAreEquivalent(path, path1);
}
@Test
public void testAccessFillType() {
// set the expected value
Path.FillType expected1 = Path.FillType.EVEN_ODD;
Path.FillType expected2 = Path.FillType.INVERSE_EVEN_ODD;
Path.FillType expected3 = Path.FillType.INVERSE_WINDING;
Path.FillType expected4 = Path.FillType.WINDING;
// new the Path instance
Path path = new Path();
// set FillType by {@link Path#setFillType(FillType)}
path.setFillType(Path.FillType.EVEN_ODD);
assertEquals(expected1, path.getFillType());
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
assertEquals(expected2, path.getFillType());
path.setFillType(Path.FillType.INVERSE_WINDING);
assertEquals(expected3, path.getFillType());
path.setFillType(Path.FillType.WINDING);
assertEquals(expected4, path.getFillType());
}
@Test
public void testRQuadTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.rQuadTo(5.0f, 5.0f, 10.0f, 10.0f);
assertFalse(path.isEmpty());
}
@Test
public void testTransform1() {
Path path = new Path();
assertTrue(path.isEmpty());
Path dst = new Path();
addRectToPath(path);
path.transform(new Matrix(), dst);
assertFalse(dst.isEmpty());
}
@Test
public void testLineTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.lineTo(XCOORD, YCOORD);
assertFalse(path.isEmpty());
}
@Test
public void testClose() {
Path path = new Path();
assertTrue(path.isEmpty());
addRectToPath(path);
path.close();
}
@Test
public void testQuadTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.quadTo(20.0f, 20.0f, 40.0f, 40.0f);
assertFalse(path.isEmpty());
}
@Test
public void testAddCircle() {
// new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.addCircle(XCOORD, YCOORD, 10.0f, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testArcTo1() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.arcTo(oval, 0.0f, 30.0f, true);
assertFalse(path.isEmpty());
}
@Test
public void testArcTo2() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.arcTo(oval, 0.0f, 30.0f);
assertFalse(path.isEmpty());
}
@Test
public void testComputeBounds1() {
RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f);
Path path = new Path();
assertTrue(path.isEmpty());
RectF bounds = new RectF();
path.computeBounds(bounds, true);
assertEquals(expected.width(), bounds.width(), 0.0f);
assertEquals(expected.height(), bounds.height(), 0.0f);
path.computeBounds(bounds, false);
assertEquals(expected.width(), bounds.width(), 0.0f);
assertEquals(expected.height(), bounds.height(), 0.0f);
}
@Test
public void testComputeBounds2() {
RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM);
Path path = new Path();
assertTrue(path.isEmpty());
RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRect(bounds, Path.Direction.CW);
path.computeBounds(bounds, true);
assertEquals(expected.width(), bounds.width(), 0.0f);
assertEquals(expected.height(), bounds.height(), 0.0f);
path.computeBounds(bounds, false);
assertEquals(expected.width(), bounds.width(), 0.0f);
assertEquals(expected.height(), bounds.height(), 0.0f);
}
@Test
public void testSetLastPoint() {
Path path = new Path();
path.setLastPoint(10.0f, 10.0f);
}
@Test
public void testRLineTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.rLineTo(10.0f, 10.0f);
assertFalse(path.isEmpty());
}
@Test
public void testIsEmpty() {
Path path = new Path();
assertTrue(path.isEmpty());
addRectToPath(path);
assertFalse(path.isEmpty());
}
@Test
public void testRewind() {
Path.FillType expected = Path.FillType.EVEN_ODD;
Path path = new Path();
assertTrue(path.isEmpty());
addRectToPath(path);
path.rewind();
path.setFillType(Path.FillType.EVEN_ODD);
assertTrue(path.isEmpty());
assertEquals(expected, path.getFillType());
}
@Test
public void testAddOval() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addOval(oval, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testIsRect() {
Path path = new Path();
assertTrue(path.isEmpty());
addRectToPath(path);
}
@Test
public void testAddPath1() {
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
addRectToPath(src);
path.addPath(src, 10.0f, 10.0f);
assertFalse(path.isEmpty());
}
@Test
public void testAddPath2() {
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
addRectToPath(src);
path.addPath(src);
assertFalse(path.isEmpty());
}
@Test
public void testAddPath3() {
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
addRectToPath(src);
Matrix matrix = new Matrix();
path.addPath(src, matrix);
assertFalse(path.isEmpty());
}
@Test
public void testAddRoundRect1() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRoundRect(rect, XCOORD, YCOORD, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testAddRoundRect2() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
float[] radii = new float[8];
for (int i = 0; i < 8; i++) {
radii[i] = 10.0f + i * 5.0f;
}
path.addRoundRect(rect, radii, Path.Direction.CW);
assertFalse(path.isEmpty());
}
@Test
public void testIsConvex1() {
Path path = new Path();
path.addRect(0, 0, 100, 10, Path.Direction.CW);
assertTrue(path.isConvex());
path.addRect(0, 0, 10, 100, Path.Direction.CW);
assertFalse(path.isConvex()); // path is concave
}
@Test
public void testIsConvex2() {
Path path = new Path();
path.addRect(0, 0, 40, 40, Path.Direction.CW);
assertTrue(path.isConvex());
path.addRect(10, 10, 30, 30, Path.Direction.CCW);
assertFalse(path.isConvex()); // path has hole, isn't convex
}
@Test
public void testIsConvex3() {
Path path = new Path();
path.addRect(0, 0, 10, 10, Path.Direction.CW);
assertTrue(path.isConvex());
path.addRect(0, 20, 10, 10, Path.Direction.CW);
assertFalse(path.isConvex()); // path isn't one convex shape
}
@Test
public void testIsInverseFillType() {
Path path = new Path();
assertFalse(path.isInverseFillType());
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
assertTrue(path.isInverseFillType());
}
@Test
public void testOffset1() {
Path path = new Path();
assertTrue(path.isEmpty());
addRectToPath(path);
Path dst = new Path();
path.offset(XCOORD, YCOORD, dst);
assertFalse(dst.isEmpty());
}
@Test
public void testCubicTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.cubicTo(10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f);
assertFalse(path.isEmpty());
}
@Test
public void testReset() {
Path path = new Path();
assertTrue(path.isEmpty());
Path path1 = new Path();
addRectToPath(path1);
path.set(path1);
assertFalse(path.isEmpty());
path.reset();
assertTrue(path.isEmpty());
}
@Test
public void testToggleInverseFillType() {
Path path = new Path();
assertTrue(path.isEmpty());
path.toggleInverseFillType();
assertTrue(path.isInverseFillType());
}
@Test
public void testAddArc() {
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addArc(oval, 0.0f, 30.0f);
assertFalse(path.isEmpty());
}
@Test
public void testRCubicTo() {
Path path = new Path();
assertTrue(path.isEmpty());
path.rCubicTo(10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f);
assertFalse(path.isEmpty());
}
@Test
public void testOffsetTextPath() {
Paint paint = new Paint();
Path path = new Path();
paint.setTextSize(20);
String text = "abc";
paint.getTextPath(text, 0, text.length() - 1, 0, 0, path);
RectF expectedRect = new RectF();
path.computeBounds(expectedRect, false);
assertFalse(expectedRect.isEmpty());
int offset = 10;
expectedRect.offset(offset, offset);
path.offset(offset, offset);
RectF offsettedRect = new RectF();
path.computeBounds(offsettedRect, false);
assertEquals(expectedRect, offsettedRect);
}
@Test(expected=IllegalArgumentException.class)
public void testApproximate_lowError() {
new Path().approximate(-0.1f);
}
@Test
public void testApproximate_rect_cw() {
Path path = new Path();
path.addRect(0, 0, 100, 100, Path.Direction.CW);
assertArrayEquals(new float[] {
0, 0, 0,
0.25f, 100, 0,
0.50f, 100, 100,
0.75f, 0, 100,
1, 0, 0,
}, path.approximate(1f), 0);
}
@Test
public void testApproximate_rect_ccw() {
Path path = new Path();
path.addRect(0, 0, 100, 100, Path.Direction.CCW);
assertArrayEquals(new float[] {
0, 0, 0,
0.25f, 0, 100,
0.50f, 100, 100,
0.75f, 100, 0,
1, 0, 0,
}, path.approximate(1f), 0);
}
@Test
public void testApproximate_empty() {
Path path = new Path();
assertArrayEquals(new float[] {
0, 0, 0,
1, 0, 0,
}, path.approximate(0.5f), 0);
}
@Test
public void testApproximate_circle() {
Path path = new Path();
path.addCircle(0, 0, 50, Path.Direction.CW);
assertTrue(path.approximate(0.25f).length > 20);
}
/** This test just ensures the process doesn't crash. The actual output is not interesting
* hence the lack of asserts, as the only behavior that's being asserted is that it
* doesn't crash.
*/
@Test
public void testUseAfterFinalize() throws Throwable {
PathAbuser pathAbuser = new PathAbuser();
// Basic test that we created a path successfully
assertTrue(pathAbuser.isEmpty());
addRectToPath(pathAbuser);
assertTrue(pathAbuser.isRect(null));
assertFalse(pathAbuser.isEmpty());
// Now use-after-finalize.
pathAbuser.destroy();
pathAbuser.isEmpty();
pathAbuser.isRect(null);
pathAbuser.destroy();
pathAbuser.isEmpty();
pathAbuser.isRect(null);
pathAbuser.destroy();
}
private static final class PathAbuser extends Path {
public void destroy() throws Throwable {
finalize();
}
}
private static void verifyPathsAreEquivalent(Path actual, Path expected) {
Bitmap actualBitmap = drawAndGetBitmap(actual);
Bitmap expectedBitmap = drawAndGetBitmap(expected);
assertTrue(actualBitmap.sameAs(expectedBitmap));
}
private static final int WIDTH = 100;
private static final int HEIGHT = 100;
private static Bitmap drawAndGetBitmap(Path path) {
Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.BLACK);
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = new Canvas(bitmap);
canvas.drawPath(path, paint);
return bitmap;
}
private void addRectToPath(Path path) {
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRect(rect, Path.Direction.CW);
}
}