1use std::rc::Rc;
2
3use cranpose_core::NodeId;
4pub use cranpose_render_common::graph_scene::{HitRegion, Scene};
5use cranpose_ui::{TextLayoutOptions, TextStyle};
6use cranpose_ui_graphics::{
7 ArcGeometry, BlendMode, Brush, Color, ColorFilter, ImageBitmap, ImageSampling, Point, Rect,
8 RoundedCornerShape, Stroke,
9};
10
11#[derive(Clone)]
12pub(crate) struct DrawShape {
13 pub rect: Rect,
14 pub snap_anchor: Option<Point>,
15 pub snap_to_pixel_grid: bool,
16 pub brush: Brush,
17 pub shape: Option<RoundedCornerShape>,
18 pub stroke: Option<Stroke>,
19 pub arc: Option<ArcGeometry>,
20 pub z_index: usize,
21 pub clip: Option<Rect>,
22 pub blend_mode: BlendMode,
23}
24
25#[derive(Clone)]
26pub(crate) struct TextDraw {
27 pub node_id: NodeId,
28 pub rect: Rect,
29 pub snap_anchor: Option<Point>,
30 pub text: Rc<cranpose_ui::text::AnnotatedString>,
31 pub color: Color,
32 pub text_style: TextStyle,
33 pub font_size: f32,
34 pub scale: f32,
35 pub layout_options: TextLayoutOptions,
36 pub z_index: usize,
37 pub clip: Option<Rect>,
38}
39
40#[derive(Clone)]
41pub(crate) struct ImageDraw {
42 pub rect: Rect,
43 pub snap_anchor: Option<Point>,
44 pub image: ImageBitmap,
45 pub alpha: f32,
46 pub color_filter: Option<ColorFilter>,
47 pub sampling: ImageSampling,
48 pub z_index: usize,
49 pub clip: Option<Rect>,
50 pub blend_mode: BlendMode,
51 pub src_rect: Option<Rect>,
52}
53
54pub(crate) struct RasterScene {
55 pub shapes: Vec<DrawShape>,
56 pub images: Vec<ImageDraw>,
57 pub texts: Vec<TextDraw>,
58 pub next_z: usize,
59}
60
61impl RasterScene {
62 pub fn new() -> Self {
63 Self {
64 shapes: Vec::new(),
65 images: Vec::new(),
66 texts: Vec::new(),
67 next_z: 0,
68 }
69 }
70
71 pub fn push_shape(
72 &mut self,
73 rect: Rect,
74 brush: Brush,
75 shape: Option<RoundedCornerShape>,
76 clip: Option<Rect>,
77 blend_mode: BlendMode,
78 ) {
79 let z_index = self.next_z;
80 self.next_z += 1;
81 self.shapes.push(DrawShape {
82 rect,
83 snap_anchor: None,
84 snap_to_pixel_grid: false,
85 brush,
86 shape,
87 stroke: None,
88 arc: None,
89 z_index,
90 clip,
91 blend_mode,
92 });
93 }
94
95 pub fn push_pixel_snapped_shape(
96 &mut self,
97 rect: Rect,
98 brush: Brush,
99 shape: Option<RoundedCornerShape>,
100 clip: Option<Rect>,
101 blend_mode: BlendMode,
102 ) {
103 let z_index = self.next_z;
104 self.next_z += 1;
105 self.shapes.push(DrawShape {
106 rect,
107 snap_anchor: None,
108 snap_to_pixel_grid: true,
109 brush,
110 shape,
111 stroke: None,
112 arc: None,
113 z_index,
114 clip,
115 blend_mode,
116 });
117 }
118
119 #[expect(clippy::too_many_arguments)]
120 pub fn push_shape_with_stroke_and_arc(
121 &mut self,
122 rect: Rect,
123 brush: Brush,
124 shape: Option<RoundedCornerShape>,
125 stroke: Option<Stroke>,
126 arc: Option<ArcGeometry>,
127 clip: Option<Rect>,
128 blend_mode: BlendMode,
129 ) {
130 let z_index = self.next_z;
131 self.next_z += 1;
132 self.shapes.push(DrawShape {
133 rect,
134 snap_anchor: None,
135 snap_to_pixel_grid: false,
136 brush,
137 shape,
138 stroke,
139 arc,
140 z_index,
141 clip,
142 blend_mode,
143 });
144 }
145
146 #[expect(clippy::too_many_arguments)]
147 pub fn push_image_with_geometry(
148 &mut self,
149 rect: Rect,
150 _local_rect: Rect,
151 _quad: [[f32; 2]; 4],
152 image: ImageBitmap,
153 alpha: f32,
154 color_filter: Option<ColorFilter>,
155 sampling: ImageSampling,
156 clip: Option<Rect>,
157 src_rect: Option<Rect>,
158 blend_mode: BlendMode,
159 ) {
160 let z_index = self.next_z;
161 self.next_z += 1;
162 self.images.push(ImageDraw {
163 rect,
164 snap_anchor: None,
165 image,
166 alpha: alpha.clamp(0.0, 1.0),
167 color_filter,
168 sampling,
169 z_index,
170 clip,
171 blend_mode,
172 src_rect,
173 });
174 }
175
176 #[expect(clippy::too_many_arguments)]
177 pub fn push_text(
178 &mut self,
179 node_id: NodeId,
180 rect: Rect,
181 text: Rc<cranpose_ui::text::AnnotatedString>,
182 color: Color,
183 text_style: TextStyle,
184 font_size: f32,
185 scale: f32,
186 layout_options: TextLayoutOptions,
187 clip: Option<Rect>,
188 ) {
189 let z_index = self.next_z;
190 self.next_z += 1;
191 self.texts.push(TextDraw {
192 node_id,
193 rect,
194 snap_anchor: None,
195 text,
196 color,
197 text_style,
198 font_size,
199 scale,
200 layout_options,
201 z_index,
202 clip,
203 });
204 }
205}
206
207impl Default for RasterScene {
208 fn default() -> Self {
209 Self::new()
210 }
211}