summaryrefslogtreecommitdiff
path: root/src/exec
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-04-03 17:36:33 +0200
committerLaurenz <laurmaedje@gmail.com>2021-04-03 21:09:17 +0200
commitd74c9378b81618419dc8c6315e391b6012955218 (patch)
treeae7de73aafa96b407bac5ead7bd827556133e34d /src/exec
parent8245b7b73667dcdd32b32f49729d39083d513817 (diff)
New paragraph layout 🚀
The previous paragraph layout algorithm had a couple of flaws: - It always produced line break opportunities between runs although on the textual level there might have been none. - It didn't handle trailing spacing correctly in some cases. - It wouldn't have been easily adaptable to Knuth-Plass style optimal line breaking because it was fundamentally structured first-fit run-by-run. The new paragraph layout algorithm fixes these flaws. It proceeds roughly in the following stages: 1. Collect all text in the paragraph. 2. Compute BiDi embedding levels. 3. Shape all runs, layout all children and store the resulting items in a reusable (possibly even cacheable) `ParLayout`. 3. Iterate over all line breaks in the concatenated text. 4. Construct lightweight `LineLayout` objects for full lines instead of runs. These mostly borrow from the `ParLayout` and only reshape the first and last run if necessary. The design allows to use Harfbuzz's UNSAFE_TO_BREAK mechanism to make reshaping more efficient. The size of a `LineLayout` can be measured without building the line's frame. 5. Build only the selected line's frames and stack them.
Diffstat (limited to 'src/exec')
-rw-r--r--src/exec/context.rs14
1 files changed, 8 insertions, 6 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs
index 987f9f7f..d33d62ef 100644
--- a/src/exec/context.rs
+++ b/src/exec/context.rs
@@ -6,7 +6,7 @@ use crate::env::Env;
use crate::eval::TemplateValue;
use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size};
use crate::layout::{
- AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, TextNode, Tree,
+ AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, Tree,
};
use crate::syntax::Span;
@@ -129,7 +129,7 @@ impl<'a> ExecContext<'a> {
fn make_text_node(&self, text: impl Into<String>) -> ParChild {
let align = self.state.aligns.cross;
let props = self.state.font.resolve_props();
- ParChild::Text(TextNode { text: text.into(), props }, align)
+ ParChild::Text(text.into(), props, align)
}
}
@@ -238,10 +238,12 @@ impl ParBuilder {
}
fn push_inner(&mut self, child: ParChild) {
- if let ParChild::Text(curr, curr_align) = &child {
- if let Some(ParChild::Text(prev, prev_align)) = self.children.last_mut() {
- if prev_align == curr_align && prev.props == curr.props {
- prev.text.push_str(&curr.text);
+ if let ParChild::Text(curr_text, curr_props, curr_align) = &child {
+ if let Some(ParChild::Text(prev_text, prev_props, prev_align)) =
+ self.children.last_mut()
+ {
+ if prev_align == curr_align && prev_props == curr_props {
+ prev_text.push_str(&curr_text);
return;
}
}