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 179c80550cbbe357a89e2abeeb9c7769fcaefc3a65Jake Whartonpackage androidx.core.graphics 18245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 19245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport android.graphics.Path 204df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guyimport android.graphics.RectF 218770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Whartonimport android.support.test.filters.SdkSuppress 22245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Assert.assertEquals 23245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Assert.assertNotEquals 244df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guyimport org.junit.Assert.assertTrue 25245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyimport org.junit.Test 26245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 27245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guyclass PathTest { 288770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 26) 29245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy @Test fun testFlatten() { 30245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy val p = Path() 31245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 32245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Start with several moves 33245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(5.0f, 5.0f) 34245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 35245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(20.0f, 20.0f) 36245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(30.0f, 10.0f) 37245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // Several moves in the middle 38245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(40.0f, 10.0f) 39245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(50.0f, 10.0f) 40245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.lineTo(60.0f, 20.0f) 41245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy // End with several moves 42245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(10.0f, 10.0f) 43245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.moveTo(30.0f, 30.0f) 44245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy 456889aa5fa8875d1a2842df11e24a5fbb2fd76a67Jake Wharton var count = 0 46245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy p.flatten().forEach { 47245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy count++ 48245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertNotEquals(it.startFraction, it.endFraction) 49245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 50245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy assertEquals(3, count) 51245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy } 524df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 538770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 544df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testUnion() { 554df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 5626fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 574df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 584df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 + r2 594df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 604df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 614df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 624df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 634df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 644df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 658770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 664df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testAnd() { 674df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 6826fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 694df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 704df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 and r2 714df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 724df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 734df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 744df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 754df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 764df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 778770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 784df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testDifference() { 794df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 804df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 814df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 824df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 - r2 834df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 844df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 854df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 864df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 5.0f, 10.0f), r) 874df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 884df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 898770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 904df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testIntersection() { 914df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 9226fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy val r2 = Path().apply { addRect(5.0f, 0.0f, 15.0f, 15.0f, Path.Direction.CW) } 934df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 944df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 or r2 954df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 964df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 974df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 9826fbe188a9873102721c3585be159e0dccdfa6b2Romain Guy assertEquals(RectF(5.0f, 0.0f, 10.0f, 10.0f), r) 994df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1004df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1018770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1024df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testEmptyIntersection() { 1034df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 2.0f, 2.0f, Path.Direction.CW) } 1044df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 5.0f, 7.0f, 7.0f, Path.Direction.CW) } 1054df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1064df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 or r2 1074df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertTrue(p.isEmpty) 1084df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 1094df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1108770f84ffe4cf2ee98744f30ee8b4cd659a65633Jake Wharton @SdkSuppress(minSdkVersion = 19) 1114df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy @Test fun testXor() { 1124df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r1 = Path().apply { addRect(0.0f, 0.0f, 10.0f, 10.0f, Path.Direction.CW) } 1134df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r2 = Path().apply { addRect(5.0f, 5.0f, 15.0f, 15.0f, Path.Direction.CW) } 1144df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1154df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val p = r1 xor r2 1164df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy val r = RectF() 1174df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy p.computeBounds(r, true) 1184df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy 1194df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy assertEquals(RectF(0.0f, 0.0f, 15.0f, 15.0f), r) 1204df8629cfe9f924b507ff26e53f896e025eb9ff7Romain Guy } 121245f352e7e7a8b37faebc5aefd52ce98ae9f08e6Romain Guy} 122