Allow unbreakable multi-layouters to expand (#5162)

This commit is contained in:
Laurenz 2024-10-08 17:55:44 +02:00 committed by GitHub
parent fc5858c982
commit b7725a7442
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 24 additions and 11 deletions

View File

@ -487,7 +487,7 @@ impl Packed<BlockElem> {
engine: &mut Engine,
locator: Locator,
styles: StyleChain,
base: Size,
region: Region,
) -> SourceResult<Frame> {
// Fetch sizing properties.
let width = self.width(styles);
@ -495,7 +495,7 @@ impl Packed<BlockElem> {
let inset = self.inset(styles).unwrap_or_default();
// Build the pod regions.
let pod = unbreakable_pod(&width.into(), &height, &inset, styles, base);
let pod = unbreakable_pod(&width.into(), &height, &inset, styles, region.size);
// Layout the body.
let body = self.body(styles);
@ -518,6 +518,8 @@ impl Packed<BlockElem> {
// If we have a child that wants to layout with full region access,
// we layout it.
Some(BlockBody::MultiLayouter(callback)) => {
let expand = (pod.expand | region.expand) & pod.size.map(Abs::is_finite);
let pod = Region { expand, ..pod };
callback.call(engine, locator, styles, pod.into())?.into_frame()
}
};

View File

@ -173,6 +173,7 @@ impl<'a> Collector<'a, '_, '_> {
fn block(&mut self, elem: &'a Packed<BlockElem>, styles: StyleChain<'a>) {
let locator = self.locator.next(&elem.span());
let align = AlignElem::alignment_in(styles).resolve(styles);
let alone = self.children.len() == 1;
let sticky = elem.sticky(styles);
let breakable = elem.breakable(styles);
let fr = match elem.height(styles) {
@ -193,6 +194,7 @@ impl<'a> Collector<'a, '_, '_> {
self.output.push(Child::Single(self.boxed(SingleChild {
align,
sticky,
alone,
fr,
elem,
styles,
@ -200,7 +202,6 @@ impl<'a> Collector<'a, '_, '_> {
cell: CachedCell::new(),
})));
} else {
let alone = self.children.len() == 1;
self.output.push(Child::Multi(self.boxed(MultiChild {
align,
sticky,
@ -318,6 +319,7 @@ pub struct LineChild {
pub struct SingleChild<'a> {
pub align: Axes<FixedAlignment>,
pub sticky: bool,
pub alone: bool,
pub fr: Option<Fr>,
elem: &'a Packed<BlockElem>,
styles: StyleChain<'a>,
@ -327,8 +329,10 @@ pub struct SingleChild<'a> {
impl SingleChild<'_> {
/// Build the child's frame given the region's base size.
pub fn layout(&self, engine: &mut Engine, base: Size) -> SourceResult<Frame> {
self.cell.get_or_init(base, |base| {
pub fn layout(&self, engine: &mut Engine, region: Region) -> SourceResult<Frame> {
self.cell.get_or_init(region, |mut region| {
// Vertical expansion is only kept if this block is the only child.
region.expand.y &= self.alone;
layout_single_impl(
engine.world,
engine.introspector,
@ -338,7 +342,7 @@ impl SingleChild<'_> {
self.elem,
self.locator.track(),
self.styles,
base,
region,
)
})
}
@ -356,7 +360,7 @@ fn layout_single_impl(
elem: &Packed<BlockElem>,
locator: Tracked<Locator>,
styles: StyleChain,
base: Size,
region: Region,
) -> SourceResult<Frame> {
let link = LocatorLink::new(locator);
let locator = Locator::link(&link);
@ -368,7 +372,7 @@ fn layout_single_impl(
route: Route::extend(route),
};
elem.layout_single(&mut engine, locator, styles, base)
elem.layout_single(&mut engine, locator, styles, region)
.map(|frame| frame.post_processed(styles))
}

View File

@ -226,7 +226,10 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> {
}
// Lay out the block.
let frame = single.layout(self.composer.engine, self.regions.base())?;
let frame = single.layout(
self.composer.engine,
Region::new(self.regions.base(), self.regions.expand),
)?;
// If the block doesn't fit and a followup region may improve things,
// finish the region.
@ -422,8 +425,8 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> {
for item in &self.items {
let Item::Fr(v, Some(single)) = item else { continue };
let length = v.share(frs, fr_space);
let base = Size::new(region.size.x, length);
let frame = single.layout(self.composer.engine, base)?;
let pod = Region::new(Size::new(region.size.x, length), region.expand);
let frame = single.layout(self.composer.engine, pod)?;
used.x.set_max(frame.width());
fr_frames.push(frame);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

View File

@ -32,3 +32,7 @@ Hi #box(pad(left: 10pt)[A]) there
--- issue-5044-pad-100-percent ---
#set page(width: 30pt, height: 30pt)
#pad(100%, block(width: 1cm, height: 1cm, fill: red))
--- issue-5160-unbreakable-pad ---
#set block(breakable: false)
#block(width: 100%, pad(x: 20pt, align(right)[A]))