iced_wgpu/
layer.rs

1use crate::core::{
2    self, Background, Color, Point, Rectangle, Svg, Transformation, renderer,
3};
4use crate::graphics;
5use crate::graphics::Mesh;
6use crate::graphics::color;
7use crate::graphics::layer;
8use crate::graphics::text::{Editor, Paragraph};
9use crate::image::{self, Image};
10use crate::primitive::{self, Primitive};
11use crate::quad::{self, Quad};
12use crate::text::{self, Text};
13use crate::triangle;
14
15pub type Stack = layer::Stack<Layer>;
16
17#[derive(Debug)]
18pub struct Layer {
19    pub bounds: Rectangle,
20    pub quads: quad::Batch,
21    pub triangles: triangle::Batch,
22    pub primitives: primitive::Batch,
23    pub images: image::Batch,
24    pub text: text::Batch,
25    pending_meshes: Vec<Mesh>,
26    pending_text: Vec<Text>,
27}
28
29impl Layer {
30    pub fn is_empty(&self) -> bool {
31        self.quads.is_empty()
32            && self.triangles.is_empty()
33            && self.primitives.is_empty()
34            && self.images.is_empty()
35            && self.text.is_empty()
36            && self.pending_meshes.is_empty()
37            && self.pending_text.is_empty()
38    }
39
40    pub fn draw_quad(
41        &mut self,
42        quad: renderer::Quad,
43        background: Background,
44        transformation: Transformation,
45    ) {
46        let bounds = quad.bounds * transformation;
47
48        let quad = Quad {
49            position: [bounds.x, bounds.y],
50            size: [bounds.width, bounds.height],
51            border_color: color::pack(quad.border.color),
52            border_radius: quad.border.radius.into(),
53            border_width: quad.border.width,
54            shadow_color: color::pack(quad.shadow.color),
55            shadow_offset: quad.shadow.offset.into(),
56            shadow_blur_radius: quad.shadow.blur_radius,
57        };
58
59        self.quads.add(quad, &background);
60    }
61
62    pub fn draw_paragraph(
63        &mut self,
64        paragraph: &Paragraph,
65        position: Point,
66        color: Color,
67        clip_bounds: Rectangle,
68        transformation: Transformation,
69    ) {
70        let paragraph = Text::Paragraph {
71            paragraph: paragraph.downgrade(),
72            position,
73            color,
74            clip_bounds,
75            transformation,
76        };
77
78        self.pending_text.push(paragraph);
79    }
80
81    pub fn draw_editor(
82        &mut self,
83        editor: &Editor,
84        position: Point,
85        color: Color,
86        clip_bounds: Rectangle,
87        transformation: Transformation,
88    ) {
89        let editor = Text::Editor {
90            editor: editor.downgrade(),
91            position,
92            color,
93            clip_bounds,
94            transformation,
95        };
96
97        self.pending_text.push(editor);
98    }
99
100    pub fn draw_text(
101        &mut self,
102        text: crate::core::Text,
103        position: Point,
104        color: Color,
105        clip_bounds: Rectangle,
106        transformation: Transformation,
107    ) {
108        let text = Text::Cached {
109            content: text.content,
110            bounds: Rectangle::new(position, text.bounds) * transformation,
111            color,
112            size: text.size * transformation.scale_factor(),
113            line_height: text.line_height.to_absolute(text.size)
114                * transformation.scale_factor(),
115            font: text.font,
116            align_x: text.align_x,
117            align_y: text.align_y,
118            shaping: text.shaping,
119            clip_bounds: clip_bounds * transformation,
120        };
121
122        self.pending_text.push(text);
123    }
124
125    pub fn draw_image(&mut self, image: Image, transformation: Transformation) {
126        match image {
127            Image::Raster(image, bounds) => {
128                self.draw_raster(image, bounds, transformation);
129            }
130            Image::Vector(svg, bounds) => {
131                self.draw_svg(svg, bounds, transformation);
132            }
133        }
134    }
135
136    pub fn draw_raster(
137        &mut self,
138        image: core::Image,
139        bounds: Rectangle,
140        transformation: Transformation,
141    ) {
142        let image = Image::Raster(image, bounds * transformation);
143
144        self.images.push(image);
145    }
146
147    pub fn draw_svg(
148        &mut self,
149        svg: Svg,
150        bounds: Rectangle,
151        transformation: Transformation,
152    ) {
153        let svg = Image::Vector(svg, bounds * transformation);
154
155        self.images.push(svg);
156    }
157
158    pub fn draw_mesh(
159        &mut self,
160        mut mesh: Mesh,
161        transformation: Transformation,
162    ) {
163        match &mut mesh {
164            Mesh::Solid {
165                transformation: local_transformation,
166                ..
167            }
168            | Mesh::Gradient {
169                transformation: local_transformation,
170                ..
171            } => {
172                *local_transformation = *local_transformation * transformation;
173            }
174        }
175
176        self.pending_meshes.push(mesh);
177    }
178
179    pub fn draw_mesh_group(
180        &mut self,
181        meshes: Vec<Mesh>,
182        transformation: Transformation,
183    ) {
184        self.flush_meshes();
185
186        self.triangles.push(triangle::Item::Group {
187            meshes,
188            transformation,
189        });
190    }
191
192    pub fn draw_mesh_cache(
193        &mut self,
194        cache: triangle::Cache,
195        transformation: Transformation,
196    ) {
197        self.flush_meshes();
198
199        self.triangles.push(triangle::Item::Cached {
200            cache,
201            transformation,
202        });
203    }
204
205    pub fn draw_text_group(
206        &mut self,
207        text: Vec<Text>,
208        transformation: Transformation,
209    ) {
210        self.flush_text();
211
212        self.text.push(text::Item::Group {
213            text,
214            transformation,
215        });
216    }
217
218    pub fn draw_text_cache(
219        &mut self,
220        cache: text::Cache,
221        transformation: Transformation,
222    ) {
223        self.flush_text();
224
225        self.text.push(text::Item::Cached {
226            cache,
227            transformation,
228        });
229    }
230
231    pub fn draw_primitive(
232        &mut self,
233        bounds: Rectangle,
234        primitive: Box<dyn Primitive>,
235        transformation: Transformation,
236    ) {
237        let bounds = bounds * transformation;
238
239        self.primitives
240            .push(primitive::Instance { bounds, primitive });
241    }
242
243    fn flush_meshes(&mut self) {
244        if !self.pending_meshes.is_empty() {
245            self.triangles.push(triangle::Item::Group {
246                transformation: Transformation::IDENTITY,
247                meshes: self.pending_meshes.drain(..).collect(),
248            });
249        }
250    }
251
252    fn flush_text(&mut self) {
253        if !self.pending_text.is_empty() {
254            self.text.push(text::Item::Group {
255                transformation: Transformation::IDENTITY,
256                text: self.pending_text.drain(..).collect(),
257            });
258        }
259    }
260}
261
262impl graphics::Layer for Layer {
263    fn with_bounds(bounds: Rectangle) -> Self {
264        Self {
265            bounds,
266            ..Self::default()
267        }
268    }
269
270    fn flush(&mut self) {
271        self.flush_meshes();
272        self.flush_text();
273    }
274
275    fn resize(&mut self, bounds: Rectangle) {
276        self.bounds = bounds;
277    }
278
279    fn reset(&mut self) {
280        self.bounds = Rectangle::INFINITE;
281
282        self.quads.clear();
283        self.triangles.clear();
284        self.primitives.clear();
285        self.text.clear();
286        self.images.clear();
287        self.pending_meshes.clear();
288        self.pending_text.clear();
289    }
290}
291
292impl Default for Layer {
293    fn default() -> Self {
294        Self {
295            bounds: Rectangle::INFINITE,
296            quads: quad::Batch::default(),
297            triangles: triangle::Batch::default(),
298            primitives: primitive::Batch::default(),
299            text: text::Batch::default(),
300            images: image::Batch::default(),
301            pending_meshes: Vec::new(),
302            pending_text: Vec::new(),
303        }
304    }
305}