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