1use crate::font::FontHeight;
22use crate::style::resource::StyleResource;
23use crate::{
24 brush::Brush,
25 core::{
26 algebra::{Matrix3, Point2, Vector2},
27 color::Color,
28 log::Log,
29 math::{self, Rect, TriangleDefinition},
30 },
31 font::FontResource,
32 formatted_text::FormattedText,
33 Thickness,
34};
35use bytemuck::{Pod, Zeroable};
36use fyrox_core::math::round_to_step;
37use fyrox_texture::TextureResource;
38use std::ops::Range;
39
40#[derive(Clone, Copy, Debug, Pod, Zeroable)]
41#[repr(C)]
42pub struct Vertex {
43 pub pos: Vector2<f32>,
44 pub tex_coord: Vector2<f32>,
45 pub color: Color,
46}
47
48impl Vertex {
49 fn new(pos: Vector2<f32>, tex_coord: Vector2<f32>) -> Vertex {
50 Vertex {
51 pos,
52 tex_coord,
53 color: Color::WHITE,
54 }
55 }
56}
57
58#[derive(Clone, Debug)]
59pub enum CommandTexture {
60 None,
61 Texture(TextureResource),
62 Font {
63 font: FontResource,
64 height: FontHeight,
65 page_index: usize,
66 },
67}
68
69#[derive(Clone, Debug)]
71pub struct ClippingGeometry {
72 pub vertex_buffer: Vec<Vertex>,
73 pub triangle_buffer: Vec<TriangleDefinition>,
74 pub transform_stack: TransformStack,
75}
76
77impl Draw for ClippingGeometry {
78 #[inline(always)]
79 fn push_vertex_raw(&mut self, mut vertex: Vertex) {
80 vertex.pos = self
81 .transform_stack
82 .transform
83 .transform_point(&Point2::from(vertex.pos))
84 .coords;
85
86 self.vertex_buffer.push(vertex);
87 }
88
89 #[inline(always)]
90 fn push_triangle(&mut self, a: u32, b: u32, c: u32) {
91 self.triangle_buffer.push(TriangleDefinition([a, b, c]));
92 }
93
94 #[inline(always)]
95 fn last_vertex_index(&self) -> u32 {
96 self.vertex_buffer.len() as u32
97 }
98}
99
100impl ClippingGeometry {
101 pub fn is_contains_point(&self, pos: Vector2<f32>) -> bool {
102 for triangle in self.triangle_buffer.iter() {
103 if let Some((va, vb, vc)) = self.triangle_points(triangle) {
104 if math::is_point_inside_2d_triangle(pos, va.pos, vb.pos, vc.pos) {
105 return true;
106 }
107 }
108 }
109
110 false
111 }
112
113 pub fn triangle_points(
114 &self,
115 triangle: &TriangleDefinition,
116 ) -> Option<(&Vertex, &Vertex, &Vertex)> {
117 let a = self.vertex_buffer.get(triangle[0] as usize)?;
118 let b = self.vertex_buffer.get(triangle[1] as usize)?;
119 let c = self.vertex_buffer.get(triangle[2] as usize)?;
120 Some((a, b, c))
121 }
122}
123
124#[derive(Clone, Debug)]
125pub struct Command {
126 pub clip_bounds: Rect<f32>,
128 pub bounds: Rect<f32>,
130 pub brush: Brush,
132 pub texture: CommandTexture,
133 pub triangles: Range<usize>,
134 pub opacity: f32,
135 pub clipping_geometry: Option<ClippingGeometry>,
137}
138
139pub trait Draw {
140 fn push_vertex(&mut self, pos: Vector2<f32>, tex_coord: Vector2<f32>) {
141 self.push_vertex_raw(Vertex::new(pos, tex_coord))
142 }
143
144 fn push_vertex_raw(&mut self, vertex: Vertex);
145
146 fn push_triangle(&mut self, a: u32, b: u32, c: u32);
147
148 fn last_vertex_index(&self) -> u32;
149
150 fn push_triangle_multicolor(&mut self, vertices: [(Vector2<f32>, Color); 3]) {
151 let index = self.last_vertex_index();
152 for &(pos, color) in &vertices {
153 self.push_vertex_raw(Vertex {
154 pos,
155 tex_coord: Vector2::new(0.0, 0.0),
156 color,
157 });
158 }
159
160 self.push_triangle(index, index + 1, index + 2);
161 }
162
163 fn push_triangle_filled(&mut self, vertices: [Vector2<f32>; 3]) {
164 let index = self.last_vertex_index();
165
166 for &pos in &vertices {
167 self.push_vertex(pos, Default::default());
168 }
169
170 self.push_triangle(index, index + 1, index + 2);
171 }
172
173 fn push_line(&mut self, a: Vector2<f32>, b: Vector2<f32>, thickness: f32) {
174 let index = self.last_vertex_index();
175 let perp = get_line_thickness_vector(a, b, thickness);
176 self.push_vertex(a - perp, Vector2::new(0.0, 0.0));
177 self.push_vertex(b - perp, Vector2::new(1.0, 0.0));
178 self.push_vertex(a + perp, Vector2::new(1.0, 1.0));
179 self.push_vertex(b + perp, Vector2::new(0.0, 1.0));
180
181 self.push_triangle(index, index + 1, index + 2);
182 self.push_triangle(index + 2, index + 1, index + 3);
183 }
184
185 fn push_rect(&mut self, rect: &Rect<f32>, thickness: f32) {
186 let offset = thickness * 0.5;
187
188 let left_top = Vector2::new(rect.x() + offset, rect.y() + thickness);
189 let right_top = Vector2::new(rect.x() + rect.w() - offset, rect.y() + thickness);
190 let right_bottom = Vector2::new(
191 rect.x() + rect.w() - offset,
192 rect.y() + rect.h() - thickness,
193 );
194 let left_bottom = Vector2::new(rect.x() + offset, rect.y() + rect.h() - thickness);
195 let left_top_off = Vector2::new(rect.x(), rect.y() + offset);
196 let right_top_off = Vector2::new(rect.x() + rect.w(), rect.y() + offset);
197 let right_bottom_off = Vector2::new(rect.x() + rect.w(), rect.y() + rect.h() - offset);
198 let left_bottom_off = Vector2::new(rect.x(), rect.y() + rect.h() - offset);
199
200 self.push_line(left_top_off, right_top_off, thickness);
202 self.push_line(right_bottom_off, left_bottom_off, thickness);
203
204 self.push_line(right_top, right_bottom, thickness);
206 self.push_line(left_bottom, left_top, thickness);
207 }
208
209 fn push_rect_vary(&mut self, rect: &Rect<f32>, thickness: Thickness) {
210 let left_top = Vector2::new(rect.x() + thickness.left * 0.5, rect.y() + thickness.top);
211 let right_top = Vector2::new(
212 rect.x() + rect.w() - thickness.right * 0.5,
213 rect.y() + thickness.top,
214 );
215 let right_bottom = Vector2::new(
216 rect.x() + rect.w() - thickness.right * 0.5,
217 rect.y() + rect.h() - thickness.bottom,
218 );
219 let left_bottom = Vector2::new(
220 rect.x() + thickness.left * 0.5,
221 rect.y() + rect.h() - thickness.bottom,
222 );
223 let left_top_off = Vector2::new(rect.x(), rect.y() + thickness.top * 0.5);
224 let right_top_off = Vector2::new(rect.x() + rect.w(), rect.y() + thickness.top * 0.5);
225 let right_bottom_off = Vector2::new(
226 rect.x() + rect.w(),
227 rect.y() + rect.h() - thickness.bottom * 0.5,
228 );
229 let left_bottom_off = Vector2::new(rect.x(), rect.y() + rect.h() - thickness.bottom * 0.5);
230
231 self.push_line(left_top_off, right_top_off, thickness.top);
233 self.push_line(right_bottom_off, left_bottom_off, thickness.bottom);
234
235 self.push_line(right_top, right_bottom, thickness.right);
237 self.push_line(left_bottom, left_top, thickness.left);
238 }
239
240 fn push_rect_filled(&mut self, rect: &Rect<f32>, tex_coords: Option<&[Vector2<f32>; 4]>) {
241 let index = self.last_vertex_index();
242 self.push_vertex(
243 Vector2::new(rect.x(), rect.y()),
244 tex_coords.map_or(Vector2::new(0.0, 0.0), |t| t[0]),
245 );
246 self.push_vertex(
247 Vector2::new(rect.x() + rect.w(), rect.y()),
248 tex_coords.map_or(Vector2::new(1.0, 0.0), |t| t[1]),
249 );
250 self.push_vertex(
251 Vector2::new(rect.x() + rect.w(), rect.y() + rect.h()),
252 tex_coords.map_or(Vector2::new(1.0, 1.0), |t| t[2]),
253 );
254 self.push_vertex(
255 Vector2::new(rect.x(), rect.y() + rect.h()),
256 tex_coords.map_or(Vector2::new(0.0, 1.0), |t| t[3]),
257 );
258
259 self.push_triangle(index, index + 1, index + 2);
260 self.push_triangle(index, index + 2, index + 3);
261 }
262
263 fn push_rect_multicolor(&mut self, rect: &Rect<f32>, colors: [Color; 4]) {
264 let index = self.last_vertex_index();
265 self.push_vertex_raw(Vertex {
266 pos: rect.left_top_corner(),
267 tex_coord: Vector2::new(0.0, 0.0),
268 color: colors[0],
269 });
270 self.push_vertex_raw(Vertex {
271 pos: rect.right_top_corner(),
272 tex_coord: Vector2::new(1.0, 0.0),
273 color: colors[1],
274 });
275 self.push_vertex_raw(Vertex {
276 pos: rect.right_bottom_corner(),
277 tex_coord: Vector2::new(1.0, 1.0),
278 color: colors[2],
279 });
280 self.push_vertex_raw(Vertex {
281 pos: rect.left_bottom_corner(),
282 tex_coord: Vector2::new(0.0, 1.0),
283 color: colors[3],
284 });
285
286 self.push_triangle(index, index + 1, index + 2);
287 self.push_triangle(index, index + 2, index + 3);
288 }
289
290 fn push_circle_filled(
291 &mut self,
292 origin: Vector2<f32>,
293 radius: f32,
294 segments: usize,
295 color: Color,
296 ) {
297 if segments >= 3 {
298 let center_index = self.last_vertex_index();
299
300 self.push_vertex_raw(Vertex {
301 pos: origin,
302 tex_coord: Vector2::default(),
303 color,
304 });
305
306 let two_pi = 2.0 * std::f32::consts::PI;
307 let delta_angle = two_pi / (segments as f32);
308 let mut angle: f32 = 0.0;
309 for _ in 0..segments {
310 let x = origin.x + radius * angle.cos();
311 let y = origin.y + radius * angle.sin();
312 self.push_vertex_raw(Vertex {
313 pos: Vector2::new(x, y),
314 tex_coord: Vector2::default(),
315 color,
316 });
317 angle += delta_angle;
318 }
319
320 let first_vertex = center_index + 1;
321 for segment in 0..segments {
322 self.push_triangle(
323 center_index,
324 first_vertex + segment as u32,
325 first_vertex + (segment as u32 + 1) % segments as u32,
326 );
327 }
328 }
329 }
330
331 fn push_circle(
332 &mut self,
333 center: Vector2<f32>,
334 radius: f32,
335 subdivisions: usize,
336 thickness: f32,
337 ) {
338 let start_vertex = self.last_vertex_index();
339 let d = std::f32::consts::TAU / subdivisions as f32;
340
341 let half_thickness = thickness * 0.5;
342
343 let mut angle = 0.0;
344 while angle < std::f32::consts::TAU {
345 let r = Vector2::new(angle.cos(), angle.sin());
346
347 let p0 = center + r.scale(radius - half_thickness);
348 self.push_vertex(p0, Default::default());
349
350 let p1 = center + r.scale(radius + half_thickness);
351 self.push_vertex(p1, Default::default());
352
353 angle += d;
354 }
355 let last_vertex_index = self.last_vertex_index();
356
357 self.connect_as_line(start_vertex, last_vertex_index, true)
358 }
359
360 fn connect_as_line(&mut self, from: u32, to: u32, closed: bool) {
361 if closed {
362 let count = to - from;
363 for i in (0..count).step_by(2) {
364 let i0 = from + i % count;
365 let i1 = from + (i + 1) % count;
366 let i2 = from + (i + 2) % count;
367 let i3 = from + (i + 3) % count;
368 self.push_triangle(i0, i1, i2);
369 self.push_triangle(i1, i3, i2);
370 }
371 } else {
372 for i in (from..to.saturating_sub(4)).step_by(2) {
373 let i0 = i;
374 let i1 = i + 1;
375 let i2 = i + 2;
376 let i3 = i + 3;
377 self.push_triangle(i0, i1, i2);
378 self.push_triangle(i1, i3, i2);
379 }
380 }
381 }
382
383 fn push_arc(
384 &mut self,
385 center: Vector2<f32>,
386 radius: f32,
387 angles: Range<f32>,
388 subdivisions: usize,
389 thickness: f32,
390 ) {
391 let start_vertex = self.last_vertex_index();
392 self.push_arc_path_with_thickness(center, radius, angles, subdivisions, thickness);
393 let last_vertex_index = self.last_vertex_index();
394
395 self.connect_as_line(start_vertex, last_vertex_index, false)
396 }
397
398 fn push_arc_path_with_thickness(
399 &mut self,
400 center: Vector2<f32>,
401 radius: f32,
402 angles: Range<f32>,
403 subdivisions: usize,
404 thickness: f32,
405 ) {
406 let mut start_angle = math::wrap_angle(angles.start);
407 let mut end_angle = math::wrap_angle(angles.end);
408
409 if start_angle > end_angle {
410 std::mem::swap(&mut start_angle, &mut end_angle);
411 }
412
413 let d = (end_angle - start_angle) / subdivisions as f32;
414
415 let half_thickness = thickness * 0.5;
416
417 let mut angle = start_angle;
418 while angle <= end_angle {
419 let r = Vector2::new(angle.cos(), angle.sin());
420
421 let p0 = center + r.scale(radius - half_thickness);
422 self.push_vertex(p0, Default::default());
423
424 let p1 = center + r.scale(radius + half_thickness);
425 self.push_vertex(p1, Default::default());
426
427 angle += d;
428 }
429 }
430
431 fn push_arc_path(
432 &mut self,
433 center: Vector2<f32>,
434 radius: f32,
435 angles: Range<f32>,
436 subdivisions: usize,
437 ) {
438 let mut start_angle = math::wrap_angle(angles.start);
439 let mut end_angle = math::wrap_angle(angles.end);
440
441 if start_angle > end_angle {
442 std::mem::swap(&mut start_angle, &mut end_angle);
443 }
444
445 let d = (end_angle - start_angle) / subdivisions as f32;
446
447 let mut angle = start_angle;
448 while angle <= end_angle {
449 let p0 = center + Vector2::new(angle.cos() * radius, angle.sin() * radius);
450
451 self.push_vertex(p0, Default::default());
452
453 angle += d;
454 }
455 }
456
457 fn push_line_path(&mut self, a: Vector2<f32>, b: Vector2<f32>) {
458 self.push_vertex(a, Default::default());
459 self.push_vertex(b, Default::default());
460 }
461
462 fn push_line_path_with_thickness(&mut self, a: Vector2<f32>, b: Vector2<f32>, thickness: f32) {
463 let perp = get_line_thickness_vector(a, b, thickness);
464 self.push_vertex(a - perp, Vector2::new(0.0, 0.0));
465 self.push_vertex(a + perp, Vector2::new(1.0, 1.0));
466 self.push_vertex(b - perp, Vector2::new(1.0, 0.0));
467 self.push_vertex(b + perp, Vector2::new(0.0, 1.0));
468 }
469
470 fn push_rounded_rect_filled(
471 &mut self,
472 rect: &Rect<f32>,
473 mut corner_radius: f32,
474 corner_subdivisions: usize,
475 ) {
476 let min_axis = rect.w().min(rect.h());
478 corner_radius = corner_radius.min(min_axis * 0.5);
479
480 let center_index = self.last_vertex_index();
481 self.push_vertex(rect.center(), Default::default());
482
483 self.push_line_path(
484 Vector2::new(rect.x(), rect.y() + rect.h() - corner_radius),
485 Vector2::new(rect.x(), rect.y() + corner_radius),
486 );
487
488 self.push_arc_path(
489 rect.position + Vector2::repeat(corner_radius),
490 corner_radius,
491 180.0f32.to_radians()..270.0f32.to_radians(),
492 corner_subdivisions,
493 );
494
495 self.push_line_path(
496 Vector2::new(rect.x() + corner_radius, rect.y()),
497 Vector2::new(rect.x() + rect.w() - corner_radius, rect.y()),
498 );
499
500 self.push_arc_path(
501 Vector2::new(
502 rect.position.x + rect.w() - corner_radius,
503 rect.position.y + corner_radius,
504 ),
505 corner_radius,
506 270.0f32.to_radians()..359.9999f32.to_radians(),
507 corner_subdivisions,
508 );
509
510 self.push_line_path(
511 Vector2::new(rect.x() + rect.w(), rect.y() + corner_radius),
512 Vector2::new(rect.x() + rect.w(), rect.y() + rect.h() - corner_radius),
513 );
514
515 self.push_arc_path(
516 Vector2::new(
517 rect.position.x + rect.w() - corner_radius,
518 rect.position.y + rect.h() - corner_radius,
519 ),
520 corner_radius,
521 0.0f32.to_radians()..90.0f32.to_radians(),
522 corner_subdivisions,
523 );
524
525 self.push_line_path(
526 Vector2::new(rect.x() + rect.w() - corner_radius, rect.y() + rect.h()),
527 Vector2::new(rect.x() + corner_radius, rect.y() + rect.h()),
528 );
529
530 self.push_arc_path(
531 Vector2::new(
532 rect.position.x + corner_radius,
533 rect.position.y + rect.h() - corner_radius,
534 ),
535 corner_radius,
536 90.0f32.to_radians()..180.0f32.to_radians(),
537 corner_subdivisions,
538 );
539
540 let first_index = center_index + 1;
542 let last_vertex_index = self.last_vertex_index().saturating_sub(1);
543 for i in first_index..last_vertex_index {
544 let next = i + 1;
545 self.push_triangle(i, next, center_index)
546 }
547
548 self.push_triangle(last_vertex_index, first_index, center_index);
549 }
550
551 fn push_rounded_rect(
552 &mut self,
553 rect: &Rect<f32>,
554 thickness: f32,
555 mut corner_radius: f32,
556 corner_subdivisions: usize,
557 ) {
558 let min_axis = rect.w().min(rect.h());
560 corner_radius = corner_radius.min(min_axis * 0.5);
561
562 let half_thickness = thickness * 0.5;
563
564 let start_index = self.last_vertex_index();
565
566 self.push_line_path_with_thickness(
567 Vector2::new(
568 rect.x() + half_thickness,
569 rect.y() + rect.h() - thickness - corner_radius,
570 ),
571 Vector2::new(
572 rect.x() + half_thickness,
573 rect.y() + thickness + corner_radius,
574 ),
575 thickness,
576 );
577
578 self.push_arc_path_with_thickness(
579 rect.position + Vector2::repeat(corner_radius + half_thickness),
580 corner_radius,
581 180.0f32.to_radians()..270.0f32.to_radians(),
582 corner_subdivisions,
583 thickness,
584 );
585
586 self.push_line_path_with_thickness(
587 Vector2::new(
588 rect.x() + corner_radius + half_thickness,
589 rect.y() + half_thickness,
590 ),
591 Vector2::new(
592 rect.x() + rect.w() - corner_radius - half_thickness,
593 rect.y() + half_thickness,
594 ),
595 thickness,
596 );
597
598 self.push_arc_path_with_thickness(
599 Vector2::new(
600 rect.position.x + rect.w() - corner_radius - half_thickness,
601 rect.position.y + corner_radius + half_thickness,
602 ),
603 corner_radius,
604 270.0f32.to_radians()..359.9999f32.to_radians(),
605 corner_subdivisions,
606 thickness,
607 );
608
609 self.push_line_path_with_thickness(
610 Vector2::new(
611 rect.x() + rect.w() - half_thickness,
612 rect.y() + thickness + corner_radius,
613 ),
614 Vector2::new(
615 rect.x() + rect.w() - half_thickness,
616 rect.y() + rect.h() - thickness - corner_radius,
617 ),
618 thickness,
619 );
620
621 self.push_arc_path_with_thickness(
622 Vector2::new(
623 rect.position.x + rect.w() - corner_radius - half_thickness,
624 rect.position.y + rect.h() - corner_radius - half_thickness,
625 ),
626 corner_radius,
627 0.0f32.to_radians()..90.0f32.to_radians(),
628 corner_subdivisions,
629 thickness,
630 );
631
632 self.push_line_path_with_thickness(
633 Vector2::new(
634 rect.x() + rect.w() - corner_radius - half_thickness,
635 rect.y() + rect.h() - half_thickness,
636 ),
637 Vector2::new(
638 rect.x() + corner_radius + half_thickness,
639 rect.y() + rect.h() - half_thickness,
640 ),
641 thickness,
642 );
643
644 self.push_arc_path_with_thickness(
645 Vector2::new(
646 rect.position.x + corner_radius + half_thickness,
647 rect.position.y + rect.h() - corner_radius - half_thickness,
648 ),
649 corner_radius,
650 90.0f32.to_radians()..180.0f32.to_radians(),
651 corner_subdivisions,
652 thickness,
653 );
654
655 let last_vertex_index = self.last_vertex_index();
656 self.connect_as_line(start_index, last_vertex_index, true);
657 }
658
659 fn push_bezier(
660 &mut self,
661 p0: Vector2<f32>,
662 p1: Vector2<f32>,
663 p2: Vector2<f32>,
664 p3: Vector2<f32>,
665 subdivisions: usize,
666 thickness: f32,
667 ) {
668 fn cubic_bezier(
669 p0: Vector2<f32>,
670 p1: Vector2<f32>,
671 p2: Vector2<f32>,
672 p3: Vector2<f32>,
673 t: f32,
674 ) -> Vector2<f32> {
675 p0.scale((1.0 - t).powi(3))
676 + p1.scale(3.0 * t * (1.0 - t).powi(2))
677 + p2.scale(3.0 * t.powi(2) * (1.0 - t))
678 + p3.scale(t.powi(3))
679 }
680
681 let mut prev = cubic_bezier(p0, p1, p2, p3, 0.0);
682 for i in 0..subdivisions {
683 let t = (i + 1) as f32 / subdivisions as f32;
684 let next = cubic_bezier(p0, p1, p2, p3, t);
685 self.push_line(prev, next, thickness);
688 prev = next;
689 }
690 }
691
692 fn push_grid(&mut self, zoom: f32, cell_size: Vector2<f32>, grid_bounds: Rect<f32>) {
693 let mut local_left_bottom = grid_bounds.left_top_corner();
694 local_left_bottom.x = round_to_step(local_left_bottom.x, cell_size.x);
695 local_left_bottom.y = round_to_step(local_left_bottom.y, cell_size.y);
696
697 let mut local_right_top = grid_bounds.right_bottom_corner();
698 local_right_top.x = round_to_step(local_right_top.x, cell_size.x);
699 local_right_top.y = round_to_step(local_right_top.y, cell_size.y);
700
701 let w = (local_right_top.x - local_left_bottom.x).abs();
702 let h = (local_right_top.y - local_left_bottom.y).abs();
703
704 let nw = ((w / cell_size.x).ceil()) as usize;
705 let nh = ((h / cell_size.y).ceil()) as usize;
706
707 for ny in 0..=nh {
708 let k = ny as f32 / (nh) as f32;
709 let y = local_left_bottom.y + k * h;
710 self.push_line(
711 Vector2::new(local_left_bottom.x - cell_size.x, y),
712 Vector2::new(local_right_top.x + cell_size.x, y),
713 1.0 / zoom,
714 );
715 }
716
717 for nx in 0..=nw {
718 let k = nx as f32 / (nw) as f32;
719 let x = local_left_bottom.x + k * w;
720 self.push_line(
721 Vector2::new(x, local_left_bottom.y - cell_size.y),
722 Vector2::new(x, local_right_top.y + cell_size.y),
723 1.0 / zoom,
724 );
725 }
726 }
727}
728
729#[derive(Clone, Debug)]
730pub struct TransformStack {
731 transform: Matrix3<f32>,
732 stack: Vec<Matrix3<f32>>,
733}
734
735impl Default for TransformStack {
736 fn default() -> Self {
737 Self {
738 transform: Matrix3::identity(),
739 stack: vec![],
740 }
741 }
742}
743
744impl TransformStack {
745 #[inline]
746 pub fn push(&mut self, matrix: Matrix3<f32>) {
747 self.stack
748 .push(std::mem::replace(&mut self.transform, matrix));
749 }
750
751 #[inline]
753 pub fn transform(&self) -> &Matrix3<f32> {
754 &self.transform
755 }
756
757 #[inline]
758 pub fn len(&self) -> usize {
759 self.stack.len()
760 }
761
762 pub fn is_empty(&self) -> bool {
763 self.stack.is_empty()
764 }
765
766 pub fn content(&self) -> Vec<Matrix3<f32>> {
767 self.stack.clone()
768 }
769
770 #[inline]
771 pub fn pop(&mut self) {
772 if let Some(top) = self.stack.pop() {
773 self.transform = top;
774 } else {
775 Log::err("TransformStack pop failure.")
776 }
777 }
778}
779
780#[derive(Debug, Clone)]
781pub struct DrawingContext {
782 vertex_buffer: Vec<Vertex>,
783 triangle_buffer: Vec<TriangleDefinition>,
784 command_buffer: Vec<Command>,
785 pub transform_stack: TransformStack,
786 opacity_stack: Vec<f32>,
787 triangles_to_commit: usize,
788 pub style: StyleResource,
789 pub elapsed_time: f32,
793}
794
795fn get_line_thickness_vector(a: Vector2<f32>, b: Vector2<f32>, thickness: f32) -> Vector2<f32> {
796 if let Some(dir) = (b - a).try_normalize(f32::EPSILON) {
797 Vector2::new(dir.y, -dir.x).scale(thickness * 0.5)
798 } else {
799 Vector2::default()
800 }
801}
802
803impl Draw for DrawingContext {
804 #[inline(always)]
805 fn push_vertex_raw(&mut self, mut vertex: Vertex) {
806 vertex.pos = self
807 .transform_stack
808 .transform
809 .transform_point(&Point2::from(vertex.pos))
810 .coords;
811
812 self.vertex_buffer.push(vertex);
813 }
814
815 #[inline(always)]
816 fn push_triangle(&mut self, a: u32, b: u32, c: u32) {
817 self.triangle_buffer.push(TriangleDefinition([a, b, c]));
818 self.triangles_to_commit += 1;
819 }
820
821 #[inline(always)]
822 fn last_vertex_index(&self) -> u32 {
823 self.vertex_buffer.len() as u32
824 }
825}
826
827impl DrawingContext {
828 pub fn new(style: StyleResource) -> DrawingContext {
829 DrawingContext {
830 vertex_buffer: Vec::new(),
831 triangle_buffer: Vec::new(),
832 command_buffer: Vec::new(),
833 triangles_to_commit: 0,
834 opacity_stack: vec![1.0],
835 transform_stack: Default::default(),
836 style,
837 elapsed_time: 0.0,
838 }
839 }
840
841 #[inline]
842 pub fn clear(&mut self) {
843 self.vertex_buffer.clear();
844 self.triangle_buffer.clear();
845 self.command_buffer.clear();
846 self.opacity_stack.clear();
847 self.opacity_stack.push(1.0);
848 self.triangles_to_commit = 0;
849 }
850
851 #[inline]
852 pub fn get_vertices(&self) -> &[Vertex] {
853 self.vertex_buffer.as_slice()
854 }
855
856 #[inline]
857 pub fn get_triangles(&self) -> &[TriangleDefinition] {
858 self.triangle_buffer.as_slice()
859 }
860
861 #[inline]
862 pub fn get_commands(&self) -> &Vec<Command> {
863 &self.command_buffer
864 }
865
866 pub fn push_opacity(&mut self, opacity: f32) {
867 self.opacity_stack.push(opacity);
868 }
869
870 pub fn pop_opacity(&mut self) {
871 self.opacity_stack.pop().unwrap();
872 }
873
874 pub fn triangle_points(
875 &self,
876 triangle: &TriangleDefinition,
877 ) -> Option<(&Vertex, &Vertex, &Vertex)> {
878 let a = self.vertex_buffer.get(triangle[0] as usize)?;
879 let b = self.vertex_buffer.get(triangle[1] as usize)?;
880 let c = self.vertex_buffer.get(triangle[2] as usize)?;
881 Some((a, b, c))
882 }
883
884 pub fn is_command_contains_point(&self, command: &Command, pos: Vector2<f32>) -> bool {
885 for i in command.triangles.clone() {
886 if let Some(triangle) = self.triangle_buffer.get(i) {
887 if let Some((va, vb, vc)) = self.triangle_points(triangle) {
888 if math::is_point_inside_2d_triangle(pos, va.pos, vb.pos, vc.pos) {
889 return true;
890 }
891 }
892 }
893 }
894
895 false
896 }
897
898 fn pending_range(&self) -> Range<usize> {
899 if self.triangle_buffer.is_empty() {
900 0..self.triangles_to_commit
901 } else {
902 (self.triangle_buffer.len() - self.triangles_to_commit)..self.triangle_buffer.len()
903 }
904 }
905
906 fn bounds_of(&self, range: Range<usize>) -> Rect<f32> {
907 let mut bounds = Rect::new(f32::MAX, f32::MAX, 0.0, 0.0);
908 for i in range {
909 for &k in self.triangle_buffer[i].as_ref() {
910 bounds.push(self.vertex_buffer[k as usize].pos);
911 }
912 }
913 bounds
914 }
915
916 pub fn commit(
917 &mut self,
918 clip_bounds: Rect<f32>,
919 brush: Brush,
920 texture: CommandTexture,
921 clipping_geometry: Option<ClippingGeometry>,
922 ) {
923 if self.triangles_to_commit > 0 {
924 let triangles = self.pending_range();
925 let bounds = self.bounds_of(triangles.clone());
926
927 let opacity = *self.opacity_stack.last().unwrap();
928 self.command_buffer.push(Command {
929 clip_bounds,
930 bounds,
931 brush,
932 texture,
933 triangles,
934 opacity,
935 clipping_geometry,
936 });
937 self.triangles_to_commit = 0;
938 }
939 }
940
941 pub fn draw_text(
942 &mut self,
943 clip_bounds: Rect<f32>,
944 position: Vector2<f32>,
945 formatted_text: &FormattedText,
946 ) {
947 let font = formatted_text.get_font();
948
949 #[inline(always)]
950 fn draw(
951 formatted_text: &FormattedText,
952 ctx: &mut DrawingContext,
953 clip_bounds: Rect<f32>,
954 position: Vector2<f32>,
955 dilation: f32,
956 offset: Vector2<f32>,
957 brush: Brush,
958 font: &FontResource,
959 ) {
960 let Some(mut current_page_index) = formatted_text
961 .get_glyphs()
962 .first()
963 .map(|g| g.atlas_page_index)
964 else {
965 return;
966 };
967
968 for element in formatted_text.get_glyphs() {
969 if current_page_index != element.atlas_page_index {
971 ctx.commit(
972 clip_bounds,
973 brush.clone(),
974 CommandTexture::Font {
975 font: font.clone(),
976 page_index: current_page_index,
977 height: FontHeight::from(formatted_text.super_sampled_font_size()),
980 },
981 None,
982 );
983 current_page_index = element.atlas_page_index;
984 }
985
986 let bounds = element.bounds;
987
988 let final_bounds = Rect::new(
989 position.x + bounds.x() + offset.x,
990 position.y + bounds.y() + offset.y,
991 bounds.w(),
992 bounds.h(),
993 )
994 .inflate(dilation, dilation);
995
996 ctx.push_rect_filled(&final_bounds, Some(&element.tex_coords));
997 }
998
999 ctx.commit(
1001 clip_bounds,
1002 brush,
1003 CommandTexture::Font {
1004 font: font.clone(),
1005 page_index: current_page_index,
1006 height: FontHeight::from(formatted_text.super_sampled_font_size()),
1009 },
1010 None,
1011 );
1012 }
1013
1014 if *formatted_text.shadow {
1016 draw(
1017 formatted_text,
1018 self,
1019 clip_bounds,
1020 position,
1021 *formatted_text.shadow_dilation,
1022 *formatted_text.shadow_offset,
1023 (*formatted_text.shadow_brush).clone(),
1024 &font,
1025 );
1026 }
1027
1028 draw(
1029 formatted_text,
1030 self,
1031 clip_bounds,
1032 position,
1033 0.0,
1034 Default::default(),
1035 formatted_text.brush(),
1036 &font,
1037 );
1038 }
1039}