summaryrefslogtreecommitdiff
path: root/src/exec
diff options
context:
space:
mode:
authorMartin <mhaug@live.de>2021-04-07 13:50:21 +0200
committerGitHub <noreply@github.com>2021-04-07 13:50:21 +0200
commitdf58a4d89b67783b1ffc5c3b7282302d59db8c70 (patch)
tree2bdc3a7ad1704ccee7c14972df1fa3cb9c77097a /src/exec
parent318eb9021edc493f5181247dbb7963de34126688 (diff)
parent3d2ee54848db80a8ede7e00fd5a53bc059138122 (diff)
Merge pull request #19 from typst/shape-runs 🔀
Text work
Diffstat (limited to 'src/exec')
-rw-r--r--src/exec/context.rs66
-rw-r--r--src/exec/mod.rs12
-rw-r--r--src/exec/state.rs1
3 files changed, 36 insertions, 43 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs
index 6101047e..d33d62ef 100644
--- a/src/exec/context.rs
+++ b/src/exec/context.rs
@@ -6,9 +6,8 @@ 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::parse::{is_newline, Scanner};
use crate::syntax::Span;
/// The context for execution.
@@ -73,28 +72,14 @@ impl<'a> ExecContext<'a> {
/// Push a word space into the active paragraph.
pub fn push_word_space(&mut self) {
- let em = self.state.font.resolve_size();
- let amount = self.state.par.word_spacing.resolve(em);
- self.stack.par.push_soft(ParChild::Spacing(amount));
+ self.stack.par.push_soft(self.make_text_node(" "));
}
/// Push text into the active paragraph.
///
/// The text is split into lines at newlines.
- pub fn push_text(&mut self, text: &str) {
- let mut scanner = Scanner::new(text);
- let mut text = String::new();
-
- while let Some(c) = scanner.eat_merging_crlf() {
- if is_newline(c) {
- self.stack.par.push_text(mem::take(&mut text), &self.state);
- self.linebreak();
- } else {
- text.push(c);
- }
- }
-
- self.stack.par.push_text(text, &self.state);
+ pub fn push_text(&mut self, text: impl Into<String>) {
+ self.stack.par.push(self.make_text_node(text));
}
/// Push spacing into paragraph or stack depending on `axis`.
@@ -112,7 +97,7 @@ impl<'a> ExecContext<'a> {
/// Apply a forced line break.
pub fn linebreak(&mut self) {
- self.stack.par.push_hard(ParChild::Linebreak);
+ self.stack.par.push_hard(self.make_text_node("\n"));
}
/// Apply a forced paragraph break.
@@ -140,6 +125,12 @@ impl<'a> ExecContext<'a> {
self.pagebreak(true, false, Span::default());
Pass::new(self.tree, self.diags)
}
+
+ 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(text.into(), props, align)
+ }
}
struct PageBuilder {
@@ -231,24 +222,10 @@ impl ParBuilder {
}
fn push(&mut self, child: ParChild) {
- self.children.extend(self.last.any());
- self.children.push(child);
- }
-
- fn push_text(&mut self, text: String, state: &State) {
- self.children.extend(self.last.any());
-
- let align = state.aligns.cross;
- let props = state.font.resolve_props();
-
- if let Some(ParChild::Text(prev, prev_align)) = self.children.last_mut() {
- if *prev_align == align && prev.props == props {
- prev.text.push_str(&text);
- return;
- }
+ if let Some(soft) = self.last.any() {
+ self.push_inner(soft);
}
-
- self.children.push(ParChild::Text(TextNode { text, props }, align));
+ self.push_inner(child);
}
fn push_soft(&mut self, child: ParChild) {
@@ -257,6 +234,21 @@ impl ParBuilder {
fn push_hard(&mut self, child: ParChild) {
self.last.hard();
+ self.push_inner(child);
+ }
+
+ fn push_inner(&mut self, child: ParChild) {
+ 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;
+ }
+ }
+ }
+
self.children.push(child);
}
diff --git a/src/exec/mod.rs b/src/exec/mod.rs
index 69a41beb..b6765d1e 100644
--- a/src/exec/mod.rs
+++ b/src/exec/mod.rs
@@ -64,7 +64,7 @@ impl ExecWithMap for Tree {
impl ExecWithMap for Node {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) {
match self {
- Node::Text(text) => ctx.push_text(text),
+ Node::Text(text) => ctx.push_text(text.clone()),
Node::Space => ctx.push_word_space(),
_ => map[&(self as *const _)].exec(ctx),
}
@@ -75,9 +75,9 @@ impl Exec for Value {
fn exec(&self, ctx: &mut ExecContext) {
match self {
Value::None => {}
- Value::Int(v) => ctx.push_text(&pretty(v)),
- Value::Float(v) => ctx.push_text(&pretty(v)),
- Value::Str(v) => ctx.push_text(v),
+ Value::Int(v) => ctx.push_text(pretty(v)),
+ Value::Float(v) => ctx.push_text(pretty(v)),
+ Value::Str(v) => ctx.push_text(v.clone()),
Value::Template(v) => v.exec(ctx),
Value::Error => {}
other => {
@@ -85,7 +85,7 @@ impl Exec for Value {
// the representation in monospace.
let prev = Rc::clone(&ctx.state.font.families);
ctx.set_monospace();
- ctx.push_text(&pretty(other));
+ ctx.push_text(pretty(other));
ctx.state.font.families = prev;
}
}
@@ -104,7 +104,7 @@ impl Exec for TemplateNode {
fn exec(&self, ctx: &mut ExecContext) {
match self {
Self::Tree { tree, map } => tree.exec_with_map(ctx, &map),
- Self::Str(v) => ctx.push_text(v),
+ Self::Str(v) => ctx.push_text(v.clone()),
Self::Func(v) => v.exec(ctx),
}
}
diff --git a/src/exec/state.rs b/src/exec/state.rs
index c579bc4e..82f653e9 100644
--- a/src/exec/state.rs
+++ b/src/exec/state.rs
@@ -97,6 +97,7 @@ pub struct ParState {
/// The spacing between lines (dependent on scaled font size).
pub leading: Linear,
/// The spacing between words (dependent on scaled font size).
+ // TODO: Don't ignore this.
pub word_spacing: Linear,
}