use windows_sys::Win32::Foundation::RECT;
use winspaces_win32::dpi::px;
pub const HEIGHT: i32 = 60;
pub const PAD_X: i32 = 32;
pub const MIN_WIDTH: i32 = 168;
pub const GAP: i32 = 16;
pub const RADIUS: i32 = 10;
pub const FONT_HEIGHT: i32 = 20;
pub fn indicator_rect(work: RECT, scale: f32, text_w: i32) -> RECT {
let work_w = (work.right - work.left).max(1);
let work_h = (work.bottom - work.top).max(1);
let width = (text_w + 2 * px(scale, PAD_X))
.max(px(scale, MIN_WIDTH))
.min(work_w);
let height = px(scale, HEIGHT).min(work_h);
let left = work.left + (work_w - width) / 2;
let bottom = (work.bottom - px(scale, GAP)).max(work.top + height);
let top = bottom - height;
RECT {
left,
top,
right: left + width,
bottom: top + height,
}
}
pub fn round_rect_coverage(x: i32, y: i32, w: i32, h: i32, radius: f32, inset: f32) -> f32 {
let px_ = (x as f32 + 0.5) - w as f32 / 2.0;
let py = (y as f32 + 0.5) - h as f32 / 2.0;
let half_w = w as f32 / 2.0 - inset;
let half_h = h as f32 / 2.0 - inset;
if half_w <= 0.0 || half_h <= 0.0 {
return 0.0;
}
let r = radius.min(half_w).min(half_h).max(0.0);
let qx = px_.abs() - (half_w - r);
let qy = py.abs() - (half_h - r);
let outside = (qx.max(0.0).powi(2) + qy.max(0.0).powi(2)).sqrt();
let inside = qx.max(qy).min(0.0);
let dist = outside + inside - r;
(0.5 - dist).clamp(0.0, 1.0)
}
pub fn smoothstep(t: f32) -> f32 {
let t = t.clamp(0.0, 1.0);
t * t * (3.0 - 2.0 * t)
}
#[cfg(test)]
mod tests {
use super::*;
fn work() -> RECT {
RECT {
left: 0,
top: 0,
right: 1920,
bottom: 1032, }
}
#[test]
fn panel_is_horizontally_centered() {
let r = indicator_rect(work(), 1.0, 80);
let width = r.right - r.left;
assert_eq!(r.left, (1920 - width) / 2);
assert_eq!(1920 - r.right, r.left);
}
#[test]
fn panel_rests_above_the_work_area_bottom() {
let r = indicator_rect(work(), 1.0, 80);
assert_eq!(r.bottom, 1032 - GAP);
assert_eq!(r.bottom - r.top, HEIGHT);
}
#[test]
fn narrow_labels_hit_the_width_floor() {
let r = indicator_rect(work(), 1.0, 10);
assert_eq!(r.right - r.left, MIN_WIDTH);
}
#[test]
fn wide_labels_grow_past_the_floor() {
let r = indicator_rect(work(), 1.0, 400);
assert_eq!(r.right - r.left, 400 + 2 * PAD_X);
}
#[test]
fn scale_applies_to_every_metric() {
let r = indicator_rect(work(), 2.0, 10);
assert_eq!(r.right - r.left, MIN_WIDTH * 2);
assert_eq!(r.bottom - r.top, HEIGHT * 2);
assert_eq!(r.bottom, 1032 - GAP * 2);
}
#[test]
fn panel_never_exceeds_a_narrow_work_area() {
let narrow = RECT {
left: 100,
top: 0,
right: 220,
bottom: 300,
};
let r = indicator_rect(narrow, 1.0, 400);
assert_eq!(r.left, 100);
assert_eq!(r.right, 220);
}
#[test]
fn offset_monitor_keeps_its_own_origin() {
let secondary = RECT {
left: -1920,
top: 0,
right: 0,
bottom: 1032,
};
let r = indicator_rect(secondary, 1.0, 80);
let width = r.right - r.left;
assert_eq!(r.left, -1920 + (1920 - width) / 2);
assert!(r.right <= 0);
}
#[test]
fn coverage_is_solid_at_the_center_and_empty_outside() {
assert_eq!(round_rect_coverage(50, 30, 100, 60, 10.0, 0.0), 1.0);
assert_eq!(round_rect_coverage(0, 0, 100, 60, 10.0, 0.0), 0.0);
}
#[test]
fn coverage_rises_monotonically_moving_inward() {
let samples: Vec<f32> = (0..12)
.map(|i| round_rect_coverage(i, i, 100, 60, 10.0, 0.0))
.collect();
for pair in samples.windows(2) {
assert!(pair[1] >= pair[0], "coverage must rise moving inward");
}
}
#[test]
fn corner_arc_is_anti_aliased() {
let partials = (0..14)
.flat_map(|y| (0..14).map(move |x| round_rect_coverage(x, y, 100, 60, 10.0, 0.0)))
.filter(|c| *c > 0.0 && *c < 1.0)
.count();
assert!(
partials > 0,
"the corner arc must produce fractional coverage"
);
}
#[test]
fn inset_shrinks_the_covered_area() {
let outer = round_rect_coverage(50, 1, 100, 60, 10.0, 0.0);
let inner = round_rect_coverage(50, 1, 100, 60, 10.0, 2.0);
assert!(outer > inner);
}
#[test]
fn smoothstep_is_clamped_and_monotonic() {
assert_eq!(smoothstep(-1.0), 0.0);
assert_eq!(smoothstep(0.0), 0.0);
assert_eq!(smoothstep(1.0), 1.0);
assert_eq!(smoothstep(2.0), 1.0);
assert!(smoothstep(0.25) < smoothstep(0.5));
assert!(smoothstep(0.5) < smoothstep(0.75));
}
}