Skip to main content

i_slint_core/
lengths.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use crate::BorderRadius;
5use crate::Coord;
6/// This type is used as a tagging type for use with [`euclid::Scale`] to convert
7/// between physical and logical pixels.
8pub struct PhysicalPx;
9
10/// This type is used as a tagging type for use with [`euclid::Scale`] to convert
11/// between physical and logical pixels.
12pub struct LogicalPx;
13pub type LogicalLength = euclid::Length<Coord, LogicalPx>;
14pub type LogicalRect = euclid::Rect<Coord, LogicalPx>;
15pub type LogicalPoint = euclid::Point2D<Coord, LogicalPx>;
16pub type LogicalSize = euclid::Size2D<Coord, LogicalPx>;
17pub type LogicalVector = euclid::Vector2D<Coord, LogicalPx>;
18pub type LogicalBorderRadius = BorderRadius<Coord, LogicalPx>;
19pub type ItemTransform = euclid::Transform2D<f32, LogicalPx, LogicalPx>;
20
21pub type ScaleFactor = euclid::Scale<f32, LogicalPx, PhysicalPx>;
22
23pub trait SizeLengths {
24    type LengthType;
25    fn width_length(&self) -> Self::LengthType;
26    fn height_length(&self) -> Self::LengthType;
27}
28
29impl<T: Copy, U> SizeLengths for euclid::Size2D<T, U> {
30    type LengthType = euclid::Length<T, U>;
31    fn width_length(&self) -> Self::LengthType {
32        euclid::Length::new(self.width)
33    }
34    fn height_length(&self) -> Self::LengthType {
35        euclid::Length::new(self.height)
36    }
37}
38
39pub trait PointLengths {
40    type LengthType;
41    fn x_length(&self) -> Self::LengthType;
42    fn y_length(&self) -> Self::LengthType;
43}
44
45impl<T: Copy, U> PointLengths for euclid::Point2D<T, U> {
46    type LengthType = euclid::Length<T, U>;
47    fn x_length(&self) -> Self::LengthType {
48        euclid::Length::new(self.x)
49    }
50    fn y_length(&self) -> Self::LengthType {
51        euclid::Length::new(self.y)
52    }
53}
54
55impl<T: Copy, U> PointLengths for euclid::Vector2D<T, U> {
56    type LengthType = euclid::Length<T, U>;
57    fn x_length(&self) -> Self::LengthType {
58        euclid::Length::new(self.x)
59    }
60    fn y_length(&self) -> Self::LengthType {
61        euclid::Length::new(self.y)
62    }
63}
64
65pub trait RectLengths {
66    type SizeType;
67    type LengthType;
68    fn size_length(&self) -> Self::SizeType;
69    fn width_length(&self) -> Self::LengthType;
70    fn height_length(&self) -> Self::LengthType;
71}
72
73impl<T: Copy, U> RectLengths for euclid::Rect<T, U> {
74    type LengthType = euclid::Length<T, U>;
75    type SizeType = euclid::Size2D<T, U>;
76    fn size_length(&self) -> Self::SizeType {
77        euclid::Size2D::new(self.size.width, self.size.height)
78    }
79    fn width_length(&self) -> Self::LengthType {
80        self.size_length().width_length()
81    }
82    fn height_length(&self) -> Self::LengthType {
83        self.size_length().height_length()
84    }
85}
86
87/// Convert from the api size to the internal size
88/// (This doesn't use the `From` trait because it would expose the conversion to euclid in the public API)
89pub fn logical_size_from_api(size: crate::api::LogicalSize) -> LogicalSize {
90    size.to_euclid()
91}
92
93pub fn logical_point_from_api(position: crate::api::LogicalPosition) -> LogicalPoint {
94    position.to_euclid()
95}
96
97pub fn logical_position_to_api(pos: LogicalPoint) -> crate::api::LogicalPosition {
98    crate::api::LogicalPosition::from_euclid(pos)
99}
100
101pub fn logical_size_to_api(size: LogicalSize) -> crate::api::LogicalSize {
102    crate::api::LogicalSize::from_euclid(size)
103}
104
105/// Four distances from the edges of a rectangle represented in the coordinate space of logical pixels.
106#[derive(Debug, Default, Copy, Clone, PartialEq)]
107#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108#[repr(C)]
109pub struct LogicalEdges {
110    /// The top distance in logical pixels.
111    pub top: f32,
112    /// The bottom distance in logical pixels.
113    pub bottom: f32,
114    /// The left distance in logical pixels.
115    pub left: f32,
116    /// The right distance in logical pixels.
117    pub right: f32,
118}
119
120impl LogicalEdges {
121    /// Construct a new logical edges struct from the given border values, that are assumed to be
122    /// in the logical coordinate space.
123    pub const fn new(top: f32, bottom: f32, left: f32, right: f32) -> Self {
124        Self { top, bottom, left, right }
125    }
126
127    /// Converts the top edge to logical pixels.
128    #[inline]
129    pub const fn top(&self) -> LogicalLength {
130        LogicalLength::new(self.top as crate::Coord)
131    }
132    /// Converts the bottom edge to logical pixels.
133    #[inline]
134    pub const fn bottom(&self) -> LogicalLength {
135        LogicalLength::new(self.bottom as crate::Coord)
136    }
137    /// Converts the left edge to logical pixels.
138    #[inline]
139    pub const fn left(&self) -> LogicalLength {
140        LogicalLength::new(self.left as crate::Coord)
141    }
142    /// Converts the right edge to logical pixels.
143    #[inline]
144    pub const fn right(&self) -> LogicalLength {
145        LogicalLength::new(self.right as crate::Coord)
146    }
147}
148
149/// Four distances from the edges of a rectangle represented in the coordinate space of physical pixels.
150#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
152pub struct PhysicalEdges {
153    /// The top edge in physical pixels.
154    pub top: i32,
155    /// The bottom edge in physical pixels.
156    pub bottom: i32,
157    /// The left edge in physical pixels.
158    pub left: i32,
159    /// The right edge in physical pixels.
160    pub right: i32,
161}
162
163impl PhysicalEdges {
164    /// Construct a new physical edges struct from the given border values, that are assumed to be
165    /// in the physical coordinate space.
166    pub const fn new(top: i32, bottom: i32, left: i32, right: i32) -> Self {
167        Self { top, bottom, left, right }
168    }
169
170    /// Convert a given logical edges to a physical edges by dividing the lengths by the
171    /// specified scale factor.
172    #[inline]
173    pub const fn to_logical(&self, scale_factor: f32) -> LogicalEdges {
174        LogicalEdges::new(
175            self.top_to_logical(scale_factor).0 as f32,
176            self.bottom_to_logical(scale_factor).0 as f32,
177            self.left_to_logical(scale_factor).0 as f32,
178            self.right_to_logical(scale_factor).0 as f32,
179        )
180    }
181
182    /// Convert the top logical edge to a physical edge by dividing the length by the
183    /// specified scale factor.
184    #[inline]
185    pub const fn top_to_logical(&self, scale_factor: f32) -> LogicalLength {
186        LogicalLength::new((self.top as f32 / scale_factor) as crate::Coord)
187    }
188
189    /// Convert the bottom logical edge to a physical edge by dividing the length by the
190    /// specified scale factor.
191    #[inline]
192    pub const fn bottom_to_logical(&self, scale_factor: f32) -> LogicalLength {
193        LogicalLength::new((self.bottom as f32 / scale_factor) as crate::Coord)
194    }
195
196    #[inline]
197    /// Convert the left logical edge to a physical edge by dividing the length by the
198    /// specified scale factor.
199    pub const fn left_to_logical(&self, scale_factor: f32) -> LogicalLength {
200        LogicalLength::new((self.left as f32 / scale_factor) as crate::Coord)
201    }
202
203    /// Convert the right logical edge to a physical edge by dividing the length by the
204    /// specified scale factor.
205    #[inline]
206    pub const fn right_to_logical(&self, scale_factor: f32) -> LogicalLength {
207        LogicalLength::new((self.right as f32 / scale_factor) as crate::Coord)
208    }
209}