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 * transformation.scale_factor())
53                .into(),
54            border_width: quad.border.width * transformation.scale_factor(),
55            shadow_color: color::pack(quad.shadow.color),
56            shadow_offset: (quad.shadow.offset * transformation.scale_factor())
57                .into(),
58            shadow_blur_radius: quad.shadow.blur_radius
59                * transformation.scale_factor(),
60            snap: quad.snap as u32,
61        };
62
63        self.quads.add(quad, &background);
64    }
65
66    pub fn draw_paragraph(
67        &mut self,
68        paragraph: &Paragraph,
69        position: Point,
70        color: Color,
71        clip_bounds: Rectangle,
72        transformation: Transformation,
73    ) {
74        let paragraph = Text::Paragraph {
75            paragraph: paragraph.downgrade(),
76            position,
77            color,
78            clip_bounds,
79            transformation,
80        };
81
82        self.pending_text.push(paragraph);
83    }
84
85    pub fn draw_editor(
86        &mut self,
87        editor: &Editor,
88        position: Point,
89        color: Color,
90        clip_bounds: Rectangle,
91        transformation: Transformation,
92    ) {
93        let editor = Text::Editor {
94            editor: editor.downgrade(),
95            position,
96            color,
97            clip_bounds,
98            transformation,
99        };
100
101        self.pending_text.push(editor);
102    }
103
104    pub fn draw_text(
105        &mut self,
106        text: crate::core::Text,
107        position: Point,
108        color: Color,
109        clip_bounds: Rectangle,
110        transformation: Transformation,
111    ) {
112        let text = Text::Cached {
113            content: text.content,
114            bounds: Rectangle::new(position, text.bounds) * transformation,
115            color,
116            size: text.size * transformation.scale_factor(),
117            line_height: text.line_height.to_absolute(text.size)
118                * transformation.scale_factor(),
119            font: text.font,
120            align_x: text.align_x,
121            align_y: text.align_y,
122            shaping: text.shaping,
123            clip_bounds: clip_bounds * transformation,
124        };
125
126        self.pending_text.push(text);
127    }
128
129    pub fn draw_image(&mut self, image: Image, transformation: Transformation) {
130        match image {
131            Image::Raster {
132                image,
133                bounds,
134                clip_bounds,
135            } => {
136                self.draw_raster(image, bounds, clip_bounds, transformation);
137            }
138            Image::Vector {
139                svg,
140                bounds,
141                clip_bounds,
142            } => {
143                self.draw_svg(svg, bounds, clip_bounds, transformation);
144            }
145        }
146    }
147
148    pub fn draw_raster(
149        &mut self,
150        image: core::Image,
151        bounds: Rectangle,
152        clip_bounds: Rectangle,
153        transformation: Transformation,
154    ) {
155        let image = Image::Raster {
156            image: core::Image {
157                border_radius: image.border_radius
158                    * transformation.scale_factor(),
159                ..image
160            },
161            bounds: bounds * transformation,
162            clip_bounds: clip_bounds * transformation,
163        };
164
165        self.images.push(image);
166    }
167
168    pub fn draw_svg(
169        &mut self,
170        svg: Svg,
171        bounds: Rectangle,
172        clip_bounds: Rectangle,
173        transformation: Transformation,
174    ) {
175        let svg = Image::Vector {
176            svg,
177            bounds: bounds * transformation,
178            clip_bounds: clip_bounds * transformation,
179        };
180
181        self.images.push(svg);
182    }
183
184    pub fn draw_mesh(
185        &mut self,
186        mut mesh: Mesh,
187        transformation: Transformation,
188    ) {
189        match &mut mesh {
190            Mesh::Solid {
191                transformation: local_transformation,
192                ..
193            }
194            | Mesh::Gradient {
195                transformation: local_transformation,
196                ..
197            } => {
198                *local_transformation = *local_transformation * transformation;
199            }
200        }
201
202        self.pending_meshes.push(mesh);
203    }
204
205    pub fn draw_mesh_group(
206        &mut self,
207        meshes: Vec<Mesh>,
208        transformation: Transformation,
209    ) {
210        self.flush_meshes();
211
212        self.triangles.push(triangle::Item::Group {
213            meshes,
214            transformation,
215        });
216    }
217
218    pub fn draw_mesh_cache(
219        &mut self,
220        cache: triangle::Cache,
221        transformation: Transformation,
222    ) {
223        self.flush_meshes();
224
225        self.triangles.push(triangle::Item::Cached {
226            cache,
227            transformation,
228        });
229    }
230
231    pub fn draw_text_group(
232        &mut self,
233        text: Vec<Text>,
234        transformation: Transformation,
235    ) {
236        self.flush_text();
237
238        self.text.push(text::Item::Group {
239            text,
240            transformation,
241        });
242    }
243
244    pub fn draw_text_cache(
245        &mut self,
246        cache: text::Cache,
247        transformation: Transformation,
248    ) {
249        self.flush_text();
250
251        self.text.push(text::Item::Cached {
252            cache,
253            transformation,
254        });
255    }
256
257    pub fn draw_primitive(
258        &mut self,
259        bounds: Rectangle,
260        primitive: impl Primitive,
261        transformation: Transformation,
262    ) {
263        let bounds = bounds * transformation;
264
265        self.primitives
266            .push(primitive::Instance::new(bounds, primitive));
267    }
268
269    fn flush_meshes(&mut self) {
270        if !self.pending_meshes.is_empty() {
271            self.triangles.push(triangle::Item::Group {
272                transformation: Transformation::IDENTITY,
273                meshes: self.pending_meshes.drain(..).collect(),
274            });
275        }
276    }
277
278    fn flush_text(&mut self) {
279        if !self.pending_text.is_empty() {
280            self.text.push(text::Item::Group {
281                transformation: Transformation::IDENTITY,
282                text: self.pending_text.drain(..).collect(),
283            });
284        }
285    }
286}
287
288impl graphics::Layer for Layer {
289    fn with_bounds(bounds: Rectangle) -> Self {
290        Self {
291            bounds,
292            ..Self::default()
293        }
294    }
295
296    fn bounds(&self) -> Rectangle {
297        self.bounds
298    }
299
300    fn flush(&mut self) {
301        self.flush_meshes();
302        self.flush_text();
303    }
304
305    fn resize(&mut self, bounds: Rectangle) {
306        self.bounds = bounds;
307    }
308
309    fn reset(&mut self) {
310        self.bounds = Rectangle::INFINITE;
311
312        self.quads.clear();
313        self.triangles.clear();
314        self.primitives.clear();
315        self.text.clear();
316        self.images.clear();
317        self.pending_meshes.clear();
318        self.pending_text.clear();
319    }
320
321    fn start(&self) -> usize {
322        if !self.quads.is_empty() {
323            return 1;
324        }
325
326        if !self.triangles.is_empty() {
327            return 2;
328        }
329
330        if !self.primitives.is_empty() {
331            return 3;
332        }
333
334        if !self.images.is_empty() {
335            return 4;
336        }
337
338        if !self.text.is_empty() {
339            return 5;
340        }
341
342        usize::MAX
343    }
344
345    fn end(&self) -> usize {
346        if !self.text.is_empty() {
347            return 5;
348        }
349
350        if !self.images.is_empty() {
351            return 4;
352        }
353
354        if !self.primitives.is_empty() {
355            return 3;
356        }
357
358        if !self.triangles.is_empty() {
359            return 2;
360        }
361
362        if !self.quads.is_empty() {
363            return 1;
364        }
365
366        0
367    }
368
369    fn merge(&mut self, layer: &mut Self) {
370        self.quads.append(&mut layer.quads);
371        self.triangles.append(&mut layer.triangles);
372        self.primitives.append(&mut layer.primitives);
373        self.images.append(&mut layer.images);
374        self.text.append(&mut layer.text);
375    }
376}
377
378impl Default for Layer {
379    fn default() -> Self {
380        Self {
381            bounds: Rectangle::INFINITE,
382            quads: quad::Batch::default(),
383            triangles: triangle::Batch::default(),
384            primitives: primitive::Batch::default(),
385            text: text::Batch::default(),
386            images: image::Batch::default(),
387            pending_meshes: Vec::new(),
388            pending_text: Vec::new(),
389        }
390    }
391}