mirror of
https://github.com/typst/typst
synced 2025-05-18 02:55:28 +08:00
use may_progress_with_repeats
This commit is contained in:
parent
2127a9e044
commit
3ec699541a
@ -81,6 +81,9 @@ pub(super) struct Current {
|
|||||||
/// This is used to quickly tell if any additional space in the region has
|
/// This is used to quickly tell if any additional space in the region has
|
||||||
/// been occupied since then.
|
/// been occupied since then.
|
||||||
pub(super) initial_after_repeats: Abs,
|
pub(super) initial_after_repeats: Abs,
|
||||||
|
/// Whether `layouter.regions.may_progress()` was `true` at the top of the
|
||||||
|
/// region.
|
||||||
|
pub(super) could_progress_at_top: bool,
|
||||||
/// Rows in the current region.
|
/// Rows in the current region.
|
||||||
pub(super) lrows: Vec<Row>,
|
pub(super) lrows: Vec<Row>,
|
||||||
/// The amount of repeated header rows at the start of the current region.
|
/// The amount of repeated header rows at the start of the current region.
|
||||||
@ -253,6 +256,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
current: Current {
|
current: Current {
|
||||||
initial: regions.size,
|
initial: regions.size,
|
||||||
initial_after_repeats: regions.size.y,
|
initial_after_repeats: regions.size.y,
|
||||||
|
could_progress_at_top: regions.may_progress(),
|
||||||
lrows: vec![],
|
lrows: vec![],
|
||||||
repeated_header_rows: 0,
|
repeated_header_rows: 0,
|
||||||
last_repeated_header_end: 0,
|
last_repeated_header_end: 0,
|
||||||
@ -1383,10 +1387,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let height = frame.height();
|
let height = frame.height();
|
||||||
while self.unbreakable_rows_left == 0
|
while self.unbreakable_rows_left == 0
|
||||||
&& !self.regions.size.y.fits(height)
|
&& !self.regions.size.y.fits(height)
|
||||||
&& may_progress_with_offset(
|
&& self.may_progress_with_repeats()
|
||||||
self.regions,
|
|
||||||
self.current.repeating_header_height + self.current.footer_height,
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
self.finish_region(engine, false)?;
|
self.finish_region(engine, false)?;
|
||||||
|
|
||||||
@ -1569,12 +1570,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let footer_would_be_widow =
|
let footer_would_be_widow =
|
||||||
matches!(self.grid.footer, Some(Repeatable::Repeated(_)))
|
matches!(self.grid.footer, Some(Repeatable::Repeated(_)))
|
||||||
&& self.current.lrows.is_empty()
|
&& self.current.lrows.is_empty()
|
||||||
&& may_progress_with_offset(
|
&& self.may_progress_with_repeats();
|
||||||
self.regions,
|
|
||||||
// Don't sum header height as we just confirmed that there
|
|
||||||
// are no headers in this region.
|
|
||||||
self.current.footer_height,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut laid_out_footer_start = None;
|
let mut laid_out_footer_start = None;
|
||||||
if !footer_would_be_widow {
|
if !footer_would_be_widow {
|
||||||
@ -1773,6 +1769,10 @@ impl<'a> GridLayouter<'a> {
|
|||||||
self.rrows.push(resolved_rows);
|
self.rrows.push(resolved_rows);
|
||||||
self.regions.next();
|
self.regions.next();
|
||||||
self.current.initial = self.regions.size;
|
self.current.initial = self.regions.size;
|
||||||
|
|
||||||
|
// Repeats haven't been laid out yet, so in the meantime, this will
|
||||||
|
// represent the initial height after repeats laid out so far, and will
|
||||||
|
// be gradually updated when preparing footers and repeating headers.
|
||||||
self.current.initial_after_repeats = self.current.initial.y;
|
self.current.initial_after_repeats = self.current.initial.y;
|
||||||
|
|
||||||
if !self.grid.headers.is_empty() {
|
if !self.grid.headers.is_empty() {
|
||||||
|
@ -3,10 +3,30 @@ use typst_library::engine::Engine;
|
|||||||
use typst_library::layout::grid::resolve::{Footer, Header, Repeatable};
|
use typst_library::layout::grid::resolve::{Footer, Header, Repeatable};
|
||||||
use typst_library::layout::{Abs, Axes, Frame, Regions};
|
use typst_library::layout::{Abs, Axes, Frame, Regions};
|
||||||
|
|
||||||
use super::layouter::{may_progress_with_offset, GridLayouter, RowState};
|
use super::layouter::{GridLayouter, RowState};
|
||||||
use super::rowspans::UnbreakableRowGroup;
|
use super::rowspans::UnbreakableRowGroup;
|
||||||
|
|
||||||
impl<'a> GridLayouter<'a> {
|
impl<'a> GridLayouter<'a> {
|
||||||
|
/// Checks whether a region break could help a situation where we're out of
|
||||||
|
/// space for the next row. The criteria are:
|
||||||
|
///
|
||||||
|
/// 1. If we could progress at the top of the region, that indicates the
|
||||||
|
/// region has a backlog, or (if we're at the first region) a region break
|
||||||
|
/// is at all possible (`regions.last` is `Some()`), so that's sufficient.
|
||||||
|
///
|
||||||
|
/// 2. Otherwise, we may progress if another region break is possible
|
||||||
|
/// (`regions.last` is still `Some()`) and non-repeating rows have been
|
||||||
|
/// placed, since that means the space they occupy will be available in the
|
||||||
|
/// next region.
|
||||||
|
pub fn may_progress_with_repeats(&self) -> bool {
|
||||||
|
// TODO(subfooters): check below isn't enough to detect non-repeating
|
||||||
|
// footers... we can also change 'initial_after_repeats' to stop being
|
||||||
|
// calculated if there were any non-repeating footers.
|
||||||
|
self.current.could_progress_at_top
|
||||||
|
|| self.regions.last.is_some()
|
||||||
|
&& self.regions.size.y != self.current.initial_after_repeats
|
||||||
|
}
|
||||||
|
|
||||||
pub fn place_new_headers(
|
pub fn place_new_headers(
|
||||||
&mut self,
|
&mut self,
|
||||||
consecutive_header_count: &mut usize,
|
consecutive_header_count: &mut usize,
|
||||||
@ -213,16 +233,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
let mut skipped_region = false;
|
let mut skipped_region = false;
|
||||||
while self.unbreakable_rows_left == 0
|
while self.unbreakable_rows_left == 0
|
||||||
&& !self.regions.size.y.fits(header_height)
|
&& !self.regions.size.y.fits(header_height)
|
||||||
&& may_progress_with_offset(
|
&& self.may_progress_with_repeats()
|
||||||
self.regions,
|
|
||||||
// - Assume footer height already starts subtracted from the
|
|
||||||
// first region's size;
|
|
||||||
// - On each iteration, we subtract footer height from the
|
|
||||||
// available size for consistency with the first region, so we
|
|
||||||
// need to consider the footer when evaluating if skipping yet
|
|
||||||
// another region would make a difference.
|
|
||||||
self.current.footer_height,
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Advance regions without any output until we can place the
|
// Advance regions without any output until we can place the
|
||||||
// header and the footer.
|
// header and the footer.
|
||||||
@ -275,8 +286,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
|
|
||||||
debug_assert!(self.current.lrows.is_empty());
|
debug_assert!(self.current.lrows.is_empty());
|
||||||
debug_assert!(self.current.lrows_orphan_snapshot.is_none());
|
debug_assert!(self.current.lrows_orphan_snapshot.is_none());
|
||||||
let may_progress =
|
let may_progress = self.may_progress_with_repeats();
|
||||||
may_progress_with_offset(self.regions, self.current.footer_height);
|
|
||||||
|
|
||||||
if may_progress {
|
if may_progress {
|
||||||
// Enable orphan prevention for headers at the top of the region.
|
// Enable orphan prevention for headers at the top of the region.
|
||||||
@ -372,16 +382,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// consider if we can already be in an unbreakable row group?
|
// consider if we can already be in an unbreakable row group?
|
||||||
while self.unbreakable_rows_left == 0
|
while self.unbreakable_rows_left == 0
|
||||||
&& !self.regions.size.y.fits(header_height)
|
&& !self.regions.size.y.fits(header_height)
|
||||||
&& may_progress_with_offset(
|
&& self.may_progress_with_repeats()
|
||||||
self.regions,
|
|
||||||
// 'finish_region' will place currently active headers and
|
|
||||||
// footers again. We assume previous pending headers have
|
|
||||||
// already been flushed, so in principle
|
|
||||||
// 'header_height == repeating_header_height' here
|
|
||||||
// (there won't be any pending headers at this point, other
|
|
||||||
// than the ones we are about to place).
|
|
||||||
self.current.repeating_header_height + self.current.footer_height,
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Note that, after the first region skip, the new headers will go
|
// Note that, after the first region skip, the new headers will go
|
||||||
// at the top of the region, but after the repeating headers that
|
// at the top of the region, but after the repeating headers that
|
||||||
@ -394,10 +395,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// TODO(subfooters): what if there is a footer right after it?
|
// TODO(subfooters): what if there is a footer right after it?
|
||||||
let should_snapshot = !short_lived
|
let should_snapshot = !short_lived
|
||||||
&& self.current.lrows_orphan_snapshot.is_none()
|
&& self.current.lrows_orphan_snapshot.is_none()
|
||||||
&& may_progress_with_offset(
|
&& self.may_progress_with_repeats();
|
||||||
self.regions,
|
|
||||||
self.current.repeating_header_height + self.current.footer_height,
|
|
||||||
);
|
|
||||||
|
|
||||||
if should_snapshot {
|
if should_snapshot {
|
||||||
// If we don't enter this branch while laying out non-short lived
|
// If we don't enter this branch while laying out non-short lived
|
||||||
|
Loading…
x
Reference in New Issue
Block a user