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