Skip to main content

cranpose_render_pixels/
scene.rs

1use std::rc::Rc;
2
3pub use cranpose_render_common::graph_scene::{HitRegion, Scene};
4use cranpose_render_common::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,
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 z_index: usize,
22    pub clip: Option<Rect>,
23    pub blend_mode: BlendMode,
24}
25
26#[derive(Clone)]
27pub(crate) struct TextDraw {
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 z_index: usize,
36    pub clip: Option<Rect>,
37}
38
39#[derive(Clone)]
40pub(crate) struct ImageDraw {
41    pub rect: Rect,
42    pub snap_anchor: Option<Point>,
43    pub image: ImageBitmap,
44    pub alpha: f32,
45    pub color_filter: Option<ColorFilter>,
46    pub sampling: ImageSampling,
47    pub z_index: usize,
48    pub clip: Option<Rect>,
49    pub blend_mode: BlendMode,
50    pub src_rect: Option<Rect>,
51}
52
53pub(crate) struct RasterScene {
54    pub shapes: Vec<DrawShape>,
55    pub images: Vec<ImageDraw>,
56    pub texts: Vec<TextDraw>,
57    pub next_z: usize,
58}
59
60impl RasterScene {
61    pub fn new() -> Self {
62        Self {
63            shapes: Vec::new(),
64            images: Vec::new(),
65            texts: Vec::new(),
66            next_z: 0,
67        }
68    }
69
70    pub fn push_shape(
71        &mut self,
72        rect: Rect,
73        brush: Brush,
74        shape: Option<RoundedCornerShape>,
75        clip: Option<Rect>,
76        blend_mode: BlendMode,
77    ) {
78        let z_index = self.next_z;
79        self.next_z += 1;
80        self.shapes.push(DrawShape {
81            rect,
82            snap_anchor: None,
83            snap_to_pixel_grid: false,
84            brush,
85            shape,
86            stroke: None,
87            arc: None,
88            line: 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            line: None,
114            z_index,
115            clip,
116            blend_mode,
117        });
118    }
119
120    /// Queues a shape an emitted primitive resolved: a rect, rounded rect,
121    /// stroke, arc band or line segment.
122    pub fn push_shape_params(&mut self, params: ShapeDrawParams) {
123        let z_index = self.next_z;
124        self.next_z += 1;
125        self.shapes.push(DrawShape {
126            rect: params.rect,
127            snap_anchor: None,
128            snap_to_pixel_grid: false,
129            brush: params.brush.into_brush(),
130            shape: params.shape,
131            stroke: params.stroke,
132            arc: params.arc,
133            line: params.line,
134            z_index,
135            clip: params.clip,
136            blend_mode: params.blend_mode,
137        });
138    }
139
140    #[expect(clippy::too_many_arguments)]
141    pub fn push_image_with_geometry(
142        &mut self,
143        rect: Rect,
144        _local_rect: Rect,
145        _quad: [[f32; 2]; 4],
146        image: ImageBitmap,
147        alpha: f32,
148        color_filter: Option<ColorFilter>,
149        sampling: ImageSampling,
150        clip: Option<Rect>,
151        src_rect: Option<Rect>,
152        blend_mode: BlendMode,
153    ) {
154        let z_index = self.next_z;
155        self.next_z += 1;
156        self.images.push(ImageDraw {
157            rect,
158            snap_anchor: None,
159            image,
160            alpha: alpha.clamp(0.0, 1.0),
161            color_filter,
162            sampling,
163            z_index,
164            clip,
165            blend_mode,
166            src_rect,
167        });
168    }
169
170    #[expect(clippy::too_many_arguments)]
171    pub fn push_text(
172        &mut self,
173        rect: Rect,
174        text: Rc<cranpose_ui::text::AnnotatedString>,
175        color: Color,
176        text_style: TextStyle,
177        font_size: f32,
178        scale: f32,
179        clip: Option<Rect>,
180    ) {
181        let z_index = self.next_z;
182        self.next_z += 1;
183        self.texts.push(TextDraw {
184            rect,
185            snap_anchor: None,
186            text,
187            color,
188            text_style,
189            font_size,
190            scale,
191            z_index,
192            clip,
193        });
194    }
195}
196
197impl Default for RasterScene {
198    fn default() -> Self {
199        Self::new()
200    }
201}