1 /*
<lambda>null2  * Copyright 2023 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 androidx.graphics.shapes
18 
19 import android.graphics.Matrix
20 import android.graphics.Path
21 
22 /**
23  * Transforms a [RoundedPolygon] by the given matrix.
24  *
25  * @param matrix The matrix by which the polygon is to be transformed
26  */
27 fun RoundedPolygon.transformed(matrix: Matrix): RoundedPolygon {
28     val tempArray = FloatArray(2)
29     return transformed { x, y ->
30         tempArray[0] = x
31         tempArray[1] = y
32         matrix.mapPoints(tempArray)
33         TransformResult(tempArray[0], tempArray[1])
34     }
35 }
36 
37 /**
38  * Gets a [Path] representation for a [RoundedPolygon] shape. Note that there is some rounding
39  * happening (to the nearest thousandth), to work around rendering artifacts introduced by some
40  * points being just slightly off from each other (far less than a pixel). This also allows for a
41  * more optimal path, as redundant curves (usually a single point) can be detected and not added to
42  * the resulting path.
43  *
44  * @param path an optional [Path] object which, if supplied, will avoid the function having to
45  *   create a new [Path] object
46  */
47 @JvmOverloads
RoundedPolygonnull48 fun RoundedPolygon.toPath(path: Path = Path()): Path {
49     pathFromCubics(path, cubics)
50     return path
51 }
52 
toPathnull53 fun Morph.toPath(progress: Float, path: Path = Path()): Path {
54     pathFromCubics(path, asCubics(progress))
55     return path
56 }
57 
pathFromCubicsnull58 private fun pathFromCubics(path: Path, cubics: List<Cubic>) {
59     var first = true
60     path.rewind()
61     for (i in 0 until cubics.size) {
62         val cubic = cubics[i]
63         if (first) {
64             path.moveTo(cubic.anchor0X, cubic.anchor0Y)
65             first = false
66         }
67         path.cubicTo(
68             cubic.control0X,
69             cubic.control0Y,
70             cubic.control1X,
71             cubic.control1Y,
72             cubic.anchor1X,
73             cubic.anchor1Y
74         )
75     }
76     path.close()
77 }
78