From 56f7ede964cad235b2b39a00b2253f14b7bdad23 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 8 Jun 2023 15:50:17 +0200 Subject: [PATCH] Improve footnote handling for multi-page blocks --- library/src/layout/flow.rs | 105 +++++++++++----------- tests/ref/meta/footnote-table.png | Bin 0 -> 40162 bytes tests/typ/bugs/footnote-keep-multiple.typ | 2 +- tests/typ/meta/footnote-table.typ | 23 +++++ 4 files changed, 74 insertions(+), 56 deletions(-) create mode 100644 tests/ref/meta/footnote-table.png create mode 100644 tests/typ/meta/footnote-table.typ diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs index 8c92d4b64..65f504d54 100644 --- a/library/src/layout/flow.rs +++ b/library/src/layout/flow.rs @@ -295,11 +295,15 @@ impl<'a> FlowLayouter<'a> { // Layout the block itself. let sticky = BlockElem::sticky_in(styles); let fragment = block.layout(vt, styles, self.regions)?; + let mut notes = Vec::new(); for (i, frame) in fragment.into_iter().enumerate() { - if i > 0 - && !self.items.iter().all(|item| matches!(item, FlowItem::Footnote(_))) - { + // Find footnotes in the frame. + if self.root { + find_footnotes(&mut notes, &frame); + } + + if i > 0 { self.finish_region()?; } @@ -309,6 +313,11 @@ impl<'a> FlowLayouter<'a> { )?; } + if self.root && !self.handle_footnotes(vt, &mut notes, false)? { + self.finish_region()?; + self.handle_footnotes(vt, &mut notes, true)?; + } + self.root = is_root; self.regions.root = false; self.last_was_par = false; @@ -332,15 +341,25 @@ impl<'a> FlowLayouter<'a> { self.regions.size.y -= v } FlowItem::Fractional(_) => {} - FlowItem::Frame { ref frame, .. } => { + FlowItem::Frame { ref frame, movable, .. } => { let size = frame.size(); if !self.regions.size.y.fits(size.y) && !self.regions.in_last() { self.finish_region()?; } self.regions.size.y -= size.y; - if self.root { - return self.handle_footnotes(vt, item); + if self.root && movable { + let mut notes = Vec::new(); + find_footnotes(&mut notes, frame); + self.items.push(item); + if !self.handle_footnotes(vt, &mut notes, false)? { + let item = self.items.pop(); + self.finish_region()?; + self.items.extend(item); + self.regions.size.y -= size.y; + self.handle_footnotes(vt, &mut notes, true)?; + } + return Ok(()); } } FlowItem::Placed(_) => {} @@ -456,34 +475,18 @@ impl<'a> FlowLayouter<'a> { impl FlowLayouter<'_> { /// Processes all footnotes in the frame. #[tracing::instrument(skip_all)] - fn handle_footnotes(&mut self, vt: &mut Vt, item: FlowItem) -> SourceResult<()> { - // Find footnotes in the frame. - let mut notes = Vec::new(); + fn handle_footnotes( + &mut self, + vt: &mut Vt, + notes: &mut Vec, + force: bool, + ) -> SourceResult { + let items_len = self.items.len(); + let notes_len = notes.len(); - let mut is_movable = true; - if let FlowItem::Frame { frame, movable, .. } = &item { - find_footnotes(&mut notes, frame); - is_movable = *movable; - } - - let prev_len = self.items.len(); - self.items.push(item); - - // No new footnotes. - if notes.is_empty() { - return Ok(()); - } - - // The currently handled footnote. + // Process footnotes one at a time. let mut k = 0; - - // Whether we can still skip one region to ensure that the footnote - // and its entry are on the same page. - let mut can_skip = true; - - // Process footnotes. - 'outer: while k < notes.len() { - let had_footnotes = self.has_footnotes; + while k < notes.len() { if !self.has_footnotes { self.layout_footnote_separator(vt)?; } @@ -494,33 +497,24 @@ impl FlowLayouter<'_> { .layout(vt, self.styles, self.regions.with_root(false))? .into_frames(); - // If the entries didn't fit, undo the separator layout, move the - // item into the next region (to keep footnote and entry together) - // and try again. - if can_skip && frames.first().map_or(false, Frame::is_empty) { - // Remove separator - if !had_footnotes { - self.items.pop(); + // If the entries didn't fit, abort (to keep footnote and entry + // together). + if !force && k == 0 && frames.first().map_or(false, Frame::is_empty) { + // Remove existing footnotes attempts because we need to + // move the item to the next page. + notes.truncate(notes_len); + + // Undo region modifications. + for item in self.items.drain(items_len..) { + self.regions.size.y -= item.height(); } - if is_movable { - let moved: Vec<_> = self.items.drain(prev_len..).collect(); - self.finish_region()?; - self.has_footnotes = - moved.iter().any(|item| matches!(item, FlowItem::Footnote(_))); - self.regions.size.y -= moved.iter().map(FlowItem::height).sum(); - self.items.extend(moved); - } else { - self.finish_region()?; - } - - can_skip = false; - continue 'outer; + return Ok(false); } let prev = notes.len(); for (i, frame) in frames.into_iter().enumerate() { - find_footnotes(&mut notes, &frame); + find_footnotes(notes, &frame); if i > 0 { self.finish_region()?; self.layout_footnote_separator(vt)?; @@ -532,14 +526,15 @@ impl FlowLayouter<'_> { k += 1; - // Process the nested notes before dealing with further notes. + // Process the nested notes before dealing with further top-level + // notes. let nested = notes.len() - prev; if nested > 0 { notes[k..].rotate_right(nested); } } - Ok(()) + Ok(true) } /// Layout and save the footnote separator, typically a line. diff --git a/tests/ref/meta/footnote-table.png b/tests/ref/meta/footnote-table.png new file mode 100644 index 0000000000000000000000000000000000000000..023f8008be8de373838c90a3525989fe4f83e814 GIT binary patch literal 40162 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 literal 0 HcmV?d00001 diff --git a/tests/typ/bugs/footnote-keep-multiple.typ b/tests/typ/bugs/footnote-keep-multiple.typ index 3aa0b9d9e..e4efe3ce8 100644 --- a/tests/typ/bugs/footnote-keep-multiple.typ +++ b/tests/typ/bugs/footnote-keep-multiple.typ @@ -5,6 +5,6 @@ --- #set page(height: 100pt) -#v(30pt) +#v(40pt) A #footnote[a] \ B #footnote[b] diff --git a/tests/typ/meta/footnote-table.typ b/tests/typ/meta/footnote-table.typ new file mode 100644 index 000000000..bfbc3779c --- /dev/null +++ b/tests/typ/meta/footnote-table.typ @@ -0,0 +1,23 @@ +// Test footnotes in tables. When the table spans multiple pages, the footnotes +// will all be after the table, but it shouldn't create any empty pages. +--- + +#set page(height: 100pt) + += Tables +#table( + columns: 2, + [Hello footnote #footnote[This is a footnote.]], + [This is more text], + [This cell + #footnote[This footnote is not on the same page] + breaks over multiple pages.], + image("/tiger.jpg"), +) + +#table( + columns: 3, + ..range(1, 10) + .map(numbering.with("a")) + .map(v => upper(v) + footnote(v)) +)