Make font take everything as keyword arguments

This commit is contained in:
Laurenz 2021-06-25 18:14:19 +02:00
parent ef279fa667
commit 63cf361496
12 changed files with 67 additions and 54 deletions

View File

@ -662,7 +662,7 @@ impl From<AnyValue> for Value {
} }
} }
/// Mark a type as a [`Value`]. /// Make a type castable from a value.
/// ///
/// Given a type `T`, this implements the following traits: /// Given a type `T`, this implements the following traits:
/// - [`Type`] for `T`, /// - [`Type`] for `T`,
@ -684,7 +684,7 @@ impl From<AnyValue> for Value {
/// This would allow the type `FontFamily` to be cast from: /// This would allow the type `FontFamily` to be cast from:
/// - a [`Value::Any`] variant already containing a `FontFamily`, /// - a [`Value::Any`] variant already containing a `FontFamily`,
/// - a string, producing a named font family. /// - a string, producing a named font family.
macro_rules! value { macro_rules! castable {
($type:ty: ($type:ty:
$type_name:literal $type_name:literal
$(, $pattern:pat => $out:expr)* $(, $pattern:pat => $out:expr)*

View File

@ -216,9 +216,9 @@ impl Default for FamilyList {
Self { Self {
list: vec![FontFamily::Serif], list: vec![FontFamily::Serif],
serif: vec!["eb garamond".into()], serif: vec!["eb garamond".into()],
sans_serif: vec![/* TODO */], sans_serif: vec!["pt sans".into()],
monospace: vec!["inconsolata".into()], monospace: vec!["inconsolata".into()],
base: vec!["twitter color emoji".into()], base: vec!["twitter color emoji".into(), "latin modern math".into()],
} }
} }
} }

View File

@ -123,6 +123,6 @@ impl Display for AlignValue {
} }
} }
value! { castable! {
AlignValue: "alignment", AlignValue: "alignment",
} }

View File

@ -6,20 +6,20 @@ use super::*;
/// `font`: Configure the font. /// `font`: Configure the font.
/// ///
/// # Positional parameters /// # Positional parameters
/// - Font size: optional, of type `linear` relative to current font size.
/// - Font families: variadic, of type `font-family`.
/// - Body: optional, of type `template`. /// - Body: optional, of type `template`.
/// ///
/// # Named parameters /// # Named parameters
/// - Font size: `size`, of type `linear` relative to current font size.
/// - Font families: `family`, `font-family`, `string` or `array`.
/// - Font Style: `style`, of type `font-style`. /// - Font Style: `style`, of type `font-style`.
/// - Font Weight: `weight`, of type `font-weight`. /// - Font Weight: `weight`, of type `font-weight`.
/// - Font Stretch: `stretch`, of type `relative`, between 0.5 and 2.0. /// - Font Stretch: `stretch`, of type `relative`, between 0.5 and 2.0.
/// - Top edge of the font: `top-edge`, of type `vertical-font-metric`. /// - Top edge of the font: `top-edge`, of type `vertical-font-metric`.
/// - Bottom edge of the font: `bottom-edge`, of type `vertical-font-metric`. /// - Bottom edge of the font: `bottom-edge`, of type `vertical-font-metric`.
/// - Color the glyphs: `color`, of type `color`. /// - Color the glyphs: `color`, of type `color`.
/// - Serif family definition: `serif`, of type `font-family-definition`. /// - Serif family definition: `serif`, of type `family-def`.
/// - Sans-serif family definition: `sans-serif`, of type `font-family-definition`. /// - Sans-serif family definition: `sans-serif`, of type `family-def`.
/// - Monospace family definition: `monospace`, of type `font-family-definition`. /// - Monospace family definition: `monospace`, of type `family-def`.
/// ///
/// # Return value /// # Return value
/// A template that configures font properties. The effect is scoped to the body /// A template that configures font properties. The effect is scoped to the body
@ -31,9 +31,9 @@ use super::*;
/// - `sans-serif` /// - `sans-serif`
/// - `monospace` /// - `monospace`
/// - coerces from `string` /// - coerces from `string`
/// - Type `font-family-definition` /// - Type `family-def`
/// - coerces from `string` /// - coerces from `string`
/// - coerces from `array` /// - coerces from `array` of `string`
/// - Type `font-style` /// - Type `font-style`
/// - `normal` /// - `normal`
/// - `italic` /// - `italic`
@ -49,8 +49,8 @@ use super::*;
/// - `baseline` /// - `baseline`
/// - `descender` /// - `descender`
pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
let size = args.eat::<Linear>(ctx); let list = args.named(ctx, "family");
let list = args.all::<FontFamily>(ctx); let size = args.named::<Linear>(ctx, "size");
let style = args.named(ctx, "style"); let style = args.named(ctx, "style");
let weight = args.named(ctx, "weight"); let weight = args.named(ctx, "weight");
let stretch = args.named(ctx, "stretch"); let stretch = args.named(ctx, "stretch");
@ -70,7 +70,7 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
font.size = linear.resolve(font.size); font.size = linear.resolve(font.size);
} }
if !list.is_empty() { if let Some(FontDef(list)) = &list {
font.families_mut().list = list.clone(); font.families_mut().list = list.clone();
} }
@ -98,15 +98,15 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
font.fill = Fill::Color(color); font.fill = Fill::Color(color);
} }
if let Some(FontFamilies(serif)) = &serif { if let Some(FamilyDef(serif)) = &serif {
font.families_mut().serif = serif.clone(); font.families_mut().serif = serif.clone();
} }
if let Some(FontFamilies(sans_serif)) = &sans_serif { if let Some(FamilyDef(sans_serif)) = &sans_serif {
font.families_mut().sans_serif = sans_serif.clone(); font.families_mut().sans_serif = sans_serif.clone();
} }
if let Some(FontFamilies(monospace)) = &monospace { if let Some(FamilyDef(monospace)) = &monospace {
font.families_mut().monospace = monospace.clone(); font.families_mut().monospace = monospace.clone();
} }
@ -117,12 +117,25 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
}) })
} }
/// A list of font family names. #[derive(Debug)]
#[derive(Debug, Clone, PartialEq)] struct FontDef(Vec<FontFamily>);
struct FontFamilies(Vec<String>);
value! { castable! {
FontFamilies: "string or array of strings", 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]),
}
#[derive(Debug)]
struct FamilyDef(Vec<String>);
castable! {
FamilyDef: "string or array of strings",
Value::Str(string) => Self(vec![string.to_lowercase()]), Value::Str(string) => Self(vec![string.to_lowercase()]),
Value::Array(values) => Self(values Value::Array(values) => Self(values
.into_iter() .into_iter()
@ -132,16 +145,16 @@ value! {
), ),
} }
value! { castable! {
FontFamily: "font family", FontFamily: "font family",
Value::Str(string) => Self::Named(string.to_lowercase()) Value::Str(string) => Self::Named(string.to_lowercase())
} }
value! { castable! {
FontStyle: "font style", FontStyle: "font style",
} }
value! { castable! {
FontWeight: "font weight", FontWeight: "font weight",
Value::Int(number) => { Value::Int(number) => {
let [min, max] = [Self::THIN, Self::BLACK]; let [min, max] = [Self::THIN, Self::BLACK];
@ -161,7 +174,7 @@ value! {
}, },
} }
value! { castable! {
FontStretch: "font stretch", FontStretch: "font stretch",
Value::Relative(relative) => { Value::Relative(relative) => {
let [min, max] = [Self::ULTRA_CONDENSED, Self::ULTRA_EXPANDED]; let [min, max] = [Self::ULTRA_CONDENSED, Self::ULTRA_EXPANDED];
@ -182,6 +195,6 @@ value! {
}, },
} }
value! { castable! {
VerticalFontMetric: "vertical font metric", VerticalFontMetric: "vertical font metric",
} }

View File

@ -70,7 +70,7 @@ pub fn grid(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
/// Defines size of rows and columns in a grid. /// Defines size of rows and columns in a grid.
type Tracks = Vec<TrackSizing>; type Tracks = Vec<TrackSizing>;
value! { castable! {
Tracks: "array of `auto`s, linears, and fractionals", Tracks: "array of `auto`s, linears, and fractionals",
Value::Int(count) => vec![TrackSizing::Auto; count.max(0) as usize], Value::Int(count) => vec![TrackSizing::Auto; count.max(0) as usize],
Value::Array(values) => values Value::Array(values) => values
@ -79,7 +79,7 @@ value! {
.collect(), .collect(),
} }
value! { castable! {
TrackSizing: "`auto`, linear, or fractional", TrackSizing: "`auto`, linear, or fractional",
Value::Auto => TrackSizing::Auto, Value::Auto => TrackSizing::Auto,
Value::Length(v) => TrackSizing::Linear(v.into()), Value::Length(v) => TrackSizing::Linear(v.into()),

View File

@ -110,6 +110,6 @@ pub fn new() -> Scope {
std std
} }
value! { castable! {
Dir: "direction" Dir: "direction"
} }

View File

@ -24,7 +24,7 @@
#test(alias(alias), "function") #test(alias(alias), "function")
// Library function `font` returns template. // Library function `font` returns template.
#test(type(font(12pt)), "template") #test(type(font(size: 12pt)), "template")
--- ---
// Callee expressions. // Callee expressions.

View File

@ -3,7 +3,7 @@
--- ---
// Test reordering with different top-level paragraph directions. // Test reordering with different top-level paragraph directions.
#let text = [Text טֶקסט] #let text = [Text טֶקסט]
#font("EB Garamond", "Noto Serif Hebrew") #font(family: ("EB Garamond", "Noto Serif Hebrew"))
#lang("he") {text} #lang("he") {text}
#lang("de") {text} #lang("de") {text}
@ -11,7 +11,7 @@
// Test that consecutive, embedded LTR runs stay LTR. // Test that consecutive, embedded LTR runs stay LTR.
// Here, we have two runs: "A" and italic "B". // Here, we have two runs: "A" and italic "B".
#let text = [أنت A_B_مطرC] #let text = [أنت A_B_مطرC]
#font("EB Garamond", "Noto Sans Arabic") #font(family: ("EB Garamond", "Noto Sans Arabic"))
#lang("ar") {text} #lang("ar") {text}
#lang("de") {text} #lang("de") {text}
@ -19,32 +19,32 @@
// Test that consecutive, embedded RTL runs stay RTL. // Test that consecutive, embedded RTL runs stay RTL.
// Here, we have three runs: "גֶ", bold "שֶׁ", and "ם". // Here, we have three runs: "גֶ", bold "שֶׁ", and "ם".
#let text = [Aגֶ*שֶׁ*םB] #let text = [Aגֶ*שֶׁ*םB]
#font("EB Garamond", "Noto Serif Hebrew") #font(family: ("EB Garamond", "Noto Serif Hebrew"))
#lang("he") {text} #lang("he") {text}
#lang("de") {text} #lang("de") {text}
--- ---
// Test embedding up to level 4 with isolates. // Test embedding up to level 4 with isolates.
#font("EB Garamond", "Noto Serif Hebrew", "Twitter Color Emoji") #font(family: ("EB Garamond", "Noto Serif Hebrew", "Twitter Color Emoji"))
#lang(dir: rtl) #lang(dir: rtl)
א\u{2066}A\u{2067}Bב\u{2069}? א\u{2066}A\u{2067}Bב\u{2069}?
--- ---
// Test hard line break (leads to two paragraphs in unicode-bidi). // Test hard line break (leads to two paragraphs in unicode-bidi).
#font("Noto Sans Arabic", "EB Garamond") #font(family: ("Noto Sans Arabic", "EB Garamond"))
#lang("ar") #lang("ar")
Life المطر هو الحياة \ Life المطر هو الحياة \
الحياة تمطر is rain. الحياة تمطر is rain.
--- ---
// Test spacing. // Test spacing.
#font("EB Garamond", "Noto Serif Hebrew") #font(family: ("EB Garamond", "Noto Serif Hebrew"))
L #h(1cm) ריווחR \ L #h(1cm) ריווחR \
יווח #h(1cm) R יווח #h(1cm) R
--- ---
// Test inline object. // Test inline object.
#font("Noto Serif Hebrew", "EB Garamond") #font(family: ("Noto Serif Hebrew", "EB Garamond"))
#lang("he") #lang("he")
קרנפיםRh#image("../../res/rhino.png", height: 11pt)inoחיים קרנפיםRh#image("../../res/rhino.png", height: 11pt)inoחיים

View File

@ -1,7 +1,7 @@
// Test chinese text from Wikipedia. // Test chinese text from Wikipedia.
--- ---
#font("Noto Serif CJK SC") #font(family: "Noto Serif CJK SC")
是美国广播公司电视剧《迷失》第3季的第22和23集也是全剧的第71集和72集 是美国广播公司电视剧《迷失》第3季的第22和23集也是全剧的第71集和72集
由执行制作人戴蒙·林道夫和卡尔顿·库斯编剧,导演则是另一名执行制作人杰克·本德 由执行制作人戴蒙·林道夫和卡尔顿·库斯编剧,导演则是另一名执行制作人杰克·本德

View File

@ -2,9 +2,9 @@
--- ---
// Set same font size in three different ways. // Set same font size in three different ways.
#font(22pt)[A] #font(size: 22pt)[A]
#font(200%)[A] #font(size: 200%)[A]
#font(16.5pt + 50%)[A] #font(size: 16.5pt + 50%)[A]
// Do nothing. // Do nothing.
#font[Normal] #font[Normal]
@ -19,13 +19,13 @@
#font(stretch: 50%)[Condensed] #font(stretch: 50%)[Condensed]
// Set family. // Set family.
#font("PT Sans")[Sans serif] #font(family: "PT Sans")[Sans serif]
// Emoji. // Emoji.
Emoji: 🐪, 🌋, 🏞 Emoji: 🐪, 🌋, 🏞
// Math. // Math.
#font("Latin Modern Math")[ #font(family: "Latin Modern Math")[
𝛼 + 3𝛽 d𝑡 𝛼 + 3𝛽 d𝑡
] ]
@ -49,9 +49,9 @@ Emoji: 🐪, 🌋, 🏞
--- ---
// Test class definitions. // Test class definitions.
#font(sans-serif: "PT Sans") #font(sans-serif: "PT Sans")
#font(sans-serif)[Sans-serif.] \ #font(family: sans-serif)[Sans-serif.] \
#font(monospace)[Monospace.] \ #font(family: monospace)[Monospace.] \
#font(monospace, monospace: ("Nope", "Latin Modern Math"))[Math.] #font(family: monospace, monospace: ("Nope", "Latin Modern Math"))[Math.]
--- ---
// Ref: false // Ref: false

View File

@ -7,11 +7,11 @@
Le fira Le fira
// This should just shape nicely. // This should just shape nicely.
#font("Noto Sans Arabic") #font(family: "Noto Sans Arabic")
دع النص يمطر عليك دع النص يمطر عليك
// This should form a three-member family. // This should form a three-member family.
#font("Twitter Color Emoji") #font(family: "Twitter Color Emoji")
👩‍👩‍👦 🤚🏿 👩‍👩‍👦 🤚🏿
// These two shouldn't be affected by a zero-width joiner. // These two shouldn't be affected by a zero-width joiner.
@ -20,7 +20,7 @@ Le fira
--- ---
// Test font fallback. // Test font fallback.
#font("EB Garamond", "Noto Sans Arabic", "Twitter Color Emoji") #font(family: ("EB Garamond", "Noto Sans Arabic", "Twitter Color Emoji"))
// Font fallback for emoji. // Font fallback for emoji.
A😀B A😀B
@ -40,6 +40,6 @@ A🐈中文B
--- ---
// Test reshaping. // Test reshaping.
#font("Noto Serif Hebrew") #font(family: "Noto Serif Hebrew")
#lang("he") #lang("he")
ס \ טֶ ס \ טֶ

View File

@ -36,11 +36,11 @@ A #for _ in (none,) {"B"}C
--- ---
// Test that a run consisting only of whitespace isn't trimmed. // Test that a run consisting only of whitespace isn't trimmed.
A#font("PT Sans")[ ]B A#font(family: "PT Sans")[ ]B
--- ---
// Test font change after space. // Test font change after space.
Left #font("PT Sans")[Right]. Left #font(family: "PT Sans")[Right].
--- ---
// Test that space at start of line is not trimmed. // Test that space at start of line is not trimmed.