Allow measure to accept available size (#4264)

This commit is contained in:
+merlan #flirora 2024-05-30 03:58:07 -04:00 committed by GitHub
parent 702271dacb
commit b15aa664f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 8 deletions

View File

@ -2,17 +2,19 @@ use comemo::Tracked;
use crate::diag::{At, SourceResult}; use crate::diag::{At, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{dict, func, Content, Context, Dict, StyleChain, Styles}; use crate::foundations::{
use crate::layout::{Abs, Axes, LayoutMultiple, Regions, Size}; dict, func, Content, Context, Dict, Resolve, Smart, StyleChain, Styles,
};
use crate::layout::{Abs, Axes, LayoutMultiple, Length, Regions, Size};
use crate::syntax::Span; use crate::syntax::Span;
/// Measures the layouted size of content. /// Measures the layouted size of content.
/// ///
/// The `measure` function lets you determine the layouted size of content. Note /// The `measure` function lets you determine the layouted size of content.
/// that an infinite space is assumed, therefore the measured height/width may /// By default an infinite space is assumed, so the measured dimensions may
/// not necessarily match the final height/width of the measured content. If you /// not necessarily match the final dimensions of the content.
/// want to measure in the current layout dimensions, you can combine `measure` /// If you want to measure in the current layout dimensions, you can combine
/// and [`layout`]. /// `measure` and [`layout`].
/// ///
/// # Example /// # Example
/// The same content can have a different size depending on the [context] that /// The same content can have a different size depending on the [context] that
@ -48,6 +50,29 @@ pub fn measure(
context: Tracked<Context>, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// The width available to layout the content.
///
/// Defaults to `{auto}`, which denotes an infinite width.
///
/// Using the `width` and `height` parameters of this function is
/// different from measuring a [`box`] containing the content;
/// the former will get the dimensions of the inner content
/// instead of the dimensions of the box:
///
/// ```example
/// #context measure(lorem(100), width: 400pt)
///
/// #context measure(block(lorem(100), width: 400pt))
/// ```
#[named]
#[default(Smart::Auto)]
width: Smart<Length>,
/// The height available to layout the content.
///
/// Defaults to `{auto}`, which denotes an infinite height.
#[named]
#[default(Smart::Auto)]
height: Smart<Length>,
/// The content whose size to measure. /// The content whose size to measure.
content: Content, content: Content,
/// _Compatibility:_ This argument only exists for compatibility with /// _Compatibility:_ This argument only exists for compatibility with
@ -60,7 +85,12 @@ pub fn measure(
None => context.styles().at(span)?, None => context.styles().at(span)?,
}; };
let pod = Regions::one(Axes::splat(Abs::inf()), Axes::splat(false)); let available = Axes::new(
width.resolve(styles).unwrap_or(Abs::inf()),
height.resolve(styles).unwrap_or(Abs::inf()),
);
let pod = Regions::one(available, Axes::splat(false));
let frame = content.measure(engine, styles, pod)?.into_frame(); let frame = content.measure(engine, styles, pod)?.into_frame();
let Size { x, y } = frame.size(); let Size { x, y } = frame.size();
Ok(dict! { "width" => x, "height" => y }) Ok(dict! { "width" => x, "height" => y })

View File

@ -7,3 +7,16 @@
} }
#text(10pt, f(6pt, 8pt)) #text(10pt, f(6pt, 8pt))
#text(20pt, f(13pt, 14pt)) #text(20pt, f(13pt, 14pt))
--- measure-given-area ---
// Test `measure` given an area.
#let text = lorem(100)
#context {
let d1 = measure(text)
assert(d1.width > 2000pt)
assert(d1.height < 10pt)
let d2 = measure(width: 400pt, height: auto, text)
assert(d2.width < 400pt)
assert(d2.height > 50pt)
}