PathTest.kt revision 8770f84ffe4cf2ee98744f30ee8b4cd659a65633
1245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy/* 2245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * Copyright (C) 2018 The Android Open Source Project 3245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * 4245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * you may not use this file except in compliance with the License. 6245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * You may obtain a copy of the License at 7245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * 8245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * 10245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * Unless required by applicable law or agreed to in writing, software 11245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * See the License for the specific language governing permissions and 14245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy * limitations under the License. 15245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy */ 16245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 17245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guypackage androidx.graphics 18245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 19245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport android.graphics.Path 20245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport android.graphics.PointF 214df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guyimport android.graphics.RectF 228770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Whartonimport android.support.test.filters.SdkSuppress 23245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport androidx.fail 24245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Assert.assertEquals 25245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Assert.assertNotEquals 264df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guyimport org.junit.Assert.assertTrue 27245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Test 28245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 29245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyclass PathTest { 308770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 26) 31245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy @Test fun testFlattenEmptyPath() { 32245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy Path().flatten().forEach { fail("An empty path should not have segments: " + it) } 33245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 34245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 358770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 26) 36245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy @Test fun testFlatten() { 37245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy val p = Path() 38245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 39245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Single line 40245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(10.0f, 10.0f) 41245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertEquals( 42245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy PathSegment(PointF(), 0.0f, PointF(10.0f, 10.0f), 1.0f), 43245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.flatten().iterator().next()) 44245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 45245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Only moves 46245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.reset() 47245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 48245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(20.0f, 20.0f) 49245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.flatten().forEach { fail("A path with only moves should not have segments: " + it) } 50245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 51245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Mix of moves/lines 52245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.reset() 53245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 54245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(20.0f, 20.0f) 55245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(60.0f, 20.0f) 56245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 57245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy var count = 0 58245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.flatten().forEach { 59245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy count++ 60245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertNotEquals(it.startFraction, it.endFraction) 61245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 62245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertEquals(2, count) 63245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 64245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Mix of moves/lines, starts with moves, ends with moves 65245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.reset() 66245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Start with several moves 67245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(5.0f, 5.0f) 68245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 69245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(20.0f, 20.0f) 70245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(30.0f, 10.0f) 71245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Several moves in the middle 72245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(40.0f, 10.0f) 73245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(50.0f, 10.0f) 74245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(60.0f, 20.0f) 75245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // End with several moves 76245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 77245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(30.0f, 30.0f) 78245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 79245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy count = 0 80245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.flatten().forEach { 81245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy count++ 82245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertNotEquals(it.startFraction, it.endFraction) 83245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 84245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertEquals(3, count) 85245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 864df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 878770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 884df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testUnion() { 894df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 9026fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 914df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 924df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 + r2 934df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 944df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 954df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 964df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 974df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 984df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 998770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1004df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testAnd() { 1014df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 10226fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 1034df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1044df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 and r2 1054df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 1064df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 1074df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1084df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 1094df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1104df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1118770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1124df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testDifference() { 1134df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 1144df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 1154df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1164df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 - r2 1174df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 1184df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 1194df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1204df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 5.0f, 10.0f), r) 1214df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1224df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1238770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1244df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testIntersection() { 1254df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 12626fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 1274df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1284df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 or r2 1294df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 1304df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 1314df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 13226fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy assertEquals(RectF(5.0f, 0.0f, 10.0f, 10.0f), r) 1334df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1344df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1358770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1364df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testEmptyIntersection() { 1374df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 2.0f, 2.0f, Path.Direction.CW) } 1384df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 5.0f, 7.0f, 7.0f, Path.Direction.CW) } 1394df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1404df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 or r2 1414df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertTrue(p.isEmpty) 1424df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1434df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1448770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1454df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testXor() { 1464df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 1474df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 5.0f, 15.0f, 15.0f, Path.Direction.CW) } 1484df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1494df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 xor r2 1504df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 1514df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 1524df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1534df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 1544df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 155245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy} 156