1use crate::Brush;
4use std::ops::AddAssign;
5
6#[derive(Clone, Copy, Debug, PartialEq, Default)]
7pub struct Point {
8 pub x: f32,
9 pub y: f32,
10}
11
12impl Point {
13 pub const fn new(x: f32, y: f32) -> Self {
14 Self { x, y }
15 }
16
17 pub const ZERO: Point = Point { x: 0.0, y: 0.0 };
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Default)]
21pub struct Size {
22 pub width: f32,
23 pub height: f32,
24}
25
26impl Size {
27 pub const fn new(width: f32, height: f32) -> Self {
28 Self { width, height }
29 }
30
31 pub const ZERO: Size = Size {
32 width: 0.0,
33 height: 0.0,
34 };
35}
36
37#[derive(Clone, Copy, Debug, PartialEq)]
38pub struct Rect {
39 pub x: f32,
40 pub y: f32,
41 pub width: f32,
42 pub height: f32,
43}
44
45impl Rect {
46 pub fn from_origin_size(origin: Point, size: Size) -> Self {
47 Self {
48 x: origin.x,
49 y: origin.y,
50 width: size.width,
51 height: size.height,
52 }
53 }
54
55 pub fn from_size(size: Size) -> Self {
56 Self {
57 x: 0.0,
58 y: 0.0,
59 width: size.width,
60 height: size.height,
61 }
62 }
63
64 pub fn translate(&self, dx: f32, dy: f32) -> Self {
65 Self {
66 x: self.x + dx,
67 y: self.y + dy,
68 width: self.width,
69 height: self.height,
70 }
71 }
72
73 pub fn contains(&self, x: f32, y: f32) -> bool {
74 x >= self.x && y >= self.y && x <= self.x + self.width && y <= self.y + self.height
75 }
76}
77
78#[derive(Clone, Copy, Debug, Default, PartialEq)]
80pub struct EdgeInsets {
81 pub left: f32,
82 pub top: f32,
83 pub right: f32,
84 pub bottom: f32,
85}
86
87impl EdgeInsets {
88 pub fn uniform(all: f32) -> Self {
89 Self {
90 left: all,
91 top: all,
92 right: all,
93 bottom: all,
94 }
95 }
96
97 pub fn horizontal(horizontal: f32) -> Self {
98 Self {
99 left: horizontal,
100 right: horizontal,
101 ..Self::default()
102 }
103 }
104
105 pub fn vertical(vertical: f32) -> Self {
106 Self {
107 top: vertical,
108 bottom: vertical,
109 ..Self::default()
110 }
111 }
112
113 pub fn symmetric(horizontal: f32, vertical: f32) -> Self {
114 Self {
115 left: horizontal,
116 right: horizontal,
117 top: vertical,
118 bottom: vertical,
119 }
120 }
121
122 pub fn from_components(left: f32, top: f32, right: f32, bottom: f32) -> Self {
123 Self {
124 left,
125 top,
126 right,
127 bottom,
128 }
129 }
130
131 pub fn is_zero(&self) -> bool {
132 self.left == 0.0 && self.top == 0.0 && self.right == 0.0 && self.bottom == 0.0
133 }
134
135 pub fn horizontal_sum(&self) -> f32 {
136 self.left + self.right
137 }
138
139 pub fn vertical_sum(&self) -> f32 {
140 self.top + self.bottom
141 }
142}
143
144impl AddAssign for EdgeInsets {
145 fn add_assign(&mut self, rhs: Self) {
146 self.left += rhs.left;
147 self.top += rhs.top;
148 self.right += rhs.right;
149 self.bottom += rhs.bottom;
150 }
151}
152
153#[derive(Clone, Copy, Debug, Default, PartialEq)]
154pub struct CornerRadii {
155 pub top_left: f32,
156 pub top_right: f32,
157 pub bottom_right: f32,
158 pub bottom_left: f32,
159}
160
161impl CornerRadii {
162 pub fn uniform(radius: f32) -> Self {
163 Self {
164 top_left: radius,
165 top_right: radius,
166 bottom_right: radius,
167 bottom_left: radius,
168 }
169 }
170}
171
172#[derive(Clone, Copy, Debug, PartialEq)]
173pub struct RoundedCornerShape {
174 radii: CornerRadii,
175}
176
177impl RoundedCornerShape {
178 pub fn new(top_left: f32, top_right: f32, bottom_right: f32, bottom_left: f32) -> Self {
179 Self {
180 radii: CornerRadii {
181 top_left,
182 top_right,
183 bottom_right,
184 bottom_left,
185 },
186 }
187 }
188
189 pub fn uniform(radius: f32) -> Self {
190 Self {
191 radii: CornerRadii::uniform(radius),
192 }
193 }
194
195 pub fn with_radii(radii: CornerRadii) -> Self {
196 Self { radii }
197 }
198
199 pub fn resolve(&self, width: f32, height: f32) -> CornerRadii {
200 let mut resolved = self.radii;
201 let max_width = (width / 2.0).max(0.0);
202 let max_height = (height / 2.0).max(0.0);
203 resolved.top_left = resolved.top_left.clamp(0.0, max_width).min(max_height);
204 resolved.top_right = resolved.top_right.clamp(0.0, max_width).min(max_height);
205 resolved.bottom_right = resolved.bottom_right.clamp(0.0, max_width).min(max_height);
206 resolved.bottom_left = resolved.bottom_left.clamp(0.0, max_width).min(max_height);
207 resolved
208 }
209
210 pub fn radii(&self) -> CornerRadii {
211 self.radii
212 }
213}
214
215#[derive(Clone, Copy, Debug, PartialEq)]
216pub struct GraphicsLayer {
217 pub alpha: f32,
218 pub scale: f32,
219 pub translation_x: f32,
220 pub translation_y: f32,
221}
222
223impl Default for GraphicsLayer {
224 fn default() -> Self {
225 Self {
226 alpha: 1.0,
227 scale: 1.0,
228 translation_x: 0.0,
229 translation_y: 0.0,
230 }
231 }
232}
233
234#[derive(Clone, Debug, PartialEq)]
235pub enum DrawPrimitive {
236 Rect {
237 rect: Rect,
238 brush: Brush,
239 },
240 RoundRect {
241 rect: Rect,
242 brush: Brush,
243 radii: CornerRadii,
244 },
245}
246
247pub trait DrawScope {
248 fn size(&self) -> Size;
249 fn draw_content(&self);
250 fn draw_rect(&mut self, brush: Brush);
251 fn draw_rect_at(&mut self, rect: Rect, brush: Brush);
253 fn draw_round_rect(&mut self, brush: Brush, radii: CornerRadii);
254 fn into_primitives(self) -> Vec<DrawPrimitive>;
255}
256
257#[derive(Default)]
258pub struct DrawScopeDefault {
259 size: Size,
260 primitives: Vec<DrawPrimitive>,
261}
262
263impl DrawScopeDefault {
264 pub fn new(size: Size) -> Self {
265 Self {
266 size,
267 primitives: Vec::new(),
268 }
269 }
270}
271
272impl DrawScope for DrawScopeDefault {
273 fn size(&self) -> Size {
274 self.size
275 }
276
277 fn draw_content(&self) {}
278
279 fn draw_rect(&mut self, brush: Brush) {
280 self.primitives.push(DrawPrimitive::Rect {
281 rect: Rect::from_size(self.size),
282 brush,
283 });
284 }
285
286 fn draw_rect_at(&mut self, rect: Rect, brush: Brush) {
287 self.primitives.push(DrawPrimitive::Rect { rect, brush });
288 }
289
290 fn draw_round_rect(&mut self, brush: Brush, radii: CornerRadii) {
291 self.primitives.push(DrawPrimitive::RoundRect {
292 rect: Rect::from_size(self.size),
293 brush,
294 radii,
295 });
296 }
297
298 fn into_primitives(self) -> Vec<DrawPrimitive> {
299 self.primitives
300 }
301}