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}