use std::f64::consts::SQRT_2; use super::prelude::*; /// `rect`: A rectangle with optional content. pub fn rect(_: &mut EvalContext, args: &mut Args) -> TypResult { let width = args.named("width")?; let height = args.named("height")?; shape_impl(args, ShapeKind::Rect, width, height) } /// `square`: A square with optional content. pub fn square(_: &mut EvalContext, args: &mut Args) -> TypResult { let size = args.named::("size")?.map(Linear::from); let width = match size { None => args.named("width")?, size => size, }; let height = match size { None => args.named("height")?, size => size, }; shape_impl(args, ShapeKind::Square, width, height) } /// `ellipse`: An ellipse with optional content. pub fn ellipse(_: &mut EvalContext, args: &mut Args) -> TypResult { let width = args.named("width")?; let height = args.named("height")?; shape_impl(args, ShapeKind::Ellipse, width, height) } /// `circle`: A circle with optional content. pub fn circle(_: &mut EvalContext, args: &mut Args) -> TypResult { let diameter = args.named("radius")?.map(|r: Length| 2.0 * Linear::from(r)); let width = match diameter { None => args.named("width")?, diameter => diameter, }; let height = match diameter { None => args.named("height")?, diameter => diameter, }; shape_impl(args, ShapeKind::Circle, width, height) } fn shape_impl( args: &mut Args, kind: ShapeKind, width: Option, height: Option, ) -> TypResult { // The default appearance of a shape. let default = Stroke { paint: RgbaColor::BLACK.into(), thickness: Length::pt(1.0), }; // Parse fill & stroke. let fill = args.named("fill")?.unwrap_or(None); let stroke = match (args.named("stroke")?, args.named("thickness")?) { (None, None) => fill.is_none().then(|| default), (color, thickness) => color.unwrap_or(Some(default.paint)).map(|paint| Stroke { paint, thickness: thickness.unwrap_or(default.thickness), }), }; // Shorthand for padding. let mut padding = args.named::("padding")?.unwrap_or_default(); // Padding with this ratio ensures that a rectangular child fits // perfectly into a circle / an ellipse. if kind.is_round() { padding.rel += Relative::new(0.5 - SQRT_2 / 4.0); } // The shape's contents. let body = args.find::