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}