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.into(),
53            border_width: quad.border.width,
54            shadow_color: color::pack(quad.shadow.color),
55            shadow_offset: quad.shadow.offset.into(),
56            shadow_blur_radius: quad.shadow.blur_radius,
57            snap: quad.snap as u32,
58        };
59
60        self.quads.add(quad, &background);
61    }
62
63    pub fn draw_paragraph(
64        &mut self,
65        paragraph: &Paragraph,
66        position: Point,
67        color: Color,
68        clip_bounds: Rectangle,
69        transformation: Transformation,
70    ) {
71        let paragraph = Text::Paragraph {
72            paragraph: paragraph.downgrade(),
73            position,
74            color,
75            clip_bounds,
76            transformation,
77        };
78
79        self.pending_text.push(paragraph);
80    }
81
82    pub fn draw_editor(
83        &mut self,
84        editor: &Editor,
85        position: Point,
86        color: Color,
87        clip_bounds: Rectangle,
88        transformation: Transformation,
89    ) {
90        let editor = Text::Editor {
91            editor: editor.downgrade(),
92            position,
93            color,
94            clip_bounds,
95            transformation,
96        };
97
98        self.pending_text.push(editor);
99    }
100
101    pub fn draw_text(
102        &mut self,
103        text: crate::core::Text,
104        position: Point,
105        color: Color,
106        clip_bounds: Rectangle,
107        transformation: Transformation,
108    ) {
109        let text = Text::Cached {
110            content: text.content,
111            bounds: Rectangle::new(position, text.bounds) * transformation,
112            color,
113            size: text.size * transformation.scale_factor(),
114            line_height: text.line_height.to_absolute(text.size)
115                * transformation.scale_factor(),
116            font: text.font,
117            align_x: text.align_x,
118            align_y: text.align_y,
119            shaping: text.shaping,
120            clip_bounds: clip_bounds * transformation,
121        };
122
123        self.pending_text.push(text);
124    }
125
126    pub fn draw_image(&mut self, image: Image, transformation: Transformation) {
127        match image {
128            Image::Raster(image, bounds) => {
129                self.draw_raster(image, bounds, transformation);
130            }
131            Image::Vector(svg, bounds) => {
132                self.draw_svg(svg, bounds, transformation);
133            }
134        }
135    }
136
137    pub fn draw_raster(
138        &mut self,
139        image: core::Image,
140        bounds: Rectangle,
141        transformation: Transformation,
142    ) {
143        let image = Image::Raster(image, bounds * transformation);
144
145        self.images.push(image);
146    }
147
148    pub fn draw_svg(
149        &mut self,
150        svg: Svg,
151        bounds: Rectangle,
152        transformation: Transformation,
153    ) {
154        let svg = Image::Vector(svg, bounds * transformation);
155
156        self.images.push(svg);
157    }
158
159    pub fn draw_mesh(
160        &mut self,
161        mut mesh: Mesh,
162        transformation: Transformation,
163    ) {
164        match &mut mesh {
165            Mesh::Solid {
166                transformation: local_transformation,
167                ..
168            }
169            | Mesh::Gradient {
170                transformation: local_transformation,
171                ..
172            } => {
173                *local_transformation = *local_transformation * transformation;
174            }
175        }
176
177        self.pending_meshes.push(mesh);
178    }
179
180    pub fn draw_mesh_group(
181        &mut self,
182        meshes: Vec<Mesh>,
183        transformation: Transformation,
184    ) {
185        self.flush_meshes();
186
187        self.triangles.push(triangle::Item::Group {
188            meshes,
189            transformation,
190        });
191    }
192
193    pub fn draw_mesh_cache(
194        &mut self,
195        cache: triangle::Cache,
196        transformation: Transformation,
197    ) {
198        self.flush_meshes();
199
200        self.triangles.push(triangle::Item::Cached {
201            cache,
202            transformation,
203        });
204    }
205
206    pub fn draw_text_group(
207        &mut self,
208        text: Vec<Text>,
209        transformation: Transformation,
210    ) {
211        self.flush_text();
212
213        self.text.push(text::Item::Group {
214            text,
215            transformation,
216        });
217    }
218
219    pub fn draw_text_cache(
220        &mut self,
221        cache: text::Cache,
222        transformation: Transformation,
223    ) {
224        self.flush_text();
225
226        self.text.push(text::Item::Cached {
227            cache,
228            transformation,
229        });
230    }
231
232    pub fn draw_primitive(
233        &mut self,
234        bounds: Rectangle,
235        primitive: Box<dyn Primitive>,
236        transformation: Transformation,
237    ) {
238        let bounds = bounds * transformation;
239
240        self.primitives
241            .push(primitive::Instance { bounds, primitive });
242    }
243
244    fn flush_meshes(&mut self) {
245        if !self.pending_meshes.is_empty() {
246            self.triangles.push(triangle::Item::Group {
247                transformation: Transformation::IDENTITY,
248                meshes: self.pending_meshes.drain(..).collect(),
249            });
250        }
251    }
252
253    fn flush_text(&mut self) {
254        if !self.pending_text.is_empty() {
255            self.text.push(text::Item::Group {
256                transformation: Transformation::IDENTITY,
257                text: self.pending_text.drain(..).collect(),
258            });
259        }
260    }
261}
262
263impl graphics::Layer for Layer {
264    fn with_bounds(bounds: Rectangle) -> Self {
265        Self {
266            bounds,
267            ..Self::default()
268        }
269    }
270
271    fn flush(&mut self) {
272        self.flush_meshes();
273        self.flush_text();
274    }
275
276    fn resize(&mut self, bounds: Rectangle) {
277        self.bounds = bounds;
278    }
279
280    fn reset(&mut self) {
281        self.bounds = Rectangle::INFINITE;
282
283        self.quads.clear();
284        self.triangles.clear();
285        self.primitives.clear();
286        self.text.clear();
287        self.images.clear();
288        self.pending_meshes.clear();
289        self.pending_text.clear();
290    }
291}
292
293impl Default for Layer {
294    fn default() -> Self {
295        Self {
296            bounds: Rectangle::INFINITE,
297            quads: quad::Batch::default(),
298            triangles: triangle::Batch::default(),
299            primitives: primitive::Batch::default(),
300            text: text::Batch::default(),
301            images: image::Batch::default(),
302            pending_meshes: Vec::new(),
303            pending_text: Vec::new(),
304        }
305    }
306}