Don't allocate tag frames

This commit is contained in:
Laurenz 2025-07-18 13:42:35 +02:00
parent 315a3f192e
commit 912370abde

View File

@ -520,14 +520,22 @@ pub fn commit(
let mut top = Abs::zero(); let mut top = Abs::zero();
let mut bottom = Abs::zero(); let mut bottom = Abs::zero();
enum Final<'a> {
Frame(Frame),
Tag(&'a Tag),
}
// Build the frames and determine the height and baseline. // Build the frames and determine the height and baseline.
let mut frames = vec![]; let mut finals = vec![];
for &(idx, ref item) in line.items.indexed_iter() { for &(idx, ref item) in line.items.indexed_iter() {
let mut push = |offset: &mut Abs, frame: Frame, idx: usize| { let mut push = |finals: &mut Vec<(Abs, Final, usize)>,
offset: &mut Abs,
frame: Frame,
idx: usize| {
let width = frame.width(); let width = frame.width();
top.set_max(frame.baseline()); top.set_max(frame.baseline());
bottom.set_max(frame.size().y - frame.baseline()); bottom.set_max(frame.size().y - frame.baseline());
frames.push((*offset, frame, idx)); finals.push((*offset, Final::Frame(frame), idx));
*offset += width; *offset += width;
}; };
@ -543,7 +551,7 @@ pub fn commit(
layout_box(elem, engine, loc.relayout(), styles, region) layout_box(elem, engine, loc.relayout(), styles, region)
})?; })?;
apply_shift(&engine.world, &mut frame, *styles); apply_shift(&engine.world, &mut frame, *styles);
push(&mut offset, frame, idx); push(&mut finals, &mut offset, frame, idx);
} else { } else {
offset += amount; offset += amount;
} }
@ -555,15 +563,13 @@ pub fn commit(
justification_ratio, justification_ratio,
extra_justification, extra_justification,
); );
push(&mut offset, frame, idx); push(&mut finals, &mut offset, frame, idx);
} }
Item::Frame(frame) => { Item::Frame(frame) => {
push(&mut offset, frame.clone(), idx); push(&mut finals, &mut offset, frame.clone(), idx);
} }
Item::Tag(tag) => { Item::Tag(tag) => {
let mut frame = Frame::soft(Size::zero()); finals.push((offset, Final::Tag(tag), idx));
frame.push(Point::zero(), FrameItem::Tag((*tag).clone()));
frames.push((offset, frame, idx));
} }
Item::Skip(_) => {} Item::Skip(_) => {}
} }
@ -585,14 +591,21 @@ pub fn commit(
// Ensure that the final frame's items are in logical order rather than in // Ensure that the final frame's items are in logical order rather than in
// visual order. This is important because it affects the order of elements // visual order. This is important because it affects the order of elements
// during introspection and thus things like counters. // during introspection and thus things like counters.
frames.sort_unstable_by_key(|(_, _, idx)| *idx); finals.sort_unstable_by_key(|(_, _, idx)| *idx);
// Construct the line's frame. // Construct the line's frame.
for (offset, frame, _) in frames { for (offset, f, _) in finals {
let x = offset + p.config.align.position(remaining); let x = offset + p.config.align.position(remaining);
match f {
Final::Frame(frame) => {
let y = top - frame.baseline(); let y = top - frame.baseline();
output.push_frame(Point::new(x, y), frame); output.push_frame(Point::new(x, y), frame);
} }
Final::Tag(tag) => {
output.push(Point::new(x, top), FrameItem::Tag(tag.clone()));
}
}
}
Ok(output) Ok(output)
} }