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