MCPcopy Create free account
hub / github.com/TheRedDeveloper/ply-engine / draw_good_rounded_rectangle

Function draw_good_rounded_rectangle

src/renderer.rs:591–685  ·  view source on GitHub ↗

Draws a rounded rectangle as a single triangle-fan mesh. This avoids the visual artifacts of multi-shape rendering and handles alpha correctly.

(x: f32, y: f32, w: f32, h: f32, cr: &CornerRadii, color: Color)

Source from the content-addressed store, hash-verified

589/// Draws a rounded rectangle as a single triangle-fan mesh.
590/// This avoids the visual artifacts of multi-shape rendering and handles alpha correctly.
591fn draw_good_rounded_rectangle(x: f32, y: f32, w: f32, h: f32, cr: &CornerRadii, color: Color) {
592 use std::f32::consts::{FRAC_PI_2, PI};
593
594 if cr.top_left == 0.0 && cr.top_right == 0.0 && cr.bottom_left == 0.0 && cr.bottom_right == 0.0 {
595 draw_rectangle(x, y, w, h, color);
596 return;
597 }
598
599 // Generate outline vertices for the rounded rectangle
600 // Pre-allocate: each corner produces ~(FRAC_PI_2 * radius / PIXELS_PER_POINT).max(6) + 1 vertices
601 let est_verts = [cr.top_left, cr.top_right, cr.bottom_left, cr.bottom_right]
602 .iter()
603 .map(|&r| if r <= 0.0 { 1 } else { ((FRAC_PI_2 * r) / PIXELS_PER_POINT).max(6.0) as usize + 1 })
604 .sum::<usize>();
605 let mut outline: Vec<Vec2> = Vec::with_capacity(est_verts);
606
607 let add_arc = |outline: &mut Vec<Vec2>, cx: f32, cy: f32, radius: f32, start_angle: f32, end_angle: f32| {
608 if radius <= 0.0 {
609 outline.push(Vec2::new(cx, cy));
610 return;
611 }
612 let sides = ((FRAC_PI_2 * radius) / PIXELS_PER_POINT).max(6.0) as usize;
613 // Use incremental rotation to avoid per-point cos/sin
614 let step = (end_angle - start_angle) / sides as f32;
615 let step_cos = step.cos();
616 let step_sin = step.sin();
617 let mut dx = start_angle.cos() * radius;
618 let mut dy = start_angle.sin() * radius;
619 for _ in 0..=sides {
620 outline.push(Vec2::new(cx + dx, cy + dy));
621 let new_dx = dx * step_cos - dy * step_sin;
622 let new_dy = dx * step_sin + dy * step_cos;
623 dx = new_dx;
624 dy = new_dy;
625 }
626 };
627
628 // Top-left corner: arc from π to 3π/2
629 add_arc(&mut outline, x + cr.top_left, y + cr.top_left, cr.top_left,
630 PI, 3.0 * FRAC_PI_2);
631 // Top-right corner: arc from 3π/2 to 2π
632 add_arc(&mut outline, x + w - cr.top_right, y + cr.top_right, cr.top_right,
633 3.0 * FRAC_PI_2, 2.0 * PI);
634 // Bottom-right corner: arc from 0 to π/2
635 add_arc(&mut outline, x + w - cr.bottom_right, y + h - cr.bottom_right, cr.bottom_right,
636 0.0, FRAC_PI_2);
637 // Bottom-left corner: arc from π/2 to π
638 add_arc(&mut outline, x + cr.bottom_left, y + h - cr.bottom_left, cr.bottom_left,
639 FRAC_PI_2, PI);
640
641 let n = outline.len();
642 if n < 3 { return; }
643
644 let color_bytes = [
645 (color.r * 255.0) as u8,
646 (color.g * 255.0) as u8,
647 (color.b * 255.0) as u8,
648 (color.a * 255.0) as u8,

Callers 2

renderFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected