From 48294c603778fe011ea8a0fcf91e0388fa7fae1c Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Sun, 8 Dec 2024 14:45:23 +0700 Subject: [PATCH] Move FontConfig conversion to `styled_text` This also adds additional cases for the stretch conversion and a note in the doc comments about where these values have come from. --- fontique/src/backend/fontconfig/cache.rs | 59 +----------------- styled_text/src/attributes.rs | 77 ++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/fontique/src/backend/fontconfig/cache.rs b/fontique/src/backend/fontconfig/cache.rs index cf60e474..b0d1e64b 100644 --- a/fontique/src/backend/fontconfig/cache.rs +++ b/fontique/src/backend/fontconfig/cache.rs @@ -6,59 +6,6 @@ use std::io::Read; use std::path::PathBuf; use styled_text::{Stretch, Style, Weight}; -// FIXME(style): There's an argument for putting this into styled_text -fn stretch_from_fc(width: i32) -> Stretch { - match width { - 63 => Stretch::EXTRA_CONDENSED, - 87 => Stretch::SEMI_CONDENSED, - 113 => Stretch::SEMI_EXPANDED, - _ => Stretch::from_ratio(width as f32 / 100.0), - } -} - -// FIXME(style): There's an argument for putting this into styled_text -fn style_from_fc(slant: i32) -> Style { - match slant { - 100 => Style::Italic, - 110 => Style::Oblique(None), - _ => Style::Normal, - } -} - -// FIXME(style): There's an argument for putting this into styled_text -fn weight_from_fc(weight: i32) -> Weight { - const MAP: &[(i32, i32)] = &[ - (0, 0), - (100, 0), - (200, 40), - (300, 50), - (350, 55), - (380, 75), - (400, 80), - (500, 100), - (600, 180), - (700, 200), - (800, 205), - (900, 210), - (950, 215), - ]; - for (i, (ot, fc)) in MAP.iter().skip(1).enumerate() { - if weight == *fc { - return Weight::new(*ot as f32); - } - if weight < *fc { - let weight = weight as f32; - let fc_a = MAP[i - 1].1 as f32; - let fc_b = *fc as f32; - let ot_a = MAP[i - 1].1 as f32; - let ot_b = *ot as f32; - let t = (fc_a - fc_b) / (weight - fc_a); - return Weight::new(ot_a + (ot_b - ot_a) * t); - } - } - Weight::EXTRA_BLACK -} - #[derive(Default)] pub struct CachedFont { pub family: Vec, @@ -153,21 +100,21 @@ fn parse_font( Object::Slant => { for val in elt.values().ok()? { if let Value::Int(i) = val.ok()? { - font.style = style_from_fc(i as _); + font.style = Style::from_fontconfig(i as _); } } } Object::Weight => { for val in elt.values().ok()? { if let Value::Int(i) = val.ok()? { - font.weight = weight_from_fc(i as _); + font.weight = Weight::from_fontconfig(i as _); } } } Object::Width => { for val in elt.values().ok()? { if let Value::Int(i) = val.ok()? { - font.stretch = stretch_from_fc(i as _); + font.stretch = Stretch::from_fontconfig(i as _); } } } diff --git a/styled_text/src/attributes.rs b/styled_text/src/attributes.rs index af96013b..6ff65455 100644 --- a/styled_text/src/attributes.rs +++ b/styled_text/src/attributes.rs @@ -156,6 +156,28 @@ impl Stretch { } } +impl Stretch { + /// Creates a new stretch attribute with the given value from Fontconfig. + /// + /// The values are determined based on the [fonts.conf documentation]. + /// + /// [fonts.conf documentation]: https://www.freedesktop.org/software/fontconfig/fontconfig-user.html + pub fn from_fontconfig(width: i32) -> Self { + match width { + 50 => Self::ULTRA_CONDENSED, + 63 => Self::EXTRA_CONDENSED, + 75 => Self::CONDENSED, + 87 => Self::SEMI_CONDENSED, + 100 => Self::NORMAL, + 113 => Self::SEMI_EXPANDED, + 125 => Self::EXPANDED, + 150 => Self::EXTRA_EXPANDED, + 200 => Self::ULTRA_EXPANDED, + _ => Self::from_ratio(width as f32 / 100.0), + } + } +} + impl fmt::Display for Stretch { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let value = self.0 * 1000.0; @@ -268,6 +290,46 @@ impl Weight { } } +impl Weight { + /// Creates a new weight attribute with the given value from Fontconfig. + /// + /// The values are determined based on the [fonts.conf documentation]. + /// + /// [fonts.conf documentation]: https://www.freedesktop.org/software/fontconfig/fontconfig-user.html + pub fn from_fontconfig(weight: i32) -> Self { + const MAP: &[(i32, i32)] = &[ + (0, 0), + (100, 0), + (200, 40), + (300, 50), + (350, 55), + (380, 75), + (400, 80), + (500, 100), + (600, 180), + (700, 200), + (800, 205), + (900, 210), + (950, 215), + ]; + for (i, (ot, fc)) in MAP.iter().skip(1).enumerate() { + if weight == *fc { + return Self::new(*ot as f32); + } + if weight < *fc { + let weight = weight as f32; + let fc_a = MAP[i - 1].1 as f32; + let fc_b = *fc as f32; + let ot_a = MAP[i - 1].1 as f32; + let ot_b = *ot as f32; + let t = (fc_a - fc_b) / (weight - fc_a); + return Self::new(ot_a + (ot_b - ot_a) * t); + } + } + Self::EXTRA_BLACK + } +} + impl Default for Weight { fn default() -> Self { Self::NORMAL @@ -362,6 +424,21 @@ impl Style { } } +impl Style { + /// Creates a new style attribute with the given value from Fontconfig. + /// + /// The values are determined based on the [fonts.conf documentation]. + /// + /// [fonts.conf documentation]: https://www.freedesktop.org/software/fontconfig/fontconfig-user.html + pub fn from_fontconfig(slant: i32) -> Self { + match slant { + 100 => Self::Italic, + 110 => Self::Oblique(None), + _ => Self::Normal, + } + } +} + impl fmt::Display for Style { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let value = match self {