mirror of
https://github.com/typst/typst
synced 2025-05-19 11:35:27 +08:00
Fix multi-page paragraph bugs 🐞
This commit is contained in:
parent
d74c9378b8
commit
9014e83478
@ -128,10 +128,12 @@ impl<'a> ParLayout<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
ParChild::Any(ref node, align) => {
|
ParChild::Any(ref node, align) => {
|
||||||
for frame in node.layout(ctx, areas) {
|
let frames = node.layout(ctx, areas);
|
||||||
|
assert_eq!(frames.len(), 1);
|
||||||
|
|
||||||
|
let frame = frames.into_iter().next().unwrap();
|
||||||
items.push(ParItem::Frame(frame, align));
|
items.push(ParItem::Frame(frame, align));
|
||||||
ranges.push(range.clone());
|
ranges.push(range);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,39 +147,38 @@ impl<'a> ParLayout<'a> {
|
|||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut stack = LineStack::new(par.line_spacing, areas);
|
let mut stack = LineStack::new(par.line_spacing, areas);
|
||||||
|
|
||||||
// TODO: Provide line break opportunities on alignment changes.
|
|
||||||
let mut iter = LineBreakIterator::new(self.bidi.text).peekable();
|
|
||||||
|
|
||||||
// Find suitable line breaks.
|
// Find suitable line breaks.
|
||||||
while let Some(&(end, mandatory)) = iter.peek() {
|
// TODO: Provide line break opportunities on alignment changes.
|
||||||
assert!(start <= end);
|
for (end, mandatory) in LineBreakIterator::new(self.bidi.text) {
|
||||||
|
let mut line = LineLayout::new(&self, start .. end, ctx);
|
||||||
|
let mut size = line.measure().0;
|
||||||
|
|
||||||
let line = LineLayout::new(&self, start .. end, ctx);
|
if !stack.areas.current.fits(size) {
|
||||||
let size = line.measure().0;
|
if let Some((last_line, last_end)) = last.take() {
|
||||||
|
stack.push(last_line);
|
||||||
|
start = last_end;
|
||||||
|
line = LineLayout::new(&self, start .. end, ctx);
|
||||||
|
size = line.measure().0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find out whether the line fits.
|
if !stack.areas.current.height.fits(size.height)
|
||||||
if stack.fits(size) {
|
&& !stack.areas.in_full_last()
|
||||||
if mandatory {
|
{
|
||||||
|
stack.finish_area();
|
||||||
|
}
|
||||||
|
|
||||||
|
if mandatory || !stack.areas.current.width.fits(size.width) {
|
||||||
stack.push(line);
|
stack.push(line);
|
||||||
start = end;
|
start = end;
|
||||||
last = None;
|
last = None;
|
||||||
if end == self.bidi.text.len() {
|
|
||||||
|
if mandatory && end == self.bidi.text.len() {
|
||||||
stack.push(LineLayout::new(&self, end .. end, ctx));
|
stack.push(LineLayout::new(&self, end .. end, ctx));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
last = Some((line, end));
|
last = Some((line, end));
|
||||||
}
|
}
|
||||||
} else if let Some((line, end)) = last.take() {
|
|
||||||
stack.push(line);
|
|
||||||
stack.prepare(size.height);
|
|
||||||
start = end;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
stack.push(line);
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
iter.next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((line, _)) = last {
|
if let Some((line, _)) = last {
|
||||||
@ -433,27 +434,16 @@ impl<'a> LineStack<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fits(&self, size: Size) -> bool {
|
|
||||||
self.areas.current.fits(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare(&mut self, height: Length) {
|
|
||||||
if !self.areas.current.height.fits(height) && !self.areas.in_full_last() {
|
|
||||||
self.finish_area();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(&mut self, line: LineLayout<'a>) {
|
fn push(&mut self, line: LineLayout<'a>) {
|
||||||
let size = line.measure().0;
|
let size = line.measure().0;
|
||||||
|
|
||||||
if !self.lines.is_empty() {
|
|
||||||
self.size.height += self.line_spacing;
|
|
||||||
self.areas.current.height -= self.line_spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.size.width = self.size.width.max(size.width);
|
self.size.width = self.size.width.max(size.width);
|
||||||
self.size.height += size.height;
|
self.size.height += size.height;
|
||||||
self.areas.current.height -= size.height;
|
if !self.lines.is_empty() {
|
||||||
|
self.size.height += self.line_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.areas.current.height -= size.height + self.line_spacing;
|
||||||
self.lines.push(line);
|
self.lines.push(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,13 @@ impl Layout for StackNode {
|
|||||||
match *child {
|
match *child {
|
||||||
StackChild::Spacing(amount) => layouter.push_spacing(amount),
|
StackChild::Spacing(amount) => layouter.push_spacing(amount),
|
||||||
StackChild::Any(ref node, aligns) => {
|
StackChild::Any(ref node, aligns) => {
|
||||||
for frame in node.layout(ctx, &layouter.areas) {
|
let mut frames = node.layout(ctx, &layouter.areas).into_iter();
|
||||||
|
if let Some(frame) = frames.next() {
|
||||||
|
layouter.push_frame(frame, aligns);
|
||||||
|
}
|
||||||
|
|
||||||
|
for frame in frames {
|
||||||
|
layouter.finish_area();
|
||||||
layouter.push_frame(frame, aligns);
|
layouter.push_frame(frame, aligns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user