diff --git a/library/src/text/misc.rs b/library/src/text/misc.rs index 15ef9a63a..32e0cc1dd 100644 --- a/library/src/text/misc.rs +++ b/library/src/text/misc.rs @@ -40,12 +40,15 @@ impl Behave for LinebreakNode { } } -/// Strong content, rendered in boldface by default. +/// Strongly emphasizes content by increasing the font weight. #[derive(Debug, Hash)] pub struct StrongNode(pub Content); #[node(Show)] impl StrongNode { + /// The delta to apply on the font weight. + pub const DELTA: i64 = 300; + fn construct(_: &Vm, args: &mut Args) -> SourceResult { Ok(Self(args.expect("body")?).pack()) } @@ -59,12 +62,30 @@ impl StrongNode { } impl Show for StrongNode { - fn show(&self, _: Tracked, _: StyleChain) -> Content { - self.0.clone().styled(TextNode::BOLD, Toggle) + fn show(&self, _: Tracked, styles: StyleChain) -> Content { + self.0.clone().styled(TextNode::DELTA, Delta(styles.get(Self::DELTA))) } } -/// Emphasized content, rendered with an italic font by default. +/// A delta that is summed up when folded. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct Delta(pub i64); + +castable! { + Delta, + Expected: "integer", + Value::Int(delta) => Self(delta), +} + +impl Fold for Delta { + type Output = i64; + + fn fold(self, outer: Self::Output) -> Self::Output { + outer + self.0 + } +} + +/// Emphasizes content by flipping the italicness. #[derive(Debug, Hash)] pub struct EmphNode(pub Content); @@ -84,7 +105,7 @@ impl EmphNode { impl Show for EmphNode { fn show(&self, _: Tracked, _: StyleChain) -> Content { - self.0.clone().styled(TextNode::ITALIC, Toggle) + self.0.clone().styled(TextNode::EMPH, Toggle) } } diff --git a/library/src/text/mod.rs b/library/src/text/mod.rs index c9298feee..47aaba361 100644 --- a/library/src/text/mod.rs +++ b/library/src/text/mod.rs @@ -111,12 +111,12 @@ impl TextNode { #[property(fold)] pub const FEATURES: FontFeatures = FontFeatures(vec![]); - /// Whether the font weight should be increased by 300. + /// A delta to apply on the font weight. #[property(skip, fold)] - pub const BOLD: Toggle = false; + pub const DELTA: Delta = 0; /// Whether the font style should be inverted. #[property(skip, fold)] - pub const ITALIC: Toggle = false; + pub const EMPH: Toggle = false; /// A case transformation that should be applied to the text. #[property(skip)] pub const CASE: Option = None; diff --git a/library/src/text/shaping.rs b/library/src/text/shaping.rs index 687f2a870..88fec39dc 100644 --- a/library/src/text/shaping.rs +++ b/library/src/text/shaping.rs @@ -537,11 +537,12 @@ pub fn variant(styles: StyleChain) -> FontVariant { styles.get(TextNode::STRETCH), ); - if styles.get(TextNode::BOLD) { - variant.weight = variant.weight.thicken(300); - } + let delta = styles.get(TextNode::DELTA); + variant.weight = variant + .weight + .thicken(delta.clamp(i16::MIN as i64, i16::MAX as i64) as i16); - if styles.get(TextNode::ITALIC) { + if styles.get(TextNode::EMPH) { variant.style = match variant.style { FontStyle::Normal => FontStyle::Italic, FontStyle::Italic => FontStyle::Normal, diff --git a/src/model/cast.rs b/src/model/cast.rs index df3c8c81d..6a78eebdd 100644 --- a/src/model/cast.rs +++ b/src/model/cast.rs @@ -280,10 +280,7 @@ castable! { castable! { FontWeight, Expected: "integer or string", - Value::Int(v) => Value::Int(v) - .cast::()? - .try_into() - .map_or(Self::BLACK, Self::from_number), + Value::Int(v) => Self::from_number(v.clamp(0, u16::MAX as i64) as u16), Value::Str(string) => match string.as_str() { "thin" => Self::THIN, "extralight" => Self::EXTRALIGHT, diff --git a/tests/fonts/IBMPlexSans-Medium.ttf b/tests/fonts/IBMPlexSans-Medium.ttf new file mode 100644 index 000000000..9395402b0 Binary files /dev/null and b/tests/fonts/IBMPlexSans-Medium.ttf differ diff --git a/tests/ref/text/emphasis.png b/tests/ref/text/emphasis.png index c004421df..da04d8d1d 100644 Binary files a/tests/ref/text/emphasis.png and b/tests/ref/text/emphasis.png differ diff --git a/tests/typ/text/emphasis.typ b/tests/typ/text/emphasis.typ index cd2191ccf..27e3b9776 100644 --- a/tests/typ/text/emphasis.typ +++ b/tests/typ/text/emphasis.typ @@ -16,6 +16,16 @@ _Still [ // Inside of words can still use the functions. P#strong[art]ly em#emph[phas]ized. +--- +// Adjusting the delta that strong applies on the weight. +Normal + +#set strong(delta: 300) +*Bold* + +#set strong(delta: 150) +*Medium* and *[*Bold*]* + --- // Error: 13 expected underscore #box[_Scoped] to body.