| /* |
| * Copyright 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package androidx.compose.ui.geometry |
| |
| import androidx.compose.Immutable |
| import androidx.compose.Stable |
| import androidx.compose.ui.util.lerp |
| import androidx.compose.ui.util.packFloats |
| import androidx.compose.ui.util.toStringAsFixed |
| import androidx.compose.ui.util.unpackFloat1 |
| import androidx.compose.ui.util.unpackFloat2 |
| import kotlin.math.truncate |
| |
| /** |
| * Constructs a Radius with the given [x] and [y] parameters for the |
| * size of the radius along the x and y axis respectively. By default |
| * the radius along the Y axis matches that of the given x-axis |
| * unless otherwise specified |
| */ |
| @Suppress("NOTHING_TO_INLINE") |
| @Stable |
| inline fun Radius(x: Float, y: Float = x) = Radius(packFloats(x, y)) |
| |
| /** A radius for either circular or elliptical shapes. */ |
| @Immutable |
| inline class Radius(@PublishedApi internal val packedValue: Long) { |
| |
| /** The radius value on the horizontal axis. */ |
| @Stable |
| val x: Float |
| get() = unpackFloat1(packedValue) |
| /** The radius value on the vertical axis. */ |
| @Stable |
| val y: Float |
| get() = unpackFloat2(packedValue) |
| |
| /** |
| * Returns a copy of this Radius instance optionally overriding the |
| * radius parameter for the x or y axis |
| */ |
| fun copy(x: Float = this.x, y: Float = this.y) = Radius(x, y) |
| |
| companion object { |
| |
| /** |
| * A radius with [x] and [y] values set to zero. |
| * |
| * You can use [Radius.Zero] with [RRect] to have right-angle corners. |
| */ |
| @Stable |
| val Zero: Radius = Radius(0.0f) |
| } |
| |
| /** |
| * Unary negation operator. |
| * |
| * Returns a Radius with the distances negated. |
| * |
| * Radiuses with negative values aren't geometrically meaningful, but could |
| * occur as part of expressions. For example, negating a radius of one pixel |
| * and then adding the result to another radius is equivalent to subtracting |
| * a radius of one pixel from the other. |
| */ |
| @Stable |
| operator fun unaryMinus() = Radius(-x, -y) |
| |
| /** |
| * Binary subtraction operator. |
| * |
| * Returns a radius whose [x] value is the left-hand-side operand's [x] |
| * minus the right-hand-side operand's [x] and whose [y] value is the |
| * left-hand-side operand's [y] minus the right-hand-side operand's [y]. |
| */ |
| @Stable |
| operator fun minus(other: Radius) = Radius(x - other.x, y - other.y) |
| |
| /** |
| * Binary addition operator. |
| * |
| * Returns a radius whose [x] value is the sum of the [x] values of the |
| * two operands, and whose [y] value is the sum of the [y] values of the |
| * two operands. |
| */ |
| @Stable |
| operator fun plus(other: Radius) = Radius(x + other.x, y + other.y) |
| |
| /** |
| * Multiplication operator. |
| * |
| * Returns a radius whose coordinates are the coordinates of the |
| * left-hand-side operand (a radius) multiplied by the scalar |
| * right-hand-side operand (a Float). |
| */ |
| @Stable |
| operator fun times(operand: Float) = Radius(x * operand, y * operand) |
| |
| /** |
| * Division operator. |
| * |
| * Returns a radius whose coordinates are the coordinates of the |
| * left-hand-side operand (a radius) divided by the scalar right-hand-side |
| * operand (a Float). |
| */ |
| @Stable |
| operator fun div(operand: Float) = Radius(x / operand, y / operand) |
| |
| /** |
| * Integer (truncating) division operator. |
| * |
| * Returns a radius whose coordinates are the coordinates of the |
| * left-hand-side operand (a radius) divided by the scalar right-hand-side |
| * operand (a Float), rounded towards zero. |
| */ |
| fun truncDiv(operand: Float): Radius = |
| Radius(truncate(x / operand), truncate(y / operand)) |
| |
| /** |
| * Modulo (remainder) operator. |
| * |
| * Returns a radius whose coordinates are the remainder of dividing the |
| * coordinates of the left-hand-side operand (a radius) by the scalar |
| * right-hand-side operand (a Float). |
| */ |
| @Stable |
| operator fun rem(operand: Float) = Radius(x % operand, y % operand) |
| |
| override fun toString(): String { |
| return if (x == y) { |
| "Radius.circular(${x.toStringAsFixed(1)})" |
| } else { |
| "Radius.elliptical(${x.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})" |
| } |
| } |
| } |
| |
| /** |
| * Linearly interpolate between two radii. |
| * |
| * The [fraction] argument represents position on the timeline, with 0.0 meaning |
| * that the interpolation has not started, returning [start] (or something |
| * equivalent to [start]), 1.0 meaning that the interpolation has finished, |
| * returning [stop] (or something equivalent to [stop]), and values in between |
| * meaning that the interpolation is at the relevant point on the timeline |
| * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and |
| * 1.0, so negative values and values greater than 1.0 are valid (and can |
| * easily be generated by curves). |
| * |
| * Values for [fraction] are usually obtained from an [Animation<Float>], such as |
| * an `AnimationController`. |
| */ |
| @Stable |
| fun lerp(start: Radius, stop: Radius, fraction: Float): Radius { |
| return Radius( |
| lerp(start.x, stop.x, fraction), |
| lerp(start.y, stop.y, fraction) |
| ) |
| } |