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