mirror of
https://github.com/typst/typst
synced 2025-05-18 11:05:28 +08:00
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:
parent
ab852a5151
commit
3ef2137619
@ -254,7 +254,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
if y >= footer.start {
|
if y >= footer.start {
|
||||||
if y == footer.start {
|
if y == footer.start {
|
||||||
self.layout_footer(footer, engine, self.finished.len())?;
|
self.layout_footer(footer, engine, self.finished.len())?;
|
||||||
self.flush_pending_headers();
|
self.flush_orphans();
|
||||||
}
|
}
|
||||||
y = footer.end;
|
y = footer.end;
|
||||||
continue;
|
continue;
|
||||||
@ -266,7 +266,6 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// After the first non-header row is placed, pending headers are no
|
// After the first non-header row is placed, pending headers are no
|
||||||
// longer orphans and can repeat, so we move them to repeating
|
// longer orphans and can repeat, so we move them to repeating
|
||||||
// headers.
|
// headers.
|
||||||
self.flush_pending_headers();
|
|
||||||
//
|
//
|
||||||
// Note that this is usually done in `push_row`, since the call to
|
// Note that this is usually done in `push_row`, since the call to
|
||||||
// `layout_row` above might trigger region breaks (for multi-page
|
// `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
|
// visible output and thus does not push any rows even though it
|
||||||
// was successfully laid out, in which case we additionally flush
|
// was successfully laid out, in which case we additionally flush
|
||||||
// here just in case.
|
// here just in case.
|
||||||
|
self.flush_orphans();
|
||||||
|
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
@ -328,7 +328,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.layout_relative_row(engine, disambiguator, v, y)?
|
self.layout_relative_row(engine, disambiguator, v, y)?
|
||||||
}
|
}
|
||||||
Sizing::Fr(v) => {
|
Sizing::Fr(v) => {
|
||||||
self.current.lrows_orphan_snapshot = None;
|
self.flush_orphans();
|
||||||
self.lrows.push(Row::Fr(v, y, disambiguator))
|
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) {
|
fn push_row(&mut self, frame: Frame, y: usize, is_last: bool) {
|
||||||
// There is now a row after the rows equipped with orphan prevention,
|
// There is now a row after the rows equipped with orphan prevention,
|
||||||
// so no need to remove them anymore.
|
// so no need to remove them anymore.
|
||||||
self.current.lrows_orphan_snapshot = None;
|
self.flush_orphans();
|
||||||
self.regions.size.y -= frame.height();
|
self.regions.size.y -= frame.height();
|
||||||
self.lrows.push(Row::Frame(frame, y, is_last));
|
self.lrows.push(Row::Frame(frame, y, is_last));
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// headers afterwards, which basically are not headers, for all intents
|
// headers afterwards, which basically are not headers, for all intents
|
||||||
// and purposes. It is therefore guaranteed that all new headers have
|
// and purposes. It is therefore guaranteed that all new headers have
|
||||||
// been placed at least once.
|
// been placed at least once.
|
||||||
self.flush_pending_headers();
|
self.flush_orphans();
|
||||||
|
|
||||||
// Layout each conflicting header independently, without orphan
|
// Layout each conflicting header independently, without orphan
|
||||||
// prevention (as they don't go into 'pending_headers').
|
// prevention (as they don't go into 'pending_headers').
|
||||||
@ -139,10 +139,26 @@ impl<'a> GridLayouter<'a> {
|
|||||||
Ok(())
|
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
|
/// Indicates all currently pending headers have been successfully placed
|
||||||
/// once, since another row has been placed after them, so they are
|
/// once, since another row has been placed after them, so they are
|
||||||
/// certainly not orphans.
|
/// certainly not orphans.
|
||||||
pub fn flush_pending_headers(&mut self) {
|
pub fn flush_pending_headers(&mut self) {
|
||||||
|
if self.pending_headers.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for header in self.pending_headers {
|
for header in self.pending_headers {
|
||||||
if let Repeatable::Repeated(header) = header {
|
if let Repeatable::Repeated(header) = header {
|
||||||
// Vector remains sorted by increasing levels:
|
// Vector remains sorted by increasing levels:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user