use comemo::Tracked;
use typst_syntax::Span;
use crate::diag::{At, SourceResult};
use crate::engine::Engine;
use crate::foundations::{
Content, Context, Dict, Resolve, Smart, Target, TargetElem, dict, func,
};
use crate::introspection::{Locator, LocatorLink};
use crate::layout::{Abs, Axes, Length, Region, Size};
#[func(contextual)]
pub fn measure(
engine: &mut Engine,
context: Tracked<Context>,
span: Span,
#[named]
#[default(Smart::Auto)]
width: Smart<Length>,
#[named]
#[default(Smart::Auto)]
height: Smart<Length>,
content: Content,
) -> SourceResult<Dict> {
let styles = context.styles().at(span)?;
let pod = Region::new(
Axes::new(
width.resolve(styles).unwrap_or(Abs::inf()),
height.resolve(styles).unwrap_or(Abs::inf()),
),
Axes::splat(false),
);
let here = context.location().at(span)?;
let link = LocatorLink::measure(here);
let locator = Locator::link(&link);
let style = TargetElem::target.set(Target::Paged).wrap();
let frame = (engine.routines.layout_frame)(
engine,
&content,
locator,
styles.chain(&style),
pod,
)?;
let Size { x, y } = frame.size();
Ok(dict! { "width" => x, "height" => y })
}