Skip to main content

widgetkit_render/
model.rs

1use crate::{Stroke, TextStyle};
2use widgetkit_core::{Color, Point, Rect, Size};
3
4#[derive(Clone, Debug, PartialEq)]
5pub struct RenderFrame {
6    size: Size,
7    commands: Vec<RenderCommand>,
8}
9
10impl RenderFrame {
11    pub fn new(size: Size, commands: Vec<RenderCommand>) -> Self {
12        Self { size, commands }
13    }
14
15    pub fn size(&self) -> Size {
16        self.size
17    }
18
19    pub fn commands(&self) -> &[RenderCommand] {
20        &self.commands
21    }
22
23    pub fn into_commands(self) -> Vec<RenderCommand> {
24        self.commands
25    }
26
27    pub(crate) fn from_list(size: Size, commands: CommandList) -> Self {
28        Self::new(size, commands.into_commands())
29    }
30
31    pub(crate) fn into_parts(self) -> (Size, Vec<RenderCommand>) {
32        (self.size, self.commands)
33    }
34}
35
36#[derive(Clone, Debug, Default, PartialEq)]
37pub(crate) struct CommandList {
38    commands: Vec<RenderCommand>,
39}
40
41impl CommandList {
42    pub(crate) fn new() -> Self {
43        Self::default()
44    }
45
46    pub(crate) fn push(&mut self, command: RenderCommand) {
47        self.commands.push(command);
48    }
49
50    pub(crate) fn into_commands(self) -> Vec<RenderCommand> {
51        self.commands
52    }
53}
54
55#[derive(Clone, Debug, PartialEq)]
56pub enum RenderCommand {
57    Clear(ClearCommand),
58    Fill(FillCommand),
59    Stroke(StrokeCommand),
60    Text(TextCommand),
61    Image(ImageCommand),
62    Clip(ClipCommand),
63    Transform(TransformCommand),
64    State(StateCommand),
65}
66
67#[derive(Clone, Copy, Debug, PartialEq)]
68pub struct Paint {
69    pub color: Color,
70}
71
72impl Paint {
73    pub const fn solid(color: Color) -> Self {
74        Self { color }
75    }
76}
77
78#[derive(Clone, Copy, Debug, PartialEq)]
79pub struct ClearCommand {
80    pub paint: Paint,
81}
82
83#[derive(Clone, Copy, Debug, PartialEq)]
84pub struct Fill {
85    pub paint: Paint,
86}
87
88impl Fill {
89    pub const fn solid(color: Color) -> Self {
90        Self {
91            paint: Paint::solid(color),
92        }
93    }
94}
95
96#[derive(Clone, Copy, Debug, PartialEq)]
97pub struct FillCommand {
98    pub shape: FillShape,
99    pub fill: Fill,
100}
101
102#[derive(Clone, Copy, Debug, PartialEq)]
103pub enum FillShape {
104    Rect(Rect),
105    RoundRect {
106        rect: Rect,
107        radius: f32,
108    },
109    Circle {
110        center: Point,
111        radius: f32,
112    },
113    Ellipse {
114        center: Point,
115        radius_x: f32,
116        radius_y: f32,
117    },
118}
119
120#[derive(Clone, Copy, Debug, PartialEq)]
121pub struct StrokeCommand {
122    pub shape: StrokeShape,
123    pub stroke: Stroke,
124    pub paint: Paint,
125}
126
127#[derive(Clone, Copy, Debug, PartialEq)]
128pub enum StrokeShape {
129    Line { start: Point, end: Point },
130}
131
132#[derive(Clone, Debug, PartialEq)]
133pub struct TextCommand {
134    pub position: Point,
135    pub text: String,
136    pub style: TextStyle,
137    pub paint: Paint,
138}
139
140#[derive(Clone, Copy, Debug, PartialEq)]
141pub struct ImageCommand {
142    pub rect: Rect,
143    pub source: ImageSource,
144    pub paint: Paint,
145}
146
147#[derive(Clone, Copy, Debug, PartialEq)]
148pub enum ImageSource {
149    Placeholder,
150}
151
152#[derive(Clone, Copy, Debug, PartialEq)]
153pub struct ClipCommand {
154    pub primitive: ClipPrimitive,
155}
156
157#[derive(Clone, Copy, Debug, PartialEq)]
158pub enum ClipPrimitive {
159    Rect(Rect),
160}
161
162#[derive(Clone, Copy, Debug, Default, PartialEq)]
163pub struct Transform {
164    pub translate_x: f32,
165    pub translate_y: f32,
166}
167
168impl Transform {
169    pub const fn translation(x: f32, y: f32) -> Self {
170        Self {
171            translate_x: x,
172            translate_y: y,
173        }
174    }
175
176    pub(crate) fn then(self, next: Self) -> Self {
177        Self {
178            translate_x: self.translate_x + next.translate_x,
179            translate_y: self.translate_y + next.translate_y,
180        }
181    }
182
183    pub(crate) fn map_point(self, point: Point) -> Point {
184        Point::new(point.x + self.translate_x, point.y + self.translate_y)
185    }
186
187    pub(crate) fn map_rect(self, rect: Rect) -> Rect {
188        Rect::xywh(
189            rect.x() + self.translate_x,
190            rect.y() + self.translate_y,
191            rect.width(),
192            rect.height(),
193        )
194    }
195}
196
197#[derive(Clone, Copy, Debug, PartialEq)]
198pub struct TransformCommand {
199    pub transform: Transform,
200}
201
202#[derive(Clone, Copy, Debug, PartialEq, Eq)]
203pub enum StateCommand {
204    Save,
205    Restore,
206}
207
208// TODO(v0.3): layout-aware text measurement hooks
209// TODO(v0.4): input-related hit-test helpers for shapes
210// TODO(v0.5): ensure command model is sufficient for declarative layer