diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-07-29 13:21:25 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-07-29 13:28:19 +0200 |
| commit | 2c6127dea611944abb09a0d38375ad7cf9baced0 (patch) | |
| tree | 6572d169d4ce26edc38a880860ebae2f49639fb8 /src/library/text.rs | |
| parent | 7d15dc634b3be1b6e284bb6b2450e3736d3e6e8d (diff) | |
Refactor state
Diffstat (limited to 'src/library/text.rs')
| -rw-r--r-- | src/library/text.rs | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/src/library/text.rs b/src/library/text.rs index b56cbcd3..54e9794a 100644 --- a/src/library/text.rs +++ b/src/library/text.rs @@ -1,17 +1,10 @@ -use crate::exec::{LineState, TextState}; +use crate::exec::{FontState, LineState}; use crate::layout::Paint; use super::*; /// `font`: Configure the font. pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let families: Vec<_> = args.all().collect(); - let list = if families.is_empty() { - args.named(ctx, "family") - } else { - Some(FontDef(families)) - }; - let size = args.eat::<Linear>().or_else(|| args.named(ctx, "size")); let style = args.named(ctx, "style"); let weight = args.named(ctx, "weight"); @@ -19,20 +12,25 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let top_edge = args.named(ctx, "top-edge"); let bottom_edge = args.named(ctx, "bottom-edge"); let fill = args.named(ctx, "fill"); + + let families: Vec<_> = args.all().collect(); + let list = if families.is_empty() { + args.named(ctx, "family") + } else { + Some(FontDef(Rc::new(families))) + }; + let serif = args.named(ctx, "serif"); let sans_serif = args.named(ctx, "sans-serif"); let monospace = args.named(ctx, "monospace"); + let body = args.expect::<Template>(ctx, "body").unwrap_or_default(); Value::template(move |ctx| { - let state = ctx.state.text_mut(); + let state = ctx.state.font_mut(); - if let Some(linear) = size { - state.size = linear.resolve(state.size); - } - - if let Some(FontDef(list)) = &list { - state.families_mut().list = list.clone(); + if let Some(size) = size { + state.size = size.resolve(state.size); } if let Some(style) = style { @@ -59,6 +57,10 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { state.fill = Paint::Color(fill); } + if let Some(FontDef(list)) = &list { + state.families_mut().list = list.clone(); + } + if let Some(FamilyDef(serif)) = &serif { state.families_mut().serif = serif.clone(); } @@ -75,41 +77,42 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { }) } -struct FontDef(Vec<FontFamily>); +struct FontDef(Rc<Vec<FontFamily>>); castable! { FontDef: "font family or array of font families", - Value::Str(string) => Self(vec![FontFamily::Named(string.to_lowercase())]), - Value::Array(values) => Self(values - .into_iter() - .filter_map(|v| v.cast().ok()) - .collect() - ), - @family: FontFamily => Self(vec![family.clone()]), + Value::Str(string) => Self(Rc::new(vec![FontFamily::Named(string.to_lowercase())])), + Value::Array(values) => Self(Rc::new( + values + .into_iter() + .filter_map(|v| v.cast().ok()) + .collect() + )), + @family: FontFamily => Self(Rc::new(vec![family.clone()])), } -struct FamilyDef(Vec<String>); +struct FamilyDef(Rc<Vec<String>>); castable! { FamilyDef: "string or array of strings", - Value::Str(string) => Self(vec![string.to_lowercase()]), - Value::Array(values) => Self(values - .into_iter() - .filter_map(|v| v.cast().ok()) - .map(|string: EcoString| string.to_lowercase()) - .collect() - ), + Value::Str(string) => Self(Rc::new(vec![string.to_lowercase()])), + Value::Array(values) => Self(Rc::new( + values + .into_iter() + .filter_map(|v| v.cast().ok()) + .map(|string: EcoString| string.to_lowercase()) + .collect() + )), } /// `par`: Configure paragraphs. pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let par_spacing = args.named(ctx, "spacing"); let line_spacing = args.named(ctx, "leading"); - let word_spacing = args.named(ctx, "word-spacing"); let body = args.expect::<Template>(ctx, "body").unwrap_or_default(); Value::template(move |ctx| { - let state = ctx.state.text_mut(); + let state = ctx.state.par_mut(); if let Some(par_spacing) = par_spacing { state.par_spacing = par_spacing; @@ -119,10 +122,6 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { state.line_spacing = line_spacing; } - if let Some(word_spacing) = word_spacing { - state.word_spacing = word_spacing; - } - ctx.parbreak(); body.exec(ctx); }) @@ -130,20 +129,23 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `lang`: Configure the language. pub fn lang(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let iso = args.eat::<EcoString>().map(|s| lang_dir(&s)); - let dir = match args.named::<Spanned<Dir>>(ctx, "dir") { - Some(dir) if dir.v.axis() == SpecAxis::Horizontal => Some(dir.v), - Some(dir) => { + let iso = args.eat::<EcoString>(); + let dir = if let Some(dir) = args.named::<Spanned<Dir>>(ctx, "dir") { + if dir.v.axis() == SpecAxis::Horizontal { + Some(dir.v) + } else { ctx.diag(error!(dir.span, "must be horizontal")); None } - None => None, + } else { + iso.as_deref().map(lang_dir) }; + let body = args.expect::<Template>(ctx, "body").unwrap_or_default(); Value::template(move |ctx| { - if let Some(dir) = dir.or(iso) { - ctx.state.dir = dir; + if let Some(dir) = dir { + ctx.state.dirs.cross = dir; } ctx.parbreak(); @@ -151,7 +153,7 @@ pub fn lang(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { }) } -/// The default direction for the language identified by `iso`. +/// The default direction for the language identified by the given `iso` code. fn lang_dir(iso: &str) -> Dir { match iso.to_ascii_lowercase().as_str() { "ar" | "he" | "fa" | "ur" | "ps" | "yi" => Dir::RTL, @@ -178,7 +180,7 @@ pub fn overline(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { fn line_impl( ctx: &mut EvalContext, args: &mut FuncArgs, - substate: fn(&mut TextState) -> &mut Option<Rc<LineState>>, + substate: fn(&mut FontState) -> &mut Option<Rc<LineState>>, ) -> Value { let stroke = args.eat().or_else(|| args.named(ctx, "stroke")); let thickness = args.eat::<Linear>().or_else(|| args.named(ctx, "thickness")); @@ -197,7 +199,7 @@ fn line_impl( }); Value::template(move |ctx| { - *substate(ctx.state.text_mut()) = state.clone(); + *substate(ctx.state.font_mut()) = state.clone(); body.exec(ctx); }) } |
