Skip to content

Commit

Permalink
Move FontConfig conversion to styled_text
Browse files Browse the repository at this point in the history
This also adds additional cases for the stretch conversion and
a note in the doc comments about where these values have come from.
  • Loading branch information
waywardmonkeys committed Dec 8, 2024
1 parent 0e54031 commit 48294c6
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 56 deletions.
59 changes: 3 additions & 56 deletions fontique/src/backend/fontconfig/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
Expand Down Expand Up @@ -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 _);
}
}
}
Expand Down
77 changes: 77 additions & 0 deletions styled_text/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 48294c6

Please sign in to comment.