diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-16 22:14:27 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-16 22:39:21 +0200 |
| commit | 30f16bbf6431ca0c174ca0a1abaa6a13ef50ab06 (patch) | |
| tree | f5a5c0adad15840ebe24b39e77ff467862067c91 /src/library/font.rs | |
| parent | 9f6137d8a829fe8f34554623495fa620252a0184 (diff) | |
Add Value type and replace dyn-nodes with call-exprs 🏗
- In addition to syntax trees there are now `Value`s, which syntax trees can be evaluated into (e.g. the tree is `5+5` and the value is `10`)
- Parsing is completely pure, function calls are not parsed into nodes, but into simple call expressions, which are resolved later
- Functions aren't dynamic nodes anymore, but simply functions which receive their arguments as a table and the layouting context
- Functions may return any `Value`
- Layouting is powered by functions which return the new `Commands` value, which informs the layouting engine what to do
- When a function returns a non-`Commands` value, the layouter simply dumps the value into the document in monospace
Diffstat (limited to 'src/library/font.rs')
| -rw-r--r-- | src/library/font.rs | 110 |
1 files changed, 45 insertions, 65 deletions
diff --git a/src/library/font.rs b/src/library/font.rs index 8787cc91..71e9552f 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -18,80 +18,60 @@ use super::*; /// ```typst /// serif = ("Source Serif Pro", "Noto Serif") /// ``` -pub fn font(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> { +pub async fn font(mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); - let mut args = call.args; - let node = FontNode { - content: args.take::<SyntaxTree>(), - size: args.take::<ScaleLength>(), - style: args.take_with_key::<_, FontStyle>("style", &mut f), - weight: args.take_with_key::<_, FontWeight>("weight", &mut f), - width: args.take_with_key::<_, FontWidth>("width", &mut f), - list: args.take_all_num_vals::<StringLike>() - .map(|s| s.0.to_lowercase()) - .collect(), - classes: args.take_all_str::<TableExpr>() - .map(|(class, mut table)| { - let fallback = table.take_all_num_vals::<StringLike>() - .map(|s| s.0.to_lowercase()) - .collect(); - (class, fallback) - }) - .collect() - }; + let content = args.take::<SyntaxTree>(); + let size = args.take::<ScaleLength>(); + let style = args.take_with_key::<_, FontStyle>("style", &mut f); + let weight = args.take_with_key::<_, FontWeight>("weight", &mut f); + let width = args.take_with_key::<_, FontWidth>("width", &mut f); + let list: Vec<_> = args.take_all_num_vals::<StringLike>() + .map(|s| s.0.to_lowercase()) + .collect(); + let classes: Vec<(_, Vec<_>)> = args.take_all_str::<TableValue>() + .map(|(class, mut table)| { + let fallback = table.take_all_num_vals::<StringLike>() + .map(|s| s.0.to_lowercase()) + .collect(); + (class, fallback) + }) + .collect(); args.unexpected(&mut f); - Pass::node(node, f) -} - -#[derive(Debug, Clone, PartialEq)] -struct FontNode { - content: Option<SyntaxTree>, - size: Option<ScaleLength>, - style: Option<FontStyle>, - weight: Option<FontWeight>, - width: Option<FontWidth>, - list: Vec<String>, - classes: Vec<(String, Vec<String>)>, -} - -#[async_trait(?Send)] -impl Layout for FontNode { - async fn layout<'a>(&'a self, ctx: LayoutContext<'_>) -> Pass<Commands<'a>> { - let mut text = ctx.style.text.clone(); - - self.size.with(|s| match s { - ScaleLength::Absolute(length) => { - text.base_font_size = length.as_raw(); - text.font_scale = 1.0; - } - ScaleLength::Scaled(scale) => text.font_scale = scale, - }); - self.style.with(|s| text.variant.style = s); - self.weight.with(|w| text.variant.weight = w); - self.width.with(|w| text.variant.width = w); + let mut text = ctx.style.text.clone(); - if !self.list.is_empty() { - *text.fallback.list_mut() = self.list.iter() - .map(|s| s.to_lowercase()) - .collect(); + size.with(|s| match s { + ScaleLength::Absolute(length) => { + text.base_font_size = length.as_raw(); + text.font_scale = 1.0; } + ScaleLength::Scaled(scale) => text.font_scale = scale, + }); - for (class, fallback) in &self.classes { - text.fallback.set_class_list(class.clone(), fallback.clone()); - } + style.with(|s| text.variant.style = s); + weight.with(|w| text.variant.weight = w); + width.with(|w| text.variant.width = w); - text.fallback.flatten(); + if !list.is_empty() { + *text.fallback.list_mut() = list.iter() + .map(|s| s.to_lowercase()) + .collect(); + } - Pass::okay(match &self.content { - Some(tree) => vec![ - SetTextStyle(text), - LayoutSyntaxTree(tree), - SetTextStyle(ctx.style.text.clone()), - ], - None => vec![SetTextStyle(text)], - }) + for (class, fallback) in classes { + text.fallback.set_class_list(class.clone(), fallback.clone()); } + + text.fallback.flatten(); + + Pass::commands(match content { + Some(tree) => vec![ + SetTextStyle(text), + LayoutSyntaxTree(tree), + SetTextStyle(ctx.style.text.clone()), + ], + None => vec![SetTextStyle(text)], + }, f) } |
