iced_wgpu/
layer.rs

1use crate::core::{self, Background, Color, Point, Rectangle, Svg, Transformation, renderer};
2use crate::graphics;
3use crate::graphics::Mesh;
4use crate::graphics::color;
5use crate::graphics::layer;
6use crate::graphics::mesh;
7use crate::graphics::text::{Editor, Paragraph};
8use crate::image::{self, Image};
9use crate::primitive::{self, Primitive};
10use crate::quad::{self, Quad};
11use crate::text::{self, Text};
12use crate::triangle;
13
14pub type Stack = layer::Stack<Layer>;
15
16#[derive(Debug)]
17pub struct Layer {
18    pub bounds: Rectangle,
19    pub quads: quad::Batch,
20    pub triangles: triangle::Batch,
21    pub primitives: primitive::Batch,
22    pub images: image::Batch,
23    pub text: text::Batch,
24    pending_meshes: Vec<Mesh>,
25    pending_text: Vec<Text>,
26}
27
28impl Layer {
29    pub fn is_empty(&self) -> bool {
30        self.quads.is_empty()
31            && self.triangles.is_empty()
32            && self.primitives.is_empty()
33            && self.images.is_empty()
34            && self.text.is_empty()
35            && self.pending_meshes.is_empty()
36            && self.pending_text.is_empty()
37    }
38
39    pub fn draw_quad(
40        &mut self,
41        quad: renderer::Quad,
42        background: Background,
43        transformation: Transformation,
44    ) {
45        let bounds = quad.bounds * transformation;
46
47        let quad = Quad {
48            position: [bounds.x, bounds.y],
49            size: [bounds.width, bounds.height],
50            border_color: color::pack(quad.border.color),
51            border_radius: (quad.border.radius * transformation.scale_factor()).into(),
52            border_width: quad.border.width * transformation.scale_factor(),
53            shadow_color: color::pack(quad.shadow.color),
54            shadow_offset: (quad.shadow.offset * transformation.scale_factor()).into(),
55            shadow_blur_radius: quad.shadow.blur_radius * transformation.scale_factor(),
56            snap: quad.snap as u32,
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) * transformation.scale_factor(),
114            font: text.font,
115            align_x: text.align_x,
116            align_y: text.align_y,
117            shaping: text.shaping,
118            clip_bounds: clip_bounds * transformation,
119        };
120
121        self.pending_text.push(text);
122    }
123
124    pub fn draw_text_raw(&mut self, raw: graphics::text::Raw, transformation: Transformation) {
125        let raw = Text::Raw {
126            raw,
127            transformation,
128        };
129
130        self.pending_text.push(raw);
131    }
132
133    pub fn draw_image(&mut self, image: Image, transformation: Transformation) {
134        match image {
135            Image::Raster {
136                image,
137                bounds,
138                clip_bounds,
139            } => {
140                self.draw_raster(image, bounds, clip_bounds, transformation);
141            }
142            Image::Vector {
143                svg,
144                bounds,
145                clip_bounds,
146            } => {
147                self.draw_svg(svg, bounds, clip_bounds, transformation);
148            }
149        }
150    }
151
152    pub fn draw_raster(
153        &mut self,
154        image: core::Image,
155        bounds: Rectangle,
156        clip_bounds: Rectangle,
157        transformation: Transformation,
158    ) {
159        let image = Image::Raster {
160            image: core::Image {
161                border_radius: image.border_radius * transformation.scale_factor(),
162                ..image
163            },
164            bounds: bounds * transformation,
165            clip_bounds: clip_bounds * transformation,
166        };
167
168        self.images.push(image);
169    }
170
171    pub fn draw_svg(
172        &mut self,
173        svg: Svg,
174        bounds: Rectangle,
175        clip_bounds: Rectangle,
176        transformation: Transformation,
177    ) {
178        let svg = Image::Vector {
179            svg,
180            bounds: bounds * transformation,
181            clip_bounds: clip_bounds * transformation,
182        };
183
184        self.images.push(svg);
185    }
186
187    pub fn draw_mesh(&mut self, mut mesh: Mesh, transformation: Transformation) {
188        match &mut mesh {
189            Mesh::Solid {
190                transformation: local_transformation,
191                ..
192            }
193            | Mesh::Gradient {
194                transformation: local_transformation,
195                ..
196            } => {
197                *local_transformation = *local_transformation * transformation;
198            }
199        }
200
201        self.pending_meshes.push(mesh);
202    }
203
204    pub fn draw_mesh_group(&mut self, meshes: Vec<Mesh>, transformation: Transformation) {
205        self.flush_meshes();
206
207        self.triangles.push(triangle::Item::Group {
208            meshes,
209            transformation,
210        });
211    }
212
213    pub fn draw_mesh_cache(&mut self, cache: mesh::Cache, transformation: Transformation) {
214        self.flush_meshes();
215
216        self.triangles.push(triangle::Item::Cached {
217            cache,
218            transformation,
219        });
220    }
221
222    pub fn draw_text_group(&mut self, text: Vec<Text>, transformation: Transformation) {
223        self.flush_text();
224
225        self.text.push(text::Item::Group {
226            text,
227            transformation,
228        });
229    }
230
231    pub fn draw_text_cache(&mut self, cache: text::Cache, transformation: Transformation) {
232        self.flush_text();
233
234        self.text.push(text::Item::Cached {
235            cache,
236            transformation,
237        });
238    }
239
240    pub fn draw_primitive(
241        &mut self,
242        bounds: Rectangle,
243        primitive: impl Primitive,
244        transformation: Transformation,
245    ) {
246        let bounds = bounds * transformation;
247
248        self.primitives
249            .push(primitive::Instance::new(bounds, primitive));
250    }
251
252    fn flush_meshes(&mut self) {
253        if !self.pending_meshes.is_empty() {
254            self.triangles.push(triangle::Item::Group {
255                transformation: Transformation::IDENTITY,
256                meshes: self.pending_meshes.drain(..).collect(),
257            });
258        }
259    }
260
261    fn flush_text(&mut self) {
262        if !self.pending_text.is_empty() {
263            self.text.push(text::Item::Group {
264                transformation: Transformation::IDENTITY,
265                text: self.pending_text.drain(..).collect(),
266            });
267        }
268    }
269}
270
271impl graphics::Layer for Layer {
272    fn with_bounds(bounds: Rectangle) -> Self {
273        Self {
274            bounds,
275            ..Self::default()
276        }
277    }
278
279    fn bounds(&self) -> Rectangle {
280        self.bounds
281    }
282
283    fn flush(&mut self) {
284        self.flush_meshes();
285        self.flush_text();
286    }
287
288    fn resize(&mut self, bounds: Rectangle) {
289        self.bounds = bounds;
290    }
291
292    fn reset(&mut self) {
293        self.bounds = Rectangle::INFINITE;
294
295        self.quads.clear();
296        self.triangles.clear();
297        self.primitives.clear();
298        self.text.clear();
299        self.images.clear();
300        self.pending_meshes.clear();
301        self.pending_text.clear();
302    }
303
304    fn start(&self) -> usize {
305        if !self.quads.is_empty() {
306            return 1;
307        }
308
309        if !self.triangles.is_empty() {
310            return 2;
311        }
312
313        if !self.primitives.is_empty() {
314            return 3;
315        }
316
317        if !self.images.is_empty() {
318            return 4;
319        }
320
321        if !self.text.is_empty() {
322            return 5;
323        }
324
325        usize::MAX
326    }
327
328    fn end(&self) -> usize {
329        if !self.text.is_empty() {
330            return 5;
331        }
332
333        if !self.images.is_empty() {
334            return 4;
335        }
336
337        if !self.primitives.is_empty() {
338            return 3;
339        }
340
341        if !self.triangles.is_empty() {
342            return 2;
343        }
344
345        if !self.quads.is_empty() {
346            return 1;
347        }
348
349        0
350    }
351
352    fn merge(&mut self, layer: &mut Self) {
353        self.quads.append(&mut layer.quads);
354        self.triangles.append(&mut layer.triangles);
355        self.primitives.append(&mut layer.primitives);
356        self.images.append(&mut layer.images);
357        self.text.append(&mut layer.text);
358    }
359}
360
361impl Default for Layer {
362    fn default() -> Self {
363        Self {
364            bounds: Rectangle::INFINITE,
365            quads: quad::Batch::default(),
366            triangles: triangle::Batch::default(),
367            primitives: primitive::Batch::default(),
368            text: text::Batch::default(),
369            images: image::Batch::default(),
370            pending_meshes: Vec::new(),
371            pending_text: Vec::new(),
372        }
373    }
374}