1 /* 2 * Copyright 2022 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 @file:JvmName("PathSegmentUtilities") 18 19 package androidx.graphics.path 20 21 import android.graphics.PointF 22 23 /** 24 * A path segment represents a curve (line, cubic, quadratic or conic) or a command inside a fully 25 * formed [path][android.graphics.Path] object. 26 * 27 * A segment is identified by a [type][PathSegment.Type] which in turns defines how many [points] 28 * are available (from 0 to 3) and whether the [weight] is meaningful. Please refer to the 29 * documentation of each [type][PathSegment.Type] for more information. 30 * 31 * A segment with the [Move][Type.Move] or [Close][Type.Close] is usually represented by the 32 * singletons [DoneSegment] and [CloseSegment] respectively. 33 * 34 * @property type The type that identifies this segment and defines the number of points. 35 * @property points An array of points describing this segment, whose size depends on [type]. 36 * @property weight Conic weight, only valid if [type] is [Type.Conic]. 37 */ 38 class PathSegment 39 internal constructor( 40 val type: Type, 41 @get:Suppress("ArrayReturn") val points: Array<PointF>, 42 val weight: Float 43 ) { 44 /** 45 * Type of a given segment in a [path][android.graphics.Path], either a command ([Type.Move], 46 * [Type.Close], [Type.Done]) or a curve ([Type.Line], [Type.Cubic], [Type.Quadratic], 47 * [Type.Conic]). 48 */ 49 enum class Type { 50 /** 51 * Move command, the path segment contains 1 point indicating the move destination. The 52 * weight is set 0.0f and not meaningful. 53 */ 54 Move, 55 /** 56 * Line curve, the path segment contains 2 points indicating the two extremities of the 57 * line. The weight is set 0.0f and not meaningful. 58 */ 59 Line, 60 /** 61 * Quadratic curve, the path segment contains 3 points in the following order: 62 * - Start point 63 * - Control point 64 * - End point 65 * 66 * The weight is set 0.0f and not meaningful. 67 */ 68 Quadratic, 69 /** 70 * Conic curve, the path segment contains 3 points in the following order: 71 * - Start point 72 * - Control point 73 * - End point 74 * 75 * The curve is weighted by the [weight][PathSegment.weight] property. 76 */ 77 Conic, 78 /** 79 * Cubic curve, the path segment contains 4 points in the following order: 80 * - Start point 81 * - First control point 82 * - Second control point 83 * - End point 84 * 85 * The weight is set 0.0f and not meaningful. 86 */ 87 Cubic, 88 /** 89 * Close command, close the current contour by joining the last point added to the path with 90 * the first point of the current contour. The segment does not contain any point. The 91 * weight is set 0.0f and not meaningful. 92 */ 93 Close, 94 /** 95 * Done command, which indicates that no further segment will be found in the path. It 96 * typically indicates the end of an iteration over a path and can be ignored. 97 */ 98 Done 99 } 100 equalsnull101 override fun equals(other: Any?): Boolean { 102 if (this === other) return true 103 if (javaClass != other?.javaClass) return false 104 105 other as PathSegment 106 107 if (type != other.type) return false 108 if (!points.contentEquals(other.points)) return false 109 if (weight != other.weight) return false 110 111 return true 112 } 113 hashCodenull114 override fun hashCode(): Int { 115 var result = type.hashCode() 116 result = 31 * result + points.contentHashCode() 117 result = 31 * result + weight.hashCode() 118 return result 119 } 120 toStringnull121 override fun toString(): String { 122 return "PathSegment(type=$type, points=${points.contentToString()}, weight=$weight)" 123 } 124 } 125 126 /** 127 * A [PathSegment] containing the [Done][PathSegment.Type.Done] command. This static object exists 128 * to avoid allocating a new segment when returning a [Done][PathSegment.Type.Done] result from 129 * [PathIterator.next]. 130 */ 131 val DoneSegment = PathSegment(PathSegment.Type.Done, emptyArray(), 0.0f) 132 133 /** 134 * A [PathSegment] containing the [Close][PathSegment.Type.Close] command. This static object exists 135 * to avoid allocating a new segment when returning a [Close][PathSegment.Type.Close] result from 136 * [PathIterator.next]. 137 */ 138 val CloseSegment = PathSegment(PathSegment.Type.Close, emptyArray(), 0.0f) 139