Skip to content

Commit

Permalink
Rename FontStretch to FontWidth (#223)
Browse files Browse the repository at this point in the history
This brings it inline with CSS Fonts 4. Various things with `stretch` in
their name have also been renamed to use `width`.
  • Loading branch information
waywardmonkeys authored Dec 10, 2024
1 parent f02873a commit 63856dc
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 137 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This release has an [MSRV] of 1.75.

#### Fontique

- Breaking change: `Stretch`, `Style`, and `Weight` renamed to `FontStretch`, `FontStyle`, `FontWeight ([#211][] by [@waywardmonkeys][])
- Breaking change: `Stretch`, `Style`, and `Weight` renamed to `FontWidthh`, `FontStyle`, `FontWeight ([#211][], [#223][] by [@waywardmonkeys][])

#### Parley

Expand Down Expand Up @@ -112,6 +112,7 @@ This release has an [MSRV] of 1.70.
[#192]: https://github.com/linebender/parley/pull/192
[#198]: https://github.com/linebender/parley/pull/198
[#211]: https://github.com/linebender/parley/pull/211
[#223]: https://github.com/linebender/parley/pull/223

[Unreleased]: https://github.com/linebender/parley/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/linebender/parley/releases/tag/v0.2.0
Expand Down
84 changes: 44 additions & 40 deletions fontique/src/attributes.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
// Copyright 2024 the Parley Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! Properties for specifying font weight, stretch and style.
//! Properties for specifying font weight, width and style.
#[cfg(feature = "libm")]
#[allow(unused_imports)]
use core_maths::CoreFloat;

use core::fmt;

/// Primary attributes for font matching: [`FontStretch`], [`FontStyle`] and [`FontWeight`].
/// Primary attributes for font matching: [`FontWidth`], [`FontStyle`] and [`FontWeight`].
///
/// These are used to [configure] a [`Query`].
///
/// [configure]: crate::Query::set_attributes
/// [`Query`]: crate::Query
#[derive(Copy, Clone, PartialEq, Default, Debug)]
pub struct Attributes {
pub stretch: FontStretch,
pub width: FontWidth,
pub style: FontStyle,
pub weight: FontWeight,
}

impl Attributes {
/// Creates new attributes from the given stretch, style and weight.
pub fn new(stretch: FontStretch, style: FontStyle, weight: FontWeight) -> Self {
/// Creates new attributes from the given width, style and weight.
pub fn new(width: FontWidth, style: FontStyle, weight: FontWeight) -> Self {
Self {
stretch,
width,
style,
weight,
}
Expand All @@ -37,16 +37,16 @@ impl fmt::Display for Attributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"stretch: {}, style: {}, weight: {}",
self.stretch, self.style, self.weight
"width: {}, style: {}, weight: {}",
self.width, self.style, self.weight
)
}
}

/// Visual width of a font-- a relative change from the normal aspect
/// ratio, typically in the range `0.5` to `2.0`.
///
/// The default value is [`FontStretch::NORMAL`] or `1.0`.
/// The default value is [`FontWidth::NORMAL`] or `1.0`.
///
/// In variable fonts, this can be controlled with the `wdth` [axis]. This
/// is an `f32` so that it can represent the same range of values as as
Expand All @@ -60,13 +60,17 @@ impl fmt::Display for Attributes {
///
/// In CSS, this corresponds to the [`font-width`] property.
///
/// This has also been known as "stretch" and has a legacy CSS name alias,
/// [`font-stretch`].
///
/// [axis]: crate::AxisInfo
/// [`usWidthClass`]: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
/// [`font-width`]: https://www.w3.org/TR/css-fonts-4/#font-width-prop
/// [`font-stretch`]: https://www.w3.org/TR/css-fonts-4/#font-stretch-prop
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
pub struct FontStretch(f32);
pub struct FontWidth(f32);

impl FontStretch {
impl FontWidth {
/// Width that is 50% of normal.
pub const ULTRA_CONDENSED: Self = Self(0.5);

Expand Down Expand Up @@ -95,86 +99,86 @@ impl FontStretch {
pub const ULTRA_EXPANDED: Self = Self(2.0);
}

impl FontStretch {
/// Creates a new stretch attribute with the given ratio.
impl FontWidth {
/// Creates a new width attribute with the given ratio.
///
/// This can also be created [from a percentage](Self::from_percentage).
///
/// # Example
///
/// ```
/// # use fontique::FontStretch;
/// assert_eq!(FontStretch::from_ratio(1.5), FontStretch::EXTRA_EXPANDED);
/// # use fontique::FontWidth;
/// assert_eq!(FontWidth::from_ratio(1.5), FontWidth::EXTRA_EXPANDED);
/// ```
pub fn from_ratio(ratio: f32) -> Self {
Self(ratio)
}

/// Creates a stretch attribute from a percentage.
/// Creates a width attribute from a percentage.
///
/// This can also be created [from a ratio](Self::from_ratio).
///
/// # Example
///
/// ```
/// # use fontique::FontStretch;
/// assert_eq!(FontStretch::from_percentage(87.5), FontStretch::SEMI_CONDENSED);
/// # use fontique::FontWidth;
/// assert_eq!(FontWidth::from_percentage(87.5), FontWidth::SEMI_CONDENSED);
/// ```
pub fn from_percentage(percentage: f32) -> Self {
Self(percentage / 100.0)
}

/// Returns the stretch attribute as a ratio.
/// Returns the width attribute as a ratio.
///
/// This is a linear scaling factor with `1.0` being "normal" width.
///
/// # Example
///
/// ```
/// # use fontique::FontStretch;
/// assert_eq!(FontStretch::NORMAL.ratio(), 1.0);
/// # use fontique::FontWidth;
/// assert_eq!(FontWidth::NORMAL.ratio(), 1.0);
/// ```
pub fn ratio(self) -> f32 {
self.0
}

/// Returns the stretch attribute as a percentage value.
/// Returns the width attribute as a percentage value.
///
/// This is generally the value associated with the `wdth` axis.
pub fn percentage(self) -> f32 {
self.0 * 100.0
}

/// Returns `true` if the stretch is [normal].
/// Returns `true` if the width is [normal].
///
/// [normal]: FontStretch::NORMAL
/// [normal]: FontWidth::NORMAL
pub fn is_normal(self) -> bool {
self == Self::NORMAL
}

/// Returns `true` if the stretch is condensed (less than [normal]).
/// Returns `true` if the width is condensed (less than [normal]).
///
/// [normal]: FontStretch::NORMAL
/// [normal]: FontWidth::NORMAL
pub fn is_condensed(self) -> bool {
self < Self::NORMAL
}

/// Returns `true` if the stretch is expanded (greater than [normal]).
/// Returns `true` if the width is expanded (greater than [normal]).
///
/// [normal]: FontStretch::NORMAL
/// [normal]: FontWidth::NORMAL
pub fn is_expanded(self) -> bool {
self > Self::NORMAL
}

/// Parses the stretch from a CSS style keyword or a percentage value.
/// Parses the width from a CSS style keyword or a percentage value.
///
/// # Examples
///
/// ```
/// # use fontique::FontStretch;
/// assert_eq!(FontStretch::parse("semi-condensed"), Some(FontStretch::SEMI_CONDENSED));
/// assert_eq!(FontStretch::parse("80%"), Some(FontStretch::from_percentage(80.0)));
/// assert_eq!(FontStretch::parse("wideload"), None);
/// # use fontique::FontWidth;
/// assert_eq!(FontWidth::parse("semi-condensed"), Some(FontWidth::SEMI_CONDENSED));
/// assert_eq!(FontWidth::parse("80%"), Some(FontWidth::from_percentage(80.0)));
/// assert_eq!(FontWidth::parse("wideload"), None);
/// ```
pub fn parse(s: &str) -> Option<Self> {
let s = s.trim();
Expand All @@ -198,8 +202,8 @@ impl FontStretch {
}
}

impl FontStretch {
/// Creates a new stretch attribute with the given value from Fontconfig.
impl FontWidth {
/// Creates a new width attribute with the given value from Fontconfig.
///
/// The values are determined based on the [fonts.conf documentation].
///
Expand All @@ -220,7 +224,7 @@ impl FontStretch {
}
}

impl fmt::Display for FontStretch {
impl fmt::Display for FontWidth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let value = self.0 * 1000.0;
if value.fract() == 0.0 {
Expand All @@ -245,7 +249,7 @@ impl fmt::Display for FontStretch {
}
}

impl Default for FontStretch {
impl Default for FontWidth {
fn default() -> Self {
Self::NORMAL
}
Expand Down Expand Up @@ -507,12 +511,12 @@ impl fmt::Display for FontStyle {

#[cfg(test)]
mod tests {
use super::{FontStretch, FontStyle, FontWeight};
use super::{FontStyle, FontWeight, FontWidth};

#[test]
fn fontstretch_from_fontconfig() {
fn fontwidth_from_fontconfig() {
fn check_fc(fc: i32, s: &str) {
let fs = FontStretch::from_fontconfig(fc);
let fs = FontWidth::from_fontconfig(fc);
assert_eq!(s, fs.to_string());
}

Expand Down
8 changes: 4 additions & 4 deletions fontique/src/backend/fontconfig/cache.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2024 the Parley Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

use super::{FontStretch, FontStyle, FontWeight};
use super::{FontStyle, FontWeight, FontWidth};
use fontconfig_cache_parser::{Cache, CharSetLeaf, Object, Pattern, Value};
use std::io::Read;
use std::path::PathBuf;
Expand All @@ -11,7 +11,7 @@ pub struct CachedFont {
pub family: Vec<String>,
pub path: PathBuf,
pub index: u32,
pub stretch: FontStretch,
pub width: FontWidth,
pub style: FontStyle,
pub weight: FontWeight,
pub coverage: Coverage,
Expand All @@ -25,7 +25,7 @@ impl CachedFont {
self.coverage.clear();
self.weight = FontWeight::default();
self.style = FontStyle::default();
self.stretch = FontStretch::default();
self.width = FontWidth::default();
}
}

Expand Down Expand Up @@ -114,7 +114,7 @@ fn parse_font(
Object::Width => {
for val in elt.values().ok()? {
if let Value::Int(i) = val.ok()? {
font.stretch = FontStretch::from_fontconfig(i as _);
font.width = FontWidth::from_fontconfig(i as _);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions fontique/src/backend/fontconfig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;

use super::{
super::{FontStretch, FontStyle, FontWeight},
super::{FontStyle, FontWeight, FontWidth},
FallbackKey, FamilyId, FamilyInfo, FamilyName, FamilyNameMap, FontInfo, GenericFamily,
GenericFamilyMap, Script, SourceInfo, SourcePathMap,
};
Expand Down Expand Up @@ -50,7 +50,7 @@ impl SystemFonts {
fonts.extend(raw_family.fonts.iter().filter_map(|font| {
let mut info = FontInfo::from_source(font.source.clone(), font.index);
if let Some(info) = info.as_mut() {
info.maybe_override_attributes(font.stretch, font.style, font.weight);
info.maybe_override_attributes(font.width, font.style, font.weight);
}
info
}));
Expand Down Expand Up @@ -141,7 +141,7 @@ impl SystemFonts {
raw_family.fonts.push(RawFont {
source,
index: font.index,
stretch: font.stretch,
width: font.width,
style: font.style,
weight: font.weight,
coverage: font.coverage.clone(),
Expand Down Expand Up @@ -301,7 +301,7 @@ struct RawFamily {
struct RawFont {
source: SourceInfo,
index: u32,
stretch: FontStretch,
width: FontWidth,
style: FontStyle,
weight: FontWeight,
coverage: cache::Coverage,
Expand Down
9 changes: 2 additions & 7 deletions fontique/src/collection/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,18 +238,13 @@ fn load_font<'a>(
let family_index = if is_default {
family.default_font_index()
} else {
family.match_index(
attributes.stretch,
attributes.style,
attributes.weight,
true,
)?
family.match_index(attributes.width, attributes.style, attributes.weight, true)?
};
let font_info = family.fonts().get(family_index)?;
let blob = font_info.load(Some(source_cache))?;
let blob_index = font_info.index();
let synthesis =
font_info.synthesis(attributes.stretch, attributes.style, attributes.weight);
font_info.synthesis(attributes.width, attributes.style, attributes.weight);
*status = Entry::Ok(QueryFont {
family: (family.id(), family_index),
blob: blob.clone(),
Expand Down
10 changes: 5 additions & 5 deletions fontique/src/family.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! Model for font families.
use super::{
attributes::{FontStretch, FontStyle, FontWeight},
attributes::{FontStyle, FontWeight, FontWidth},
family_name::FamilyName,
font::FontInfo,
};
Expand Down Expand Up @@ -84,24 +84,24 @@ impl FamilyInfo {
/// Returns the index of the best font from the family for the given attributes.
pub fn match_index(
&self,
stretch: FontStretch,
width: FontWidth,
style: FontStyle,
weight: FontWeight,
synthesize_style: bool,
) -> Option<usize> {
super::matching::match_font(self.fonts(), stretch, style, weight, synthesize_style)
super::matching::match_font(self.fonts(), width, style, weight, synthesize_style)
}

/// Selects the best font from the family for the given attributes.
pub fn match_font(
&self,
stretch: FontStretch,
width: FontWidth,
style: FontStyle,
weight: FontWeight,
synthesize_style: bool,
) -> Option<&FontInfo> {
self.fonts()
.get(self.match_index(stretch, style, weight, synthesize_style)?)
.get(self.match_index(width, style, weight, synthesize_style)?)
}
}

Expand Down
Loading

0 comments on commit 63856dc

Please sign in to comment.