From 7e2c217cbc3805c4cae613baf4149cc82e10d503 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 8 Jul 2021 21:42:36 +0200 Subject: [PATCH] Rename some library arguments - font - color -> fill - shorthands for families and size - decoration functions - color -> stroke - strength -> thickness - position -> offset - invert offsets: now positive goes downwards just like the rest of typst --- src/exec/state.rs | 8 ++++---- src/layout/shaping.rs | 19 ++++++++++--------- src/library/text.rs | 30 ++++++++++++++++++------------ tests/ref/text/decorations.png | Bin 10184 -> 10865 bytes tests/typ/code/call-wide.typ | 4 ++-- tests/typ/insert/circle.typ | 2 +- tests/typ/insert/square.typ | 2 +- tests/typ/text/bidi.typ | 14 +++++++------- tests/typ/text/chinese.typ | 2 +- tests/typ/text/decorations.typ | 13 ++++++++----- tests/typ/text/font.typ | 18 ++++++++++++------ tests/typ/text/shaping.typ | 8 ++++---- tests/typ/text/whitespace.typ | 4 ++-- 13 files changed, 70 insertions(+), 54 deletions(-) diff --git a/src/exec/state.rs b/src/exec/state.rs index 6f900b546..24e4b9f37 100644 --- a/src/exec/state.rs +++ b/src/exec/state.rs @@ -165,17 +165,17 @@ impl Default for FontState { /// Describes a line that could be positioned over, under or on top of text. #[derive(Debug, Copy, Clone, PartialEq, Hash)] pub struct LineState { + /// Stroke color of the line. Defaults to the text color if `None`. + pub stroke: Option, /// Thickness of the line's stroke. Calling functions should attempt to /// read this value from the appropriate font tables if this is `None`. - pub strength: Option, + pub thickness: Option, /// Position of the line relative to the baseline. Calling functions should /// attempt to read this value from the appropriate font tables if this is /// `None`. - pub position: Option, + pub offset: Option, /// Amount that the line will be longer or shorter than its associated text. pub extent: Linear, - /// Color of the line. Will default to text color if `None`. - pub fill: Option, } /// Font family definitions. diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs index 2496aae0f..c37300f7e 100644 --- a/src/layout/shaping.rs +++ b/src/layout/shaping.rs @@ -396,23 +396,24 @@ fn decorate( let mut apply = |substate: &LineState, metrics: fn(&Face) -> &LineMetrics| { let metrics = metrics(&ctx.cache.font.get(face_id)); - let strength = substate - .strength + let stroke = substate.stroke.unwrap_or(state.fill); + + let thickness = substate + .thickness .map(|s| s.resolve(state.size)) .unwrap_or(metrics.strength.to_length(state.size)); - let position = substate - .position + let offset = substate + .offset .map(|s| s.resolve(state.size)) - .unwrap_or(metrics.position.to_length(state.size)); + .unwrap_or(-metrics.position.to_length(state.size)); let extent = substate.extent.resolve(state.size); - let fill = substate.fill.unwrap_or(state.fill); - let pos = Point::new(pos.x - extent, pos.y - position); + let pos = Point::new(pos.x - extent, pos.y + offset); let target = Point::new(width + 2.0 * extent, Length::zero()); - let shape = Shape::Line(target, strength); - let element = Element::Geometry(shape, fill); + let shape = Shape::Line(target, thickness); + let element = Element::Geometry(shape, stroke); frame.push(pos, element); }; diff --git a/src/library/text.rs b/src/library/text.rs index bf0d49a49..9c2863bc9 100644 --- a/src/library/text.rs +++ b/src/library/text.rs @@ -6,14 +6,20 @@ use super::*; /// `font`: Configure the font. pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let list = args.named(ctx, "family"); - let size = args.named::(ctx, "size"); + let families = args.all(ctx); + let list = if families.is_empty() { + args.named(ctx, "family") + } else { + Some(FontDef(families)) + }; + + let size = args.eat(ctx).or_else(|| args.named::(ctx, "size")); let style = args.named(ctx, "style"); let weight = args.named(ctx, "weight"); let stretch = args.named(ctx, "stretch"); let top_edge = args.named(ctx, "top-edge"); let bottom_edge = args.named(ctx, "bottom-edge"); - let color = args.named(ctx, "color"); + let fill = args.named(ctx, "fill"); let serif = args.named(ctx, "serif"); let sans_serif = args.named(ctx, "sans-serif"); let monospace = args.named(ctx, "monospace"); @@ -50,8 +56,8 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { font.bottom_edge = bottom_edge; } - if let Some(color) = color { - font.fill = Fill::Color(color); + if let Some(fill) = fill { + font.fill = Fill::Color(fill); } if let Some(FamilyDef(serif)) = &serif { @@ -229,19 +235,19 @@ fn line_impl( args: &mut FuncArgs, substate: fn(&mut FontState) -> &mut Option>, ) -> Value { - let color = args.named(ctx, "color"); - let position = args.named(ctx, "position"); - let strength = args.named::(ctx, "strength"); + let stroke = args.eat(ctx).or_else(|| args.named(ctx, "stroke")); + let thickness = args.eat(ctx).or_else(|| args.named::(ctx, "thickness")); + let offset = args.named(ctx, "offset"); let extent = args.named(ctx, "extent").unwrap_or_default(); let body = args.expect::(ctx, "body").unwrap_or_default(); // Suppress any existing strikethrough if strength is explicitly zero. - let state = strength.map_or(true, |s| !s.is_zero()).then(|| { + let state = thickness.map_or(true, |s| !s.is_zero()).then(|| { Rc::new(LineState { - strength, - position, + stroke: stroke.map(Fill::Color), + thickness, + offset, extent, - fill: color.map(Fill::Color), }) }); diff --git a/tests/ref/text/decorations.png b/tests/ref/text/decorations.png index 1bde2dd4f7a087ca7e1cf120019c58e0b12c52aa..e3ca1be5e810d6c637202de90e93a9fe81abb028 100644 GIT binary patch literal 10865 zcmaiaXIPU>w{AiWJ<Nd-rxRlek8eO&6<^&Su@Xbulu^gHPv5}5YiC>000stMR_Oy0K~z3wn5k! zOOmEV2j=HUQ&n5x{{H^%@Xz7l;oa)y#LvI0tE+dTbA!u=ckM%WZG&CYTce|+%_D1f z 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