flush orphans and pending headers at the same time (broken)

Goal is to ensure pending headers are flushed before a region break, else non-repeating headers will appear more than once

Must not be called while laying out headers, however, so it's broken
This commit is contained in:
PgBiel 2025-04-30 01:45:50 -03:00
parent ab852a5151
commit 3ef2137619
2 changed files with 21 additions and 5 deletions

View File

@ -254,7 +254,7 @@ impl<'a> GridLayouter<'a> {
if y >= footer.start {
if y == footer.start {
self.layout_footer(footer, engine, self.finished.len())?;
self.flush_pending_headers();
self.flush_orphans();
}
y = footer.end;
continue;
@ -266,7 +266,6 @@ impl<'a> GridLayouter<'a> {
// After the first non-header row is placed, pending headers are no
// longer orphans and can repeat, so we move them to repeating
// headers.
self.flush_pending_headers();
//
// Note that this is usually done in `push_row`, since the call to
// `layout_row` above might trigger region breaks (for multi-page
@ -275,6 +274,7 @@ impl<'a> GridLayouter<'a> {
// visible output and thus does not push any rows even though it
// was successfully laid out, in which case we additionally flush
// here just in case.
self.flush_orphans();
y += 1;
}
@ -328,7 +328,7 @@ impl<'a> GridLayouter<'a> {
self.layout_relative_row(engine, disambiguator, v, y)?
}
Sizing::Fr(v) => {
self.current.lrows_orphan_snapshot = None;
self.flush_orphans();
self.lrows.push(Row::Fr(v, y, disambiguator))
}
}
@ -1443,7 +1443,7 @@ impl<'a> GridLayouter<'a> {
fn push_row(&mut self, frame: Frame, y: usize, is_last: bool) {
// There is now a row after the rows equipped with orphan prevention,
// so no need to remove them anymore.
self.current.lrows_orphan_snapshot = None;
self.flush_orphans();
self.regions.size.y -= frame.height();
self.lrows.push(Row::Frame(frame, y, is_last));
}

View File

@ -35,7 +35,7 @@ impl<'a> GridLayouter<'a> {
// headers afterwards, which basically are not headers, for all intents
// and purposes. It is therefore guaranteed that all new headers have
// been placed at least once.
self.flush_pending_headers();
self.flush_orphans();
// Layout each conflicting header independently, without orphan
// prevention (as they don't go into 'pending_headers').
@ -139,10 +139,26 @@ impl<'a> GridLayouter<'a> {
Ok(())
}
/// This function should be called each time an additional row has been
/// laid out in a region to indicate that orphan prevention has succeeded.
///
/// It removes the current orphan snapshot and flushes pending headers,
/// such that a non-repeating header won't try to be laid out again
/// anymore, and a repeating header will begin to be part of
/// `repeating_headers`.
pub fn flush_orphans(&mut self) {
self.current.lrows_orphan_snapshot = None;
self.flush_pending_headers();
}
/// Indicates all currently pending headers have been successfully placed
/// once, since another row has been placed after them, so they are
/// certainly not orphans.
pub fn flush_pending_headers(&mut self) {
if self.pending_headers.is_empty() {
return;
}
for header in self.pending_headers {
if let Repeatable::Repeated(header) = header {
// Vector remains sorted by increasing levels: