#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ShapeScale {
pub none: f64,
pub extra_small: f64,
pub small: f64,
pub medium: f64,
pub large: f64,
pub large_increased: f64,
pub extra_large: f64,
pub extra_large_increased: f64,
pub extra_extra_large: f64,
pub full: f64,
}
impl ShapeScale {
pub const fn neutral() -> Self {
Self {
none: 0.0,
extra_small: 4.0,
small: 8.0,
medium: 12.0,
large: 16.0,
large_increased: 20.0,
extra_large: 28.0,
extra_large_increased: 32.0,
extra_extra_large: 48.0,
full: f64::INFINITY,
}
}
pub fn resolve(radius: f64, width: f64, height: f64) -> f64 {
let pill = width.min(height) / 2.0;
if radius.is_infinite() {
pill
} else {
radius.min(pill)
}
}
pub fn concentric_inner(outer_radius: f64, inset: f64) -> f64 {
if outer_radius.is_infinite() {
f64::INFINITY
} else {
(outer_radius - inset).max(0.0)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn matches_table() {
let s = ShapeScale::neutral();
assert_eq!(s.none, 0.0);
assert_eq!(s.extra_small, 4.0);
assert_eq!(s.small, 8.0);
assert_eq!(s.medium, 12.0);
assert_eq!(s.large, 16.0);
assert_eq!(s.large_increased, 20.0);
assert_eq!(s.extra_large, 28.0);
assert_eq!(s.extra_large_increased, 32.0);
assert_eq!(s.extra_extra_large, 48.0);
assert!(s.full.is_infinite());
}
#[test]
fn full_resolves_to_pill_radius() {
let s = ShapeScale::neutral();
assert_eq!(ShapeScale::resolve(s.full, 100.0, 40.0), 20.0);
}
#[test]
fn finite_radius_passes_through_when_smaller_than_pill() {
let s = ShapeScale::neutral();
assert_eq!(ShapeScale::resolve(s.medium, 200.0, 200.0), 12.0);
}
#[test]
fn finite_radius_clamps_when_larger_than_pill() {
assert_eq!(ShapeScale::resolve(1000.0, 40.0, 20.0), 10.0);
}
#[test]
fn concentric_inner_normal_nesting() {
assert_eq!(ShapeScale::concentric_inner(20.0, 4.0), 16.0);
}
#[test]
fn concentric_inner_zero_outer_radius() {
assert_eq!(ShapeScale::concentric_inner(0.0, 5.0), 0.0);
}
#[test]
fn concentric_inner_zero_inset() {
assert_eq!(ShapeScale::concentric_inner(20.0, 0.0), 20.0);
}
#[test]
fn concentric_inner_clamps_at_zero() {
assert_eq!(ShapeScale::concentric_inner(8.0, 12.0), 0.0);
}
#[test]
fn concentric_inner_inset_equals_outer() {
assert_eq!(ShapeScale::concentric_inner(15.0, 15.0), 0.0);
}
#[test]
fn concentric_inner_with_infinity() {
assert!(ShapeScale::concentric_inner(f64::INFINITY, 4.0).is_infinite());
assert!(ShapeScale::concentric_inner(f64::INFINITY, 100.0).is_infinite());
}
}