zng_unit/
corner_radius.rs
1use std::{cmp, fmt, ops};
2
3use serde::{Deserialize, Serialize};
4
5use crate::SideOffsets2D;
6
7#[derive(Serialize, Deserialize)]
9#[serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>"))]
10pub struct CornerRadius2D<T, U> {
11 pub top_left: euclid::Size2D<T, U>,
13 pub top_right: euclid::Size2D<T, U>,
15 pub bottom_right: euclid::Size2D<T, U>,
17 pub bottom_left: euclid::Size2D<T, U>,
19}
20impl<T: Default, U> Default for CornerRadius2D<T, U> {
21 fn default() -> Self {
22 Self {
23 top_left: Default::default(),
24 top_right: Default::default(),
25 bottom_right: Default::default(),
26 bottom_left: Default::default(),
27 }
28 }
29}
30impl<T: Clone, U> Clone for CornerRadius2D<T, U> {
31 fn clone(&self) -> Self {
32 Self {
33 top_left: self.top_left.clone(),
34 top_right: self.top_right.clone(),
35 bottom_right: self.bottom_right.clone(),
36 bottom_left: self.bottom_left.clone(),
37 }
38 }
39}
40impl<T: Copy, U> Copy for CornerRadius2D<T, U> {}
41impl<T: Copy + num_traits::Zero, U> CornerRadius2D<T, U> {
42 pub fn new(
44 top_left: euclid::Size2D<T, U>,
45 top_right: euclid::Size2D<T, U>,
46 bottom_right: euclid::Size2D<T, U>,
47 bottom_left: euclid::Size2D<T, U>,
48 ) -> Self {
49 Self {
50 top_left,
51 top_right,
52 bottom_right,
53 bottom_left,
54 }
55 }
56
57 pub fn new_all(radius: euclid::Size2D<T, U>) -> Self {
59 Self::new(radius, radius, radius, radius)
60 }
61
62 pub fn zero() -> Self {
64 Self::new_all(euclid::Size2D::zero())
65 }
66
67 pub fn inflate(self, offsets: SideOffsets2D<T, U>) -> Self
69 where
70 T: ops::AddAssign,
71 {
72 let mut r = self;
73
74 r.top_left.width += offsets.left;
75 r.top_left.height += offsets.top;
76
77 r.top_right.width += offsets.right;
78 r.top_right.height += offsets.top;
79
80 r.bottom_right.width += offsets.right;
81 r.bottom_right.height += offsets.bottom;
82
83 r.bottom_left.width += offsets.left;
84 r.bottom_left.height += offsets.bottom;
85
86 r
87 }
88
89 pub fn deflate(self, offsets: SideOffsets2D<T, U>) -> Self
91 where
92 T: ops::SubAssign + cmp::PartialOrd,
93 {
94 let mut r = self;
95
96 if r.top_left.width >= offsets.left {
97 r.top_left.width -= offsets.left;
98 } else {
99 r.top_left.width = T::zero();
100 }
101 if r.top_left.height >= offsets.top {
102 r.top_left.height -= offsets.top;
103 } else {
104 r.top_left.height = T::zero();
105 }
106
107 if r.top_right.width >= offsets.right {
108 r.top_right.width -= offsets.right;
109 } else {
110 r.top_right.width = T::zero();
111 }
112 if r.top_right.height >= offsets.top {
113 r.top_right.height -= offsets.top;
114 } else {
115 r.top_right.height = T::zero();
116 }
117
118 if r.bottom_right.width >= offsets.right {
119 r.bottom_right.width -= offsets.right;
120 } else {
121 r.bottom_right.width = T::zero();
122 }
123 if r.bottom_right.height >= offsets.bottom {
124 r.bottom_right.height -= offsets.bottom;
125 } else {
126 r.bottom_right.height = T::zero();
127 }
128
129 if r.bottom_left.width >= offsets.left {
130 r.bottom_left.width -= offsets.left;
131 } else {
132 r.bottom_left.width = T::zero();
133 }
134 if r.bottom_left.height >= offsets.bottom {
135 r.bottom_left.height -= offsets.bottom;
136 } else {
137 r.bottom_left.height = T::zero();
138 }
139
140 r
141 }
142}
143impl<T: fmt::Debug, U> fmt::Debug for CornerRadius2D<T, U> {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 f.debug_struct("CornerRadius2D")
146 .field("top_left", &self.top_left)
147 .field("top_right", &self.top_right)
148 .field("bottom_right", &self.bottom_right)
149 .field("bottom_left", &self.bottom_left)
150 .finish()
151 }
152}
153impl<T: PartialEq, U> PartialEq for CornerRadius2D<T, U> {
154 fn eq(&self, other: &Self) -> bool {
155 self.top_left == other.top_left
156 && self.top_right == other.top_right
157 && self.bottom_right == other.bottom_right
158 && self.bottom_left == other.bottom_left
159 }
160}
161impl<T: Eq, U> Eq for CornerRadius2D<T, U> {}