Skip to main content

cranpose_render_pixels/
scene.rs

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}