1use crate::color::Color;
9use crate::scene::Fill;
10use crate::scene::vector::{Vector, VectorShape, VectorStroke};
11
12pub struct Highlight;
18
19impl Highlight {
20 #[must_use]
23 pub fn outline(shape: VectorShape, color: Color, width: f32) -> Vector {
24 Vector::new(shape).with_stroke(VectorStroke::new(width, color))
25 }
26
27 #[must_use]
32 pub fn filled(shape: VectorShape, color: Color, alpha: f32) -> Vector {
33 let alpha = alpha.clamp(0.0, 1.0);
34 Vector::new(shape).with_fill(Fill::Solid(color.with_alpha(color.a * alpha)))
35 }
36
37 #[must_use]
41 pub fn pill(rect: crate::math::Rect, color: Color, alpha: f32) -> Vector {
42 let radius = (rect.size.y * 0.5).abs();
43 Self::filled(VectorShape::rounded_rect(rect, radius), color, alpha)
44 }
45
46 #[must_use]
51 pub fn glow(shape: VectorShape, color: Color, width: f32) -> Vector {
52 Vector::new(shape).with_stroke(VectorStroke::new(width, color.with_alpha(color.a * 0.4)))
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use crate::math::Rect;
60
61 #[test]
62 fn outline_has_stroke_no_fill() {
63 let v = Highlight::outline(
64 VectorShape::rect(Rect::new(-0.5, -0.5, 1.0, 1.0)),
65 Color::WHITE,
66 0.05,
67 );
68 assert!(v.fill.is_none());
69 let s = v.stroke.expect("outline has stroke");
70 assert!((s.width - 0.05).abs() < f32::EPSILON);
71 }
72
73 #[test]
74 fn filled_alpha_multiplies_color() {
75 let base = Color::rgba(0.5, 0.5, 0.5, 1.0);
76 let v = Highlight::filled(VectorShape::circle(glam::Vec2::ZERO, 0.4), base, 0.5);
77 let Some(Fill::Solid(c)) = v.fill else {
78 panic!("expected solid fill");
79 };
80 assert!((c.a - 0.5).abs() < f32::EPSILON);
81 }
82
83 #[test]
84 fn pill_uses_half_height_radius() {
85 let v = Highlight::pill(Rect::new(-0.5, -0.05, 1.0, 0.1), Color::WHITE, 0.6);
86 match &v.shape {
87 VectorShape::RoundedRect { radius, .. } => {
88 assert!((radius - 0.05).abs() < f32::EPSILON);
89 }
90 _ => panic!("pill should be a rounded rect"),
91 }
92 }
93
94 #[test]
95 fn glow_alpha_scales_down_to_indicate_softness() {
96 let v = Highlight::glow(
97 VectorShape::rect(Rect::new(-0.5, -0.5, 1.0, 1.0)),
98 Color::rgba(1.0, 1.0, 1.0, 1.0),
99 0.1,
100 );
101 let s = v.stroke.expect("glow has stroke");
102 assert!((s.color.a - 0.4).abs() < 1e-3);
103 }
104}