1 /* 2 * Copyright 2021 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.compose.foundation.shape 18 19 import androidx.annotation.IntRange 20 import androidx.compose.ui.geometry.CornerRadius 21 import androidx.compose.ui.geometry.RoundRect 22 import androidx.compose.ui.geometry.Size 23 import androidx.compose.ui.geometry.toRect 24 import androidx.compose.ui.graphics.Outline 25 import androidx.compose.ui.unit.Dp 26 import androidx.compose.ui.unit.LayoutDirection 27 import androidx.compose.ui.unit.dp 28 29 /** 30 * A shape describing the rectangle with rounded corners. 31 * 32 * This shape will not automatically mirror the corner sizes in [LayoutDirection.Rtl], use 33 * [RoundedCornerShape] for the layout direction aware version of this shape. 34 * 35 * @param topLeft a size of the top left corner 36 * @param topRight a size of the top right corner 37 * @param bottomRight a size of the bottom right corner 38 * @param bottomLeft a size of the bottom left corner 39 */ 40 class AbsoluteRoundedCornerShape( 41 topLeft: CornerSize, 42 topRight: CornerSize, 43 bottomRight: CornerSize, 44 bottomLeft: CornerSize 45 ) : 46 CornerBasedShape( 47 topStart = topLeft, 48 topEnd = topRight, 49 bottomEnd = bottomRight, 50 bottomStart = bottomLeft 51 ) { 52 createOutlinenull53 override fun createOutline( 54 size: Size, 55 topStart: Float, 56 topEnd: Float, 57 bottomEnd: Float, 58 bottomStart: Float, 59 layoutDirection: LayoutDirection 60 ) = 61 if (topStart + topEnd + bottomEnd + bottomStart == 0.0f) { 62 Outline.Rectangle(size.toRect()) 63 } else { 64 Outline.Rounded( 65 RoundRect( 66 rect = size.toRect(), 67 topLeft = CornerRadius(topStart), 68 topRight = CornerRadius(topEnd), 69 bottomRight = CornerRadius(bottomEnd), 70 bottomLeft = CornerRadius(bottomStart) 71 ) 72 ) 73 } 74 copynull75 override fun copy( 76 topStart: CornerSize, 77 topEnd: CornerSize, 78 bottomEnd: CornerSize, 79 bottomStart: CornerSize 80 ) = 81 AbsoluteRoundedCornerShape( 82 topLeft = topStart, 83 topRight = topEnd, 84 bottomRight = bottomEnd, 85 bottomLeft = bottomStart 86 ) 87 88 override fun toString(): String { 89 return "AbsoluteRoundedCornerShape(topLeft = $topStart, topRight = $topEnd, " + 90 "bottomRight = $bottomEnd, bottomLeft = $bottomStart)" 91 } 92 equalsnull93 override fun equals(other: Any?): Boolean { 94 if (this === other) return true 95 if (other !is AbsoluteRoundedCornerShape) return false 96 97 if (topStart != other.topStart) return false 98 if (topEnd != other.topEnd) return false 99 if (bottomEnd != other.bottomEnd) return false 100 if (bottomStart != other.bottomStart) return false 101 102 return true 103 } 104 hashCodenull105 override fun hashCode(): Int { 106 var result = topStart.hashCode() 107 result = 31 * result + topEnd.hashCode() 108 result = 31 * result + bottomEnd.hashCode() 109 result = 31 * result + bottomStart.hashCode() 110 return result 111 } 112 Floatnull113 private fun Float.toRadius() = CornerRadius(this) 114 } 115 116 /** 117 * Creates [AbsoluteRoundedCornerShape] with the same size applied for all four corners. 118 * 119 * @param corner [CornerSize] to apply. 120 */ 121 fun AbsoluteRoundedCornerShape(corner: CornerSize) = 122 AbsoluteRoundedCornerShape(corner, corner, corner, corner) 123 124 /** 125 * Creates [AbsoluteRoundedCornerShape] with the same size applied for all four corners. 126 * 127 * @param size Size in [Dp] to apply. 128 */ 129 fun AbsoluteRoundedCornerShape(size: Dp) = AbsoluteRoundedCornerShape(CornerSize(size)) 130 131 /** 132 * Creates [AbsoluteRoundedCornerShape] with the same size applied for all four corners. 133 * 134 * @param size Size in pixels to apply. 135 */ 136 fun AbsoluteRoundedCornerShape(size: Float) = AbsoluteRoundedCornerShape(CornerSize(size)) 137 138 /** 139 * Creates [AbsoluteRoundedCornerShape] with the same size applied for all four corners. 140 * 141 * @param percent Size in percents to apply. 142 */ 143 fun AbsoluteRoundedCornerShape(percent: Int) = AbsoluteRoundedCornerShape(CornerSize(percent)) 144 145 /** Creates [AbsoluteRoundedCornerShape] with sizes defined in [Dp]. */ 146 fun AbsoluteRoundedCornerShape( 147 topLeft: Dp = 0.dp, 148 topRight: Dp = 0.dp, 149 bottomRight: Dp = 0.dp, 150 bottomLeft: Dp = 0.dp 151 ) = 152 AbsoluteRoundedCornerShape( 153 topLeft = CornerSize(topLeft), 154 topRight = CornerSize(topRight), 155 bottomRight = CornerSize(bottomRight), 156 bottomLeft = CornerSize(bottomLeft) 157 ) 158 159 /** Creates [AbsoluteRoundedCornerShape] with sizes defined in pixels. */ 160 fun AbsoluteRoundedCornerShape( 161 topLeft: Float = 0.0f, 162 topRight: Float = 0.0f, 163 bottomRight: Float = 0.0f, 164 bottomLeft: Float = 0.0f 165 ) = 166 AbsoluteRoundedCornerShape( 167 topLeft = CornerSize(topLeft), 168 topRight = CornerSize(topRight), 169 bottomRight = CornerSize(bottomRight), 170 bottomLeft = CornerSize(bottomLeft) 171 ) 172 173 /** 174 * Creates [AbsoluteRoundedCornerShape] with sizes defined in percents of the shape's smaller side. 175 * 176 * @param topLeftPercent The top left corner radius as a percentage of the smaller side, with a 177 * range of 0 - 100. 178 * @param topRightPercent The top right corner radius as a percentage of the smaller side, with a 179 * range of 0 - 100. 180 * @param bottomRightPercent The bottom right corner radius as a percentage of the smaller side, 181 * with a range of 0 - 100. 182 * @param bottomLeftPercent The bottom left corner radius as a percentage of the smaller side, with 183 * a range of 0 - 100. 184 */ 185 fun AbsoluteRoundedCornerShape( 186 @IntRange(from = 0, to = 100) topLeftPercent: Int = 0, 187 @IntRange(from = 0, to = 100) topRightPercent: Int = 0, 188 @IntRange(from = 0, to = 100) bottomRightPercent: Int = 0, 189 @IntRange(from = 0, to = 100) bottomLeftPercent: Int = 0 190 ) = 191 AbsoluteRoundedCornerShape( 192 topLeft = CornerSize(topLeftPercent), 193 topRight = CornerSize(topRightPercent), 194 bottomRight = CornerSize(bottomRightPercent), 195 bottomLeft = CornerSize(bottomLeftPercent) 196 ) 197