Fix footnote migration (#4095)

This commit is contained in:
Laurenz 2024-05-08 11:31:28 +02:00
parent 58633bf9ff
commit a7102f88dd
5 changed files with 50 additions and 26 deletions

View File

@ -141,15 +141,6 @@ enum FlowItem {
} }
impl FlowItem { impl FlowItem {
/// The inherent height of the item.
fn height(&self) -> Abs {
match self {
Self::Absolute(v, _) => *v,
Self::Fractional(_) | Self::Placed { .. } => Abs::zero(),
Self::Frame { frame, .. } | Self::Footnote(frame) => frame.height(),
}
}
/// Whether this item is out-of-flow. /// Whether this item is out-of-flow.
/// ///
/// Out-of-flow items are guaranteed to have a [`Size::zero()`]. /// Out-of-flow items are guaranteed to have a [`Size::zero()`].
@ -411,12 +402,16 @@ impl<'a> FlowLayouter<'a> {
self.finish_region(engine, false)?; self.finish_region(engine, false)?;
} }
let in_last = self.regions.in_last();
self.regions.size.y -= height; self.regions.size.y -= height;
if self.root && movable { if self.root && movable {
let mut notes = Vec::new(); let mut notes = Vec::new();
find_footnotes(&mut notes, frame); find_footnotes(&mut notes, frame);
self.items.push(item); self.items.push(item);
if !self.handle_footnotes(engine, &mut notes, true, false)? {
// When we are already in_last, we can directly force the
// footnotes.
if !self.handle_footnotes(engine, &mut notes, true, in_last)? {
let item = self.items.pop(); let item = self.items.pop();
self.finish_region(engine, false)?; self.finish_region(engine, false)?;
self.items.extend(item); self.items.extend(item);
@ -651,7 +646,16 @@ impl FlowLayouter<'_> {
engine: &mut Engine, engine: &mut Engine,
mut notes: Vec<Packed<FootnoteElem>>, mut notes: Vec<Packed<FootnoteElem>>,
) -> SourceResult<()> { ) -> SourceResult<()> {
if self.root && !self.handle_footnotes(engine, &mut notes, false, false)? { // When we are already in_last, we can directly force the
// footnotes.
if self.root
&& !self.handle_footnotes(
engine,
&mut notes,
false,
self.regions.in_last(),
)?
{
self.finish_region(engine, false)?; self.finish_region(engine, false)?;
self.handle_footnotes(engine, &mut notes, false, true)?; self.handle_footnotes(engine, &mut notes, false, true)?;
} }
@ -666,8 +670,11 @@ impl FlowLayouter<'_> {
movable: bool, movable: bool,
force: bool, force: bool,
) -> SourceResult<bool> { ) -> SourceResult<bool> {
let items_len = self.items.len(); let prev_notes_len = notes.len();
let notes_len = notes.len(); let prev_items_len = self.items.len();
let prev_size = self.regions.size;
let prev_has_footnotes = self.has_footnotes;
let prev_locator = engine.locator.clone();
// Process footnotes one at a time. // Process footnotes one at a time.
let mut k = 0; let mut k = 0;
@ -682,7 +689,6 @@ impl FlowLayouter<'_> {
} }
self.regions.size.y -= self.footnote_config.gap; self.regions.size.y -= self.footnote_config.gap;
let checkpoint = engine.locator.clone();
let frames = FootnoteEntry::new(notes[k].clone()) let frames = FootnoteEntry::new(notes[k].clone())
.pack() .pack()
.layout(engine, self.styles, self.regions.with_root(false))? .layout(engine, self.styles, self.regions.with_root(false))?
@ -694,18 +700,12 @@ impl FlowLayouter<'_> {
&& (k == 0 || movable) && (k == 0 || movable)
&& frames.first().is_some_and(Frame::is_empty) && frames.first().is_some_and(Frame::is_empty)
{ {
// Remove existing footnotes attempts because we need to // Undo everything.
// move the item to the next page. notes.truncate(prev_notes_len);
notes.truncate(notes_len); self.items.truncate(prev_items_len);
self.regions.size = prev_size;
// Undo region modifications. self.has_footnotes = prev_has_footnotes;
for item in self.items.drain(items_len..) { *engine.locator = prev_locator;
self.regions.size.y -= item.height();
}
// Undo locator modifications.
*engine.locator = checkpoint;
return Ok(false); return Ok(false);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

View File

@ -90,3 +90,20 @@ B #cite(<netwok>) #cite(<arrgh>).
#show bibliography: none #show bibliography: none
#bibliography("/assets/bib/works.bib") #bibliography("/assets/bib/works.bib")
--- issue-3481-cite-location ---
// The locator was cloned in the wrong location, leading to inconsistent
// citation group locations in the second footnote attempt.
#set page(height: 60pt)
// First page shouldn't be empty because otherwise we won't skip the first
// region which causes the bug in the first place.
#v(10pt)
// Everything moves to the second page because we want to keep the line and
// its footnotes together.
#footnote[@netwok]
#footnote[A]
#show bibliography: none
#bibliography("/assets/bib/works.bib")

View File

@ -180,3 +180,10 @@ B #footnote[b]
- #footnote[1] - #footnote[1]
- #footnote[2] - #footnote[2]
--- issue-footnotes-skip-first-page ---
// In this issue, we would get an empty page at the beginning because footnote
// layout didn't properly check for in_last.
#set page(height: 50pt)
#footnote[A]
#footnote[B]