Andrey Kulikov | feb3ee0 | 2019-01-23 14:25:29 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 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 | |
Louis Pullen-Freilich | a7eeb10 | 2020-07-22 17:54:24 +0100 | [diff] [blame] | 17 | package androidx.compose.ui.unit |
Andrey Kulikov | feb3ee0 | 2019-01-23 14:25:29 +0000 | [diff] [blame] | 18 | |
Louis Pullen-Freilich | 1f10a59 | 2020-07-24 16:35:14 +0100 | [diff] [blame] | 19 | import androidx.compose.runtime.Immutable |
| 20 | import androidx.compose.runtime.Stable |
Louis Pullen-Freilich | f434a13 | 2020-07-22 14:19:24 +0100 | [diff] [blame] | 21 | import androidx.compose.ui.geometry.Rect |
George Mount | dae1d49 | 2021-07-23 22:52:24 +0000 | [diff] [blame] | 22 | import androidx.compose.ui.geometry.Size |
Zach Klippenstein | fc18319 | 2021-10-04 23:31:05 -0700 | [diff] [blame] | 23 | import androidx.compose.ui.geometry.isSpecified |
Oleksandr Karpovich | 6f98648 | 2022-06-28 11:13:19 +0200 | [diff] [blame] | 24 | import androidx.compose.ui.unit.internal.JvmDefaultWithCompatibility |
Jeff Gaston | bcaacc8 | 2023-05-09 22:44:28 -0400 | [diff] [blame] | 25 | import kotlin.math.roundToInt |
Andrey Kulikov | feb3ee0 | 2019-01-23 14:25:29 +0000 | [diff] [blame] | 26 | |
| 27 | /** |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 28 | * A density of the screen. Used for convert [Dp] to pixels. |
| 29 | * |
| 30 | * @param density The logical density of the display. This is a scaling factor for the [Dp] unit. |
| 31 | * @param fontScale Current user preference for the scaling factor for fonts. |
| 32 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 33 | @Stable |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 34 | fun Density(density: Float, fontScale: Float = 1f): Density = |
| 35 | DensityImpl(density, fontScale) |
| 36 | |
| 37 | private data class DensityImpl( |
| 38 | override val density: Float, |
| 39 | override val fontScale: Float |
| 40 | ) : Density |
| 41 | |
| 42 | /** |
George Mount | dae1d49 | 2021-07-23 22:52:24 +0000 | [diff] [blame] | 43 | * A density of the screen. Used for the conversions between pixels, [Dp], [Int] and [TextUnit]. |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 44 | * |
Louis Pullen-Freilich | a7eeb10 | 2020-07-22 17:54:24 +0100 | [diff] [blame] | 45 | * @sample androidx.compose.ui.unit.samples.WithDensitySample |
Andrey Kulikov | feb3ee0 | 2019-01-23 14:25:29 +0000 | [diff] [blame] | 46 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 47 | @Immutable |
Adam Powell | 289a76f | 2022-06-01 14:53:23 -0700 | [diff] [blame] | 48 | @JvmDefaultWithCompatibility |
Tyler Freeman | 210d5ff | 2023-10-03 16:57:34 -0700 | [diff] [blame] | 49 | interface Density : FontScaling { |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 50 | |
| 51 | /** |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 52 | * The logical density of the display. This is a scaling factor for the [Dp] unit. |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 53 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 54 | @Stable |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 55 | val density: Float |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 56 | |
| 57 | /** |
Nader Jawad | feb99f8 | 2020-05-21 13:07:36 -0700 | [diff] [blame] | 58 | * Convert [Dp] to pixels. Pixels are used to paint to Canvas. |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 59 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 60 | @Stable |
Nader Jawad | feb99f8 | 2020-05-21 13:07:36 -0700 | [diff] [blame] | 61 | fun Dp.toPx(): Float = value * density |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 62 | |
| 63 | /** |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 64 | * Convert [Dp] to [Int] by rounding |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 65 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 66 | @Stable |
Mihai Popa | 217bf49 | 2021-01-25 23:55:14 +0000 | [diff] [blame] | 67 | fun Dp.roundToPx(): Int { |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 68 | val px = toPx() |
| 69 | return if (px.isInfinite()) Constraints.Infinity else px.roundToInt() |
| 70 | } |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 71 | |
| 72 | /** |
Nader Jawad | feb99f8 | 2020-05-21 13:07:36 -0700 | [diff] [blame] | 73 | * Convert Sp to pixels. Pixels are used to paint to Canvas. |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 74 | * @throws IllegalStateException if TextUnit other than SP unit is specified. |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 75 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 76 | @Stable |
Nader Jawad | feb99f8 | 2020-05-21 13:07:36 -0700 | [diff] [blame] | 77 | fun TextUnit.toPx(): Float { |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 78 | check(type == TextUnitType.Sp) { "Only Sp can convert to Px" } |
Tyler Freeman | d1b43ca | 2023-08-10 17:28:22 +0100 | [diff] [blame] | 79 | return toDp().toPx() |
Seigo Nonaka | d963820 | 2019-11-19 16:37:07 -0800 | [diff] [blame] | 80 | } |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 81 | |
| 82 | /** |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 83 | * Convert Sp to [Int] by rounding |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 84 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 85 | @Stable |
Mihai Popa | 217bf49 | 2021-01-25 23:55:14 +0000 | [diff] [blame] | 86 | fun TextUnit.roundToPx(): Int = toPx().roundToInt() |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 87 | |
| 88 | /** |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 89 | * Convert an [Int] pixel value to [Dp]. |
Calin Tataru | 6fd39e1 | 2019-07-04 10:59:07 +0100 | [diff] [blame] | 90 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 91 | @Stable |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 92 | fun Int.toDp(): Dp = (this / density).dp |
Calin Tataru | 6fd39e1 | 2019-07-04 10:59:07 +0100 | [diff] [blame] | 93 | |
| 94 | /** |
George Mount | 8f23757 | 2020-04-30 12:08:30 -0700 | [diff] [blame] | 95 | * Convert an [Int] pixel value to Sp. |
Calin Tataru | 6fd39e1 | 2019-07-04 10:59:07 +0100 | [diff] [blame] | 96 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 97 | @Stable |
Tyler Freeman | d1b43ca | 2023-08-10 17:28:22 +0100 | [diff] [blame] | 98 | fun Int.toSp(): TextUnit = toDp().toSp() |
Calin Tataru | 6fd39e1 | 2019-07-04 10:59:07 +0100 | [diff] [blame] | 99 | |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 100 | /** Convert a [Float] pixel value to a Dp */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 101 | @Stable |
Andrey Kulikov | 47f0e1a | 2020-01-28 13:52:46 +0000 | [diff] [blame] | 102 | fun Float.toDp(): Dp = (this / density).dp |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 103 | |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 104 | /** Convert a [Float] pixel value to a Sp */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 105 | @Stable |
Tyler Freeman | d1b43ca | 2023-08-10 17:28:22 +0100 | [diff] [blame] | 106 | fun Float.toSp(): TextUnit = toDp().toSp() |
Haoyu Zhang | 88398d4 | 2019-03-29 11:31:46 -0700 | [diff] [blame] | 107 | |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 108 | /** |
Doris Liu | 619be1f | 2021-02-02 21:45:17 -0800 | [diff] [blame] | 109 | * Convert a [DpRect] to a [Rect]. |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 110 | */ |
Leland Richardson | 47df77f | 2020-05-21 09:15:40 -0700 | [diff] [blame] | 111 | @Stable |
Doris Liu | 619be1f | 2021-02-02 21:45:17 -0800 | [diff] [blame] | 112 | fun DpRect.toRect(): Rect { |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 113 | return Rect( |
Nader Jawad | feb99f8 | 2020-05-21 13:07:36 -0700 | [diff] [blame] | 114 | left.toPx(), |
| 115 | top.toPx(), |
| 116 | right.toPx(), |
| 117 | bottom.toPx() |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 118 | ) |
| 119 | } |
George Mount | dae1d49 | 2021-07-23 22:52:24 +0000 | [diff] [blame] | 120 | |
| 121 | /** |
| 122 | * Convert a [DpSize] to a [Size]. |
| 123 | */ |
| 124 | @Stable |
Zach Klippenstein | fc18319 | 2021-10-04 23:31:05 -0700 | [diff] [blame] | 125 | fun DpSize.toSize(): Size = if (isSpecified) { |
| 126 | Size(width.toPx(), height.toPx()) |
| 127 | } else { |
| 128 | Size.Unspecified |
| 129 | } |
George Mount | dae1d49 | 2021-07-23 22:52:24 +0000 | [diff] [blame] | 130 | |
| 131 | /** |
| 132 | * Convert a [Size] to a [DpSize]. |
| 133 | */ |
| 134 | @Stable |
Zach Klippenstein | fc18319 | 2021-10-04 23:31:05 -0700 | [diff] [blame] | 135 | fun Size.toDpSize(): DpSize = if (isSpecified) { |
| 136 | DpSize(width.toDp(), height.toDp()) |
| 137 | } else { |
| 138 | DpSize.Unspecified |
| 139 | } |
Andrey Kulikov | 254d58c | 2019-03-06 12:57:26 +0000 | [diff] [blame] | 140 | } |