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(image, bounds) => {
132                self.draw_raster(image, bounds, transformation);
133            }
134            Image::Vector(svg, bounds) => {
135                self.draw_svg(svg, bounds, transformation);
136            }
137        }
138    }
139
140    pub fn draw_raster(
141        &mut self,
142        image: core::Image,
143        bounds: Rectangle,
144        transformation: Transformation,
145    ) {
146        let image = Image::Raster(image, bounds * transformation);
147
148        self.images.push(image);
149    }
150
151    pub fn draw_svg(
152        &mut self,
153        svg: Svg,
154        bounds: Rectangle,
155        transformation: Transformation,
156    ) {
157        let svg = Image::Vector(svg, bounds * transformation);
158
159        self.images.push(svg);
160    }
161
162    pub fn draw_mesh(
163        &mut self,
164        mut mesh: Mesh,
165        transformation: Transformation,
166    ) {
167        match &mut mesh {
168            Mesh::Solid {
169                transformation: local_transformation,
170                ..
171            }
172            | Mesh::Gradient {
173                transformation: local_transformation,
174                ..
175            } => {
176                *local_transformation = *local_transformation * transformation;
177            }
178        }
179
180        self.pending_meshes.push(mesh);
181    }
182
183    pub fn draw_mesh_group(
184        &mut self,
185        meshes: Vec<Mesh>,
186        transformation: Transformation,
187    ) {
188        self.flush_meshes();
189
190        self.triangles.push(triangle::Item::Group {
191            meshes,
192            transformation,
193        });
194    }
195
196    pub fn draw_mesh_cache(
197        &mut self,
198        cache: triangle::Cache,
199        transformation: Transformation,
200    ) {
201        self.flush_meshes();
202
203        self.triangles.push(triangle::Item::Cached {
204            cache,
205            transformation,
206        });
207    }
208
209    pub fn draw_text_group(
210        &mut self,
211        text: Vec<Text>,
212        transformation: Transformation,
213    ) {
214        self.flush_text();
215
216        self.text.push(text::Item::Group {
217            text,
218            transformation,
219        });
220    }
221
222    pub fn draw_text_cache(
223        &mut self,
224        cache: text::Cache,
225        transformation: Transformation,
226    ) {
227        self.flush_text();
228
229        self.text.push(text::Item::Cached {
230            cache,
231            transformation,
232        });
233    }
234
235    pub fn draw_primitive(
236        &mut self,
237        bounds: Rectangle,
238        primitive: Box<dyn Primitive>,
239        transformation: Transformation,
240    ) {
241        let bounds = bounds * transformation;
242
243        self.primitives
244            .push(primitive::Instance { bounds, primitive });
245    }
246
247    fn flush_meshes(&mut self) {
248        if !self.pending_meshes.is_empty() {
249            self.triangles.push(triangle::Item::Group {
250                transformation: Transformation::IDENTITY,
251                meshes: self.pending_meshes.drain(..).collect(),
252            });
253        }
254    }
255
256    fn flush_text(&mut self) {
257        if !self.pending_text.is_empty() {
258            self.text.push(text::Item::Group {
259                transformation: Transformation::IDENTITY,
260                text: self.pending_text.drain(..).collect(),
261            });
262        }
263    }
264}
265
266impl graphics::Layer for Layer {
267    fn with_bounds(bounds: Rectangle) -> Self {
268        Self {
269            bounds,
270            ..Self::default()
271        }
272    }
273
274    fn bounds(&self) -> Rectangle {
275        self.bounds
276    }
277
278    fn flush(&mut self) {
279        self.flush_meshes();
280        self.flush_text();
281    }
282
283    fn resize(&mut self, bounds: Rectangle) {
284        self.bounds = bounds;
285    }
286
287    fn reset(&mut self) {
288        self.bounds = Rectangle::INFINITE;
289
290        self.quads.clear();
291        self.triangles.clear();
292        self.primitives.clear();
293        self.text.clear();
294        self.images.clear();
295        self.pending_meshes.clear();
296        self.pending_text.clear();
297    }
298
299    fn start(&self) -> usize {
300        if !self.quads.is_empty() {
301            return 1;
302        }
303
304        if !self.triangles.is_empty() {
305            return 2;
306        }
307
308        if !self.primitives.is_empty() {
309            return 3;
310        }
311
312        if !self.images.is_empty() {
313            return 4;
314        }
315
316        if !self.text.is_empty() {
317            return 5;
318        }
319
320        usize::MAX
321    }
322
323    fn end(&self) -> usize {
324        if !self.text.is_empty() {
325            return 5;
326        }
327
328        if !self.images.is_empty() {
329            return 4;
330        }
331
332        if !self.primitives.is_empty() {
333            return 3;
334        }
335
336        if !self.triangles.is_empty() {
337            return 2;
338        }
339
340        if !self.quads.is_empty() {
341            return 1;
342        }
343
344        0
345    }
346
347    fn merge(&mut self, layer: &mut Self) {
348        self.quads.append(&mut layer.quads);
349        self.triangles.append(&mut layer.triangles);
350        self.primitives.append(&mut layer.primitives);
351        self.images.append(&mut layer.images);
352        self.text.append(&mut layer.text);
353    }
354}
355
356impl Default for Layer {
357    fn default() -> Self {
358        Self {
359            bounds: Rectangle::INFINITE,
360            quads: quad::Batch::default(),
361            triangles: triangle::Batch::default(),
362            primitives: primitive::Batch::default(),
363            text: text::Batch::default(),
364            images: image::Batch::default(),
365            pending_meshes: Vec::new(),
366            pending_text: Vec::new(),
367        }
368    }
369}