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::{ClickAction, HitRegion, Scene};
5use cranpose_ui::{TextLayoutOptions, TextStyle};
6use cranpose_ui_graphics::{
7    BlendMode, Brush, Color, ColorFilter, ImageBitmap, ImageSampling, Point, Rect,
8    RoundedCornerShape,
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 z_index: usize,
19    pub clip: Option<Rect>,
20    pub blend_mode: BlendMode,
21}
22
23#[derive(Clone)]
24pub(crate) struct TextDraw {
25    pub node_id: NodeId,
26    pub rect: Rect,
27    pub snap_anchor: Option<Point>,
28    pub text: Rc<cranpose_ui::text::AnnotatedString>,
29    pub color: Color,
30    pub text_style: TextStyle,
31    pub font_size: f32,
32    pub scale: f32,
33    pub layout_options: TextLayoutOptions,
34    pub z_index: usize,
35    pub clip: Option<Rect>,
36}
37
38#[derive(Clone)]
39pub(crate) struct ImageDraw {
40    pub rect: Rect,
41    pub snap_anchor: Option<Point>,
42    pub image: ImageBitmap,
43    pub alpha: f32,
44    pub color_filter: Option<ColorFilter>,
45    pub sampling: ImageSampling,
46    pub z_index: usize,
47    pub clip: Option<Rect>,
48    pub blend_mode: BlendMode,
49    /// Source sub-region in image-pixel coordinates. `None` means full image.
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            z_index,
87            clip,
88            blend_mode,
89        });
90    }
91
92    pub fn push_pixel_snapped_shape(
93        &mut self,
94        rect: Rect,
95        brush: Brush,
96        shape: Option<RoundedCornerShape>,
97        clip: Option<Rect>,
98        blend_mode: BlendMode,
99    ) {
100        let z_index = self.next_z;
101        self.next_z += 1;
102        self.shapes.push(DrawShape {
103            rect,
104            snap_anchor: None,
105            snap_to_pixel_grid: true,
106            brush,
107            shape,
108            z_index,
109            clip,
110            blend_mode,
111        });
112    }
113
114    #[allow(clippy::too_many_arguments)]
115    pub fn push_shape_with_geometry(
116        &mut self,
117        rect: Rect,
118        _local_rect: Rect,
119        _quad: [[f32; 2]; 4],
120        brush: Brush,
121        shape: Option<RoundedCornerShape>,
122        clip: Option<Rect>,
123        blend_mode: BlendMode,
124    ) {
125        self.push_shape(rect, brush, shape, clip, blend_mode);
126    }
127
128    #[allow(clippy::too_many_arguments)]
129    pub fn push_image_with_geometry(
130        &mut self,
131        rect: Rect,
132        _local_rect: Rect,
133        _quad: [[f32; 2]; 4],
134        image: ImageBitmap,
135        alpha: f32,
136        color_filter: Option<ColorFilter>,
137        sampling: ImageSampling,
138        clip: Option<Rect>,
139        src_rect: Option<Rect>,
140        blend_mode: BlendMode,
141    ) {
142        let z_index = self.next_z;
143        self.next_z += 1;
144        self.images.push(ImageDraw {
145            rect,
146            snap_anchor: None,
147            image,
148            alpha: alpha.clamp(0.0, 1.0),
149            color_filter,
150            sampling,
151            z_index,
152            clip,
153            blend_mode,
154            src_rect,
155        });
156    }
157
158    #[allow(clippy::too_many_arguments)]
159    pub fn push_text(
160        &mut self,
161        node_id: NodeId,
162        rect: Rect,
163        text: Rc<cranpose_ui::text::AnnotatedString>,
164        color: Color,
165        text_style: TextStyle,
166        font_size: f32,
167        scale: f32,
168        layout_options: TextLayoutOptions,
169        clip: Option<Rect>,
170    ) {
171        let z_index = self.next_z;
172        self.next_z += 1;
173        self.texts.push(TextDraw {
174            node_id,
175            rect,
176            snap_anchor: None,
177            text,
178            color,
179            text_style,
180            font_size,
181            scale,
182            layout_options,
183            z_index,
184            clip,
185        });
186    }
187}
188
189impl Default for RasterScene {
190    fn default() -> Self {
191        Self::new()
192    }
193}