mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Fix panic in spilled block layout (#5085)
This commit is contained in:
parent
04df1264ef
commit
3ec5d442d7
@ -403,6 +403,7 @@ impl<'a> MultiChild<'a> {
|
|||||||
full: regions.full,
|
full: regions.full,
|
||||||
first: regions.size.y,
|
first: regions.size.y,
|
||||||
backlog: vec![],
|
backlog: vec![],
|
||||||
|
min_backlog_len: regions.backlog.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,6 +475,7 @@ pub struct MultiSpill<'a, 'b> {
|
|||||||
first: Abs,
|
first: Abs,
|
||||||
full: Abs,
|
full: Abs,
|
||||||
backlog: Vec<Abs>,
|
backlog: Vec<Abs>,
|
||||||
|
min_backlog_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MultiSpill<'_, '_> {
|
impl MultiSpill<'_, '_> {
|
||||||
@ -483,17 +485,18 @@ impl MultiSpill<'_, '_> {
|
|||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
regions: Regions,
|
regions: Regions,
|
||||||
) -> SourceResult<(Frame, Option<Self>)> {
|
) -> SourceResult<(Frame, Option<Self>)> {
|
||||||
// We build regions for the whole `MultiChild` with the sizes passed to
|
// The first region becomes unchangable and committed to our backlog.
|
||||||
// earlier parts of it plus the new regions. Then, we layout the
|
|
||||||
// complete block, but extract only the suffix that interests us.
|
|
||||||
self.backlog.push(regions.size.y);
|
self.backlog.push(regions.size.y);
|
||||||
|
|
||||||
|
// The remaining regions are ephemeral and may be replaced.
|
||||||
let mut backlog: Vec<_> =
|
let mut backlog: Vec<_> =
|
||||||
self.backlog.iter().chain(regions.backlog).copied().collect();
|
self.backlog.iter().chain(regions.backlog).copied().collect();
|
||||||
|
|
||||||
// Remove unnecessary backlog items (also to prevent it from growing
|
// Remove unnecessary backlog items to prevent it from growing
|
||||||
// unnecessarily, which would change the region's hash).
|
// unnecessarily, changing the region's hash.
|
||||||
while !backlog.is_empty() && backlog.last().copied() == regions.last {
|
while backlog.len() > self.min_backlog_len
|
||||||
|
&& backlog.last().copied() == regions.last
|
||||||
|
{
|
||||||
backlog.pop();
|
backlog.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,6 +516,16 @@ impl MultiSpill<'_, '_> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.skip(self.backlog.len());
|
.skip(self.backlog.len());
|
||||||
|
|
||||||
|
// Ensure that the backlog never shrinks, so that unwrapping below is at
|
||||||
|
// least fairly safe. Note that the whole region juggling here is
|
||||||
|
// fundamentally not ideal: It is a compatibility layer between the old
|
||||||
|
// (all regions provided upfront) & new (each region provided on-demand,
|
||||||
|
// like an iterator) layout model. This approach is not 100% correct, as
|
||||||
|
// in the old model later regions could have an effect on earlier
|
||||||
|
// frames, but it's the best we can do for now, until the multi
|
||||||
|
// layouters are refactored to the new model.
|
||||||
|
self.min_backlog_len = self.min_backlog_len.max(backlog.len());
|
||||||
|
|
||||||
// Save the first frame.
|
// Save the first frame.
|
||||||
let frame = frames.next().unwrap();
|
let frame = frames.next().unwrap();
|
||||||
|
|
||||||
|
BIN
tests/ref/issue-5024-spill-backlog.png
Normal file
BIN
tests/ref/issue-5024-spill-backlog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 270 B |
@ -76,3 +76,7 @@ Hi
|
|||||||
#block(rect(width: 80%, height: 80pt), breakable: false)
|
#block(rect(width: 80%, height: 80pt), breakable: false)
|
||||||
#lines(6)
|
#lines(6)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
--- issue-5024-spill-backlog ---
|
||||||
|
#set page(columns: 2, height: 50pt)
|
||||||
|
#columns(2)[Hello]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user