Skip to main content

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