summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/layout/par.rs80
-rw-r--r--src/layout/stack.rs8
2 files changed, 42 insertions, 46 deletions
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 3e35333d..5232c946 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -128,10 +128,12 @@ impl<'a> ParLayout<'a> {
});
}
ParChild::Any(ref node, align) => {
- for frame in node.layout(ctx, areas) {
- items.push(ParItem::Frame(frame, align));
- ranges.push(range.clone());
- }
+ let frames = node.layout(ctx, areas);
+ assert_eq!(frames.len(), 1);
+
+ let frame = frames.into_iter().next().unwrap();
+ items.push(ParItem::Frame(frame, align));
+ ranges.push(range);
}
}
}
@@ -145,39 +147,38 @@ impl<'a> ParLayout<'a> {
let mut last = None;
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.
- while let Some(&(end, mandatory)) = iter.peek() {
- assert!(start <= end);
-
- let line = LineLayout::new(&self, start .. end, ctx);
- let size = line.measure().0;
-
- // Find out whether the line fits.
- if stack.fits(size) {
- if mandatory {
- stack.push(line);
- start = end;
- last = None;
- if end == self.bidi.text.len() {
- stack.push(LineLayout::new(&self, end .. end, ctx));
- }
- } else {
- last = Some((line, end));
+ // TODO: Provide line break opportunities on alignment changes.
+ for (end, mandatory) in LineBreakIterator::new(self.bidi.text) {
+ let mut line = LineLayout::new(&self, start .. end, ctx);
+ let mut size = line.measure().0;
+
+ if !stack.areas.current.fits(size) {
+ 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;
}
- } else if let Some((line, end)) = last.take() {
+ }
+
+ if !stack.areas.current.height.fits(size.height)
+ && !stack.areas.in_full_last()
+ {
+ stack.finish_area();
+ }
+
+ if mandatory || !stack.areas.current.width.fits(size.width) {
stack.push(line);
- stack.prepare(size.height);
start = end;
- continue;
+ last = None;
+
+ if mandatory && end == self.bidi.text.len() {
+ stack.push(LineLayout::new(&self, end .. end, ctx));
+ }
} else {
- stack.push(line);
- start = end;
+ last = Some((line, end));
}
-
- iter.next();
}
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>) {
let size = line.measure().0;
+ self.size.width = self.size.width.max(size.width);
+ self.size.height += size.height;
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.height += size.height;
- self.areas.current.height -= size.height;
+ self.areas.current.height -= size.height + self.line_spacing;
self.lines.push(line);
}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index 8e2249d2..b69936ba 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -28,7 +28,13 @@ impl Layout for StackNode {
match *child {
StackChild::Spacing(amount) => layouter.push_spacing(amount),
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);
}
}