1use bytemuck::{Pod, Zeroable};
2use core::fmt::Debug;
3use derive_more::{Add, AddAssign, Div, Mul, Sub, SubAssign};
4use refineable::Refineable;
5use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
6
7#[derive(
8 Refineable, Default, Add, AddAssign, Sub, SubAssign, Mul, Div, Copy, Debug, PartialEq, Eq, Hash,
9)]
10#[refineable(debug)]
11#[repr(C)]
12pub struct Point<T: Clone + Debug> {
13 pub x: T,
14 pub y: T,
15}
16
17pub fn point<T: Clone + Debug>(x: T, y: T) -> Point<T> {
18 Point { x, y }
19}
20
21impl<T: Clone + Debug> Point<T> {
22 pub fn new(x: T, y: T) -> Self {
23 Self { x, y }
24 }
25
26 pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Point<U> {
27 Point {
28 x: f(self.x.clone()),
29 y: f(self.y.clone()),
30 }
31 }
32}
33
34impl<T: Clone + Debug + Sub<Output = T>> SubAssign<Size<T>> for Point<T> {
35 fn sub_assign(&mut self, rhs: Size<T>) {
36 self.x = self.x.clone() - rhs.width;
37 self.y = self.y.clone() - rhs.height;
38 }
39}
40
41impl<T: Clone + Debug + Add<Output = T> + Copy> AddAssign<T> for Point<T> {
42 fn add_assign(&mut self, rhs: T) {
43 self.x = self.x.clone() + rhs;
44 self.y = self.y.clone() + rhs;
45 }
46}
47
48impl<T: Clone + Debug + std::cmp::PartialOrd> Point<T> {
49 pub fn max(&self, other: &Self) -> Self {
50 Point {
51 x: if self.x >= other.x {
52 self.x.clone()
53 } else {
54 other.x.clone()
55 },
56 y: if self.y >= other.y {
57 self.y.clone()
58 } else {
59 other.y.clone()
60 },
61 }
62 }
63}
64
65impl<T: Clone + Debug> Clone for Point<T> {
66 fn clone(&self) -> Self {
67 Self {
68 x: self.x.clone(),
69 y: self.y.clone(),
70 }
71 }
72}
73
74unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Point<T> {}
75unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Point<T> {}
76
77#[derive(Refineable, Default, Clone, Copy, Debug, PartialEq)]
78#[refineable(debug)]
79#[repr(C)]
80pub struct Size<T: Clone + Debug> {
81 pub width: T,
82 pub height: T,
83}
84
85unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Size<T> {}
86unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Size<T> {}
87
88pub fn size<T: Clone + Debug>(width: T, height: T) -> Size<T> {
89 Size { width, height }
90}
91
92impl<T: Clone + Debug> Size<T> {
93 pub fn map<U: Clone + Debug, F: Fn(T) -> U>(&self, f: F) -> Size<U> {
94 Size {
95 width: f(self.width.clone()),
96 height: f(self.height.clone()),
97 }
98 }
99}
100
101impl From<Size<Option<Pixels>>> for Size<Option<f32>> {
102 fn from(val: Size<Option<Pixels>>) -> Self {
103 Size {
104 width: val.width.map(|p| p.0 as f32),
105 height: val.height.map(|p| p.0 as f32),
106 }
107 }
108}
109
110impl Size<Length> {
111 pub fn full() -> Self {
112 Self {
113 width: relative(1.).into(),
114 height: relative(1.).into(),
115 }
116 }
117}
118
119impl Size<DefiniteLength> {
120 pub fn zero() -> Self {
121 Self {
122 width: px(0.).into(),
123 height: px(0.).into(),
124 }
125 }
126}
127
128impl Size<Length> {
129 pub fn auto() -> Self {
130 Self {
131 width: Length::Auto,
132 height: Length::Auto,
133 }
134 }
135}
136
137#[derive(Refineable, Clone, Default, Debug, PartialEq)]
138#[refineable(debug)]
139#[repr(C)]
140pub struct Bounds<T: Clone + Debug> {
141 pub origin: Point<T>,
142 pub size: Size<T>,
143}
144
145unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Bounds<T> {}
146unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Bounds<T> {}
147
148impl<T: Clone + Debug + Copy + Add<T, Output = T>> Bounds<T> {
149 pub fn upper_right(&self) -> Point<T> {
150 Point {
151 x: self.origin.x + self.size.width,
152 y: self.origin.y,
153 }
154 }
155
156 pub fn lower_right(&self) -> Point<T> {
157 Point {
158 x: self.origin.x + self.size.width,
159 y: self.origin.y + self.size.height,
160 }
161 }
162}
163
164impl<T: Clone + Debug + Copy + PartialOrd + Add<T, Output = T>> Bounds<T> {
165 pub fn contains_point(&self, point: Point<T>) -> bool {
166 point.x >= self.origin.x
167 && point.x <= self.origin.x + self.size.width
168 && point.y >= self.origin.y
169 && point.y <= self.origin.y + self.size.height
170 }
171}
172
173impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
174
175#[derive(Refineable, Clone, Default, Debug)]
176#[refineable(debug)]
177#[repr(C)]
178pub struct Edges<T: Clone + Debug> {
179 pub top: T,
180 pub right: T,
181 pub bottom: T,
182 pub left: T,
183}
184
185impl<T: Clone + Debug + Copy> Copy for Edges<T> {}
186
187unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Edges<T> {}
188
189unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Edges<T> {}
190
191impl Edges<Length> {
192 pub fn auto() -> Self {
193 Self {
194 top: Length::Auto,
195 right: Length::Auto,
196 bottom: Length::Auto,
197 left: Length::Auto,
198 }
199 }
200
201 pub fn zero() -> Self {
202 Self {
203 top: px(0.).into(),
204 right: px(0.).into(),
205 bottom: px(0.).into(),
206 left: px(0.).into(),
207 }
208 }
209}
210
211impl Edges<DefiniteLength> {
212 pub fn zero() -> Self {
213 Self {
214 top: px(0.).into(),
215 right: px(0.).into(),
216 bottom: px(0.).into(),
217 left: px(0.).into(),
218 }
219 }
220}
221
222impl Edges<AbsoluteLength> {
223 pub fn zero() -> Self {
224 Self {
225 top: px(0.).into(),
226 right: px(0.).into(),
227 bottom: px(0.).into(),
228 left: px(0.).into(),
229 }
230 }
231
232 pub fn to_pixels(&self, rem_size: Pixels) -> Edges<Pixels> {
233 Edges {
234 top: self.top.to_pixels(rem_size),
235 right: self.right.to_pixels(rem_size),
236 bottom: self.bottom.to_pixels(rem_size),
237 left: self.left.to_pixels(rem_size),
238 }
239 }
240}
241
242impl Edges<Pixels> {
243 pub fn is_empty(&self) -> bool {
244 self.top == px(0.) && self.right == px(0.) && self.bottom == px(0.) && self.left == px(0.)
245 }
246}
247
248#[derive(Refineable, Clone, Default, Debug)]
249#[refineable(debug)]
250#[repr(C)]
251pub struct Corners<T: Clone + Debug> {
252 pub top_left: T,
253 pub top_right: T,
254 pub bottom_right: T,
255 pub bottom_left: T,
256}
257
258impl<T: Clone + Debug + Copy> Copy for Corners<T> {}
259
260unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Corners<T> {}
261
262unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Corners<T> {}
263
264#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
265#[repr(transparent)]
266pub struct Pixels(pub(crate) f32);
267
268#[derive(
269 Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd,
270)]
271#[repr(transparent)]
272pub struct DevicePixels(pub(crate) u32);
273
274impl From<DevicePixels> for u32 {
275 fn from(device_pixels: DevicePixels) -> Self {
276 device_pixels.0
277 }
278}
279
280impl Pixels {
281 pub fn round(&self) -> Self {
282 Self(self.0.round())
283 }
284
285 pub fn to_device_pixels(&self, scale: f32) -> DevicePixels {
286 DevicePixels((self.0 * scale).ceil() as u32)
287 }
288}
289
290impl Mul<f32> for Pixels {
291 type Output = Pixels;
292
293 fn mul(self, other: f32) -> Pixels {
294 Pixels(self.0 * other)
295 }
296}
297
298impl Mul<Pixels> for Pixels {
299 type Output = Pixels;
300
301 fn mul(self, rhs: Pixels) -> Self::Output {
302 Pixels(self.0 * rhs.0)
303 }
304}
305
306impl Eq for Pixels {}
307
308impl Ord for Pixels {
309 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
310 self.0.partial_cmp(&other.0).unwrap()
311 }
312}
313
314impl std::hash::Hash for Pixels {
315 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
316 self.0.to_bits().hash(state);
317 }
318}
319
320impl From<f64> for Pixels {
321 fn from(val: f64) -> Self {
322 Pixels(val as f32)
323 }
324}
325
326impl From<f32> for Pixels {
327 fn from(val: f32) -> Self {
328 Pixels(val)
329 }
330}
331
332unsafe impl bytemuck::Pod for Pixels {}
333unsafe impl bytemuck::Zeroable for Pixels {}
334
335impl Debug for Pixels {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337 write!(f, "{} px", self.0)
338 }
339}
340
341impl From<Pixels> for f32 {
342 fn from(pixels: Pixels) -> Self {
343 pixels.0
344 }
345}
346
347impl From<&Pixels> for f32 {
348 fn from(pixels: &Pixels) -> Self {
349 pixels.0
350 }
351}
352
353impl From<Pixels> for f64 {
354 fn from(pixels: Pixels) -> Self {
355 pixels.0 as f64
356 }
357}
358
359#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)]
360pub struct Rems(f32);
361
362impl Mul<Pixels> for Rems {
363 type Output = Pixels;
364
365 fn mul(self, other: Pixels) -> Pixels {
366 Pixels(self.0 * other.0)
367 }
368}
369
370impl Debug for Rems {
371 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
372 write!(f, "{} rem", self.0)
373 }
374}
375
376#[derive(Clone, Copy, Debug)]
377pub enum AbsoluteLength {
378 Pixels(Pixels),
379 Rems(Rems),
380}
381
382impl From<Pixels> for AbsoluteLength {
383 fn from(pixels: Pixels) -> Self {
384 AbsoluteLength::Pixels(pixels)
385 }
386}
387
388impl From<Rems> for AbsoluteLength {
389 fn from(rems: Rems) -> Self {
390 AbsoluteLength::Rems(rems)
391 }
392}
393
394impl AbsoluteLength {
395 pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
396 match self {
397 AbsoluteLength::Pixels(pixels) => *pixels,
398 AbsoluteLength::Rems(rems) => *rems * rem_size,
399 }
400 }
401}
402
403impl Default for AbsoluteLength {
404 fn default() -> Self {
405 px(0.).into()
406 }
407}
408
409/// A non-auto length that can be defined in pixels, rems, or percent of parent.
410#[derive(Clone, Copy)]
411pub enum DefiniteLength {
412 Absolute(AbsoluteLength),
413 /// A fraction of the parent's size between 0 and 1.
414 Fraction(f32),
415}
416
417impl Debug for DefiniteLength {
418 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419 match self {
420 DefiniteLength::Absolute(length) => Debug::fmt(length, f),
421 DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32),
422 }
423 }
424}
425
426impl From<Pixels> for DefiniteLength {
427 fn from(pixels: Pixels) -> Self {
428 Self::Absolute(pixels.into())
429 }
430}
431
432impl From<Rems> for DefiniteLength {
433 fn from(rems: Rems) -> Self {
434 Self::Absolute(rems.into())
435 }
436}
437
438impl From<AbsoluteLength> for DefiniteLength {
439 fn from(length: AbsoluteLength) -> Self {
440 Self::Absolute(length)
441 }
442}
443
444impl Default for DefiniteLength {
445 fn default() -> Self {
446 Self::Absolute(AbsoluteLength::default())
447 }
448}
449
450/// A length that can be defined in pixels, rems, percent of parent, or auto.
451#[derive(Clone, Copy)]
452pub enum Length {
453 Definite(DefiniteLength),
454 Auto,
455}
456
457impl Debug for Length {
458 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459 match self {
460 Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
461 Length::Auto => write!(f, "auto"),
462 }
463 }
464}
465
466pub fn relative(fraction: f32) -> DefiniteLength {
467 DefiniteLength::Fraction(fraction).into()
468}
469
470pub fn rems(rems: f32) -> Rems {
471 Rems(rems)
472}
473
474pub fn px(pixels: f32) -> Pixels {
475 Pixels(pixels)
476}
477
478pub fn auto() -> Length {
479 Length::Auto
480}
481
482impl From<Pixels> for Length {
483 fn from(pixels: Pixels) -> Self {
484 Self::Definite(pixels.into())
485 }
486}
487
488impl From<Rems> for Length {
489 fn from(rems: Rems) -> Self {
490 Self::Definite(rems.into())
491 }
492}
493
494impl From<DefiniteLength> for Length {
495 fn from(length: DefiniteLength) -> Self {
496 Self::Definite(length)
497 }
498}
499
500impl From<AbsoluteLength> for Length {
501 fn from(length: AbsoluteLength) -> Self {
502 Self::Definite(length.into())
503 }
504}
505
506impl Default for Length {
507 fn default() -> Self {
508 Self::Definite(DefiniteLength::default())
509 }
510}
511
512impl From<()> for Length {
513 fn from(_: ()) -> Self {
514 Self::Definite(DefiniteLength::default())
515 }
516}