Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions fontique/src/collection/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

//! Query support.

use super::super::{Collection, SourceCache};

use alloc::vec::Vec;

use super::{
super::{Attributes, Blob, FallbackKey, FamilyId, FamilyInfo, GenericFamily, Synthesis},
Inner,
use super::Inner;
use crate::{
Attributes, Blob, Collection, FallbackKey, FamilyId, FamilyInfo, GenericFamily, SourceCache,
Synthesis, UnicodeRange,
};

#[derive(Clone, Default)]
Expand All @@ -34,6 +33,7 @@ pub struct Query<'a> {
source_cache: &'a mut SourceCache,
attributes: Attributes,
fallbacks: Option<FallbackKey>,
range: Option<UnicodeRange>,
}

impl<'a> Query<'a> {
Expand All @@ -45,6 +45,7 @@ impl<'a> Query<'a> {
source_cache,
attributes: Attributes::default(),
fallbacks: None,
range: None,
}
}

Expand Down Expand Up @@ -99,6 +100,14 @@ impl<'a> Query<'a> {
}
}

/// Sets the required [`UnicodeRange`]
///
/// If set, only fonts claiming to be functional over this range will be
/// returned.
pub fn set_range(&mut self, ur: impl Into<Option<UnicodeRange>>) {
self.range = ur.into()
}

/// Invokes the given callback with all fonts that match the current
/// settings.
///
Expand Down Expand Up @@ -129,6 +138,7 @@ impl<'a> Query<'a> {
let mut best_index = None;
if let Some(font) = load_font(
family_info,
self.range,
self.attributes,
&mut family.best,
false,
Expand All @@ -146,6 +156,7 @@ impl<'a> Query<'a> {
}
if let Some(font) = load_font(
family_info,
self.range,
self.attributes,
&mut family.default,
true,
Expand Down Expand Up @@ -223,6 +234,7 @@ pub struct QueryFont {

fn load_font<'a>(
family: &FamilyInfo,
opt_range: Option<UnicodeRange>,
attributes: Attributes,
font: &'a mut Entry<QueryFont>,
is_default: bool,
Expand All @@ -241,6 +253,12 @@ fn load_font<'a>(
family.match_index(attributes.width, attributes.style, attributes.weight, true)?
};
let font_info = family.fonts().get(family_index)?;
if let Some(range) = opt_range {
if !font_info.ranges().contains(range) {
return None;
}
}

let blob = font_info.load(Some(source_cache))?;
let blob_index = font_info.index();
let synthesis =
Expand Down
38 changes: 32 additions & 6 deletions fontique/src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use super::attributes::{FontStyle, FontWeight, FontWidth};
use super::source::{SourceInfo, SourceKind};
use super::{Blob, source_cache::SourceCache};
use crate::UnicodeRanges;
use core::fmt;
use read_fonts::{FontRef, TableProvider as _, types::Tag};
use smallvec::SmallVec;
Expand All @@ -15,6 +16,7 @@ type AxisVec = SmallVec<[AxisInfo; 1]>;
/// Representation of a single font in a family.
#[derive(Clone, Debug)]
pub struct FontInfo {
ranges: UnicodeRanges,
source: SourceInfo,
index: u32,
width: FontWidth,
Expand Down Expand Up @@ -42,6 +44,13 @@ impl FontInfo {
}
}

/// Returns the bit-map of contained ranges
///
/// This represents Unicode characters over which the font is "functional".
pub fn ranges(&self) -> UnicodeRanges {
self.ranges
}

/// Returns an object describing how to locate the data containing this
/// font.
pub fn source(&self) -> &SourceInfo {
Expand Down Expand Up @@ -199,7 +208,7 @@ impl FontInfo {
source: SourceInfo,
index: u32,
) -> Option<Self> {
let (width, style, weight) = read_attributes(font);
let (ranges, width, style, weight) = read_attributes(font);
let (axes, attr_axes) = if let Ok(fvar_axes) = font.fvar().and_then(|fvar| fvar.axes()) {
let mut axes = SmallVec::<[AxisInfo; 1]>::with_capacity(fvar_axes.len());
let mut attrs_axes = 0_u8;
Expand All @@ -225,6 +234,7 @@ impl FontInfo {
(Default::default(), Default::default())
};
Some(Self {
ranges,
source,
index,
width,
Expand Down Expand Up @@ -368,7 +378,7 @@ impl fmt::Debug for Synthesis {
}
}

fn read_attributes(font: &FontRef<'_>) -> (FontWidth, FontStyle, FontWeight) {
fn read_attributes(font: &FontRef<'_>) -> (UnicodeRanges, FontWidth, FontStyle, FontWeight) {
use read_fonts::{
TableProvider,
tables::{
Expand All @@ -392,7 +402,17 @@ fn read_attributes(font: &FontRef<'_>) -> (FontWidth, FontStyle, FontWeight) {
})
}

fn from_os2_post(os2: Os2<'_>, post: Option<Post<'_>>) -> (FontWidth, FontStyle, FontWeight) {
fn from_os2_post(
os2: Os2<'_>,
post: Option<Post<'_>>,
) -> (UnicodeRanges, FontWidth, FontStyle, FontWeight) {
let ranges = UnicodeRanges::from([
os2.ul_unicode_range_1(),
os2.ul_unicode_range_2(),
os2.ul_unicode_range_3(),
os2.ul_unicode_range_4(),
]);

let width = width_from_width_class(os2.us_width_class());
// Bits 1 and 9 of the fsSelection field signify italic and
// oblique, respectively.
Expand All @@ -411,10 +431,10 @@ fn read_attributes(font: &FontRef<'_>) -> (FontWidth, FontStyle, FontWeight) {
// have a value outside of that range.
// See <https://learn.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass>
let weight = FontWeight::new(os2.us_weight_class() as f32);
(width, style, weight)
(ranges, width, style, weight)
}

fn from_head(head: Head<'_>) -> (FontWidth, FontStyle, FontWeight) {
fn from_head(head: Head<'_>) -> (UnicodeRanges, FontWidth, FontStyle, FontWeight) {
let mac_style = head.mac_style();
let style = mac_style
.contains(MacStyle::ITALIC)
Expand All @@ -424,7 +444,12 @@ fn read_attributes(font: &FontRef<'_>) -> (FontWidth, FontStyle, FontWeight) {
.contains(MacStyle::BOLD)
.then_some(700.0)
.unwrap_or_default();
(FontWidth::default(), style, FontWeight::new(weight))
(
UnicodeRanges::default(),
FontWidth::default(),
style,
FontWeight::new(weight),
)
}

if let Ok(os2) = font.os2() {
Expand All @@ -436,6 +461,7 @@ fn read_attributes(font: &FontRef<'_>) -> (FontWidth, FontStyle, FontWeight) {
from_head(head)
} else {
(
UnicodeRanges::default(),
FontWidth::default(),
FontStyle::Normal,
FontWeight::default(),
Expand Down
2 changes: 2 additions & 0 deletions fontique/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ mod matching;
mod scan;
mod script;
mod source;
mod unicode_range;

mod source_cache;

Expand All @@ -59,6 +60,7 @@ pub use font::{AxisInfo, FontInfo, FontInfoOverride, Synthesis};
pub use generic::GenericFamily;
pub use script::Script;
pub use source::{SourceId, SourceInfo, SourceKind};
pub use unicode_range::{UnicodeRange, UnicodeRanges};

#[cfg(all(feature = "system", target_vendor = "apple"))]
use objc2 as _;
Expand Down
Loading
Loading