iced_wgpu/
layer.rs

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