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