typst/src/library/shapes.rs

62 lines
1.9 KiB
Rust

use super::*;
/// `box`: Create a rectangular box.
///
/// # Positional arguments
/// - Body: optional, of type `template`.
///
/// # Named arguments
/// - Width of the box: `width`, of type `linear` relative to parent width.
/// - Height of the box: `height`, of type `linear` relative to parent height.
/// - Main layouting direction: `main-dir`, of type `direction`.
/// - Cross layouting direction: `cross-dir`, of type `direction`.
/// - Background color of the box: `color`, of type `color`.
///
/// # Relevant types and constants
/// - Type `direction`
/// - `ltr` (left to right)
/// - `rtl` (right to left)
/// - `ttb` (top to bottom)
/// - `btt` (bottom to top)
pub fn box_(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
let width = args.get(ctx, "width");
let height = args.get(ctx, "height");
let main = args.get(ctx, "main-dir");
let cross = args.get(ctx, "cross-dir");
let color = args.get(ctx, "color");
let body = args.find::<ValueTemplate>(ctx);
Value::template("box", move |ctx| {
let snapshot = ctx.state.clone();
ctx.set_dirs(Gen::new(main, cross));
let dirs = ctx.state.dirs;
let align = ctx.state.align;
ctx.start_content_group();
if let Some(body) = &body {
body.exec(ctx);
}
let children = ctx.end_content_group();
let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
let fixed = NodeFixed {
width,
height,
child: NodeStack { dirs, align, expand, children }.into(),
};
if let Some(color) = color {
ctx.push(NodeBackground {
fill: Fill::Color(color),
child: fixed.into(),
});
} else {
ctx.push(fixed);
}
ctx.state = snapshot;
})
}