#[cfg(feature = "bundled-fonts")]
const SPACE_MONO_REGULAR: &[u8] = include_bytes!("../../fonts/space-mono/SpaceMono-Regular.ttf");
#[cfg(feature = "bundled-fonts")]
const SPACE_MONO_BOLD: &[u8] = include_bytes!("../../fonts/space-mono/SpaceMono-Bold.ttf");
#[cfg(feature = "bundled-fonts")]
const SPACE_MONO_ITALIC: &[u8] = include_bytes!("../../fonts/space-mono/SpaceMono-Italic.ttf");
#[cfg(feature = "bundled-fonts")]
const IBM_PLEX_MONO_REGULAR: &[u8] =
include_bytes!("../../fonts/ibm-plex-mono/IBMPlexMono-Regular.ttf");
#[cfg(feature = "bundled-fonts")]
const IBM_PLEX_MONO_MEDIUM: &[u8] =
include_bytes!("../../fonts/ibm-plex-mono/IBMPlexMono-Medium.ttf");
#[cfg(feature = "bundled-fonts")]
const IBM_PLEX_MONO_SEMIBOLD: &[u8] =
include_bytes!("../../fonts/ibm-plex-mono/IBMPlexMono-SemiBold.ttf");
#[cfg(feature = "bundled-fonts")]
const IBM_PLEX_MONO_ITALIC: &[u8] =
include_bytes!("../../fonts/ibm-plex-mono/IBMPlexMono-Italic.ttf");
pub(crate) const SPACE_MONO_REGULAR_INDEX: usize = 0;
pub(crate) const IBM_PLEX_MONO_REGULAR_INDEX: usize = 3;
#[cfg(feature = "bundled-fonts")]
pub fn font_data() -> &'static [&'static [u8]] {
&[
SPACE_MONO_REGULAR,
SPACE_MONO_BOLD,
SPACE_MONO_ITALIC,
IBM_PLEX_MONO_REGULAR,
IBM_PLEX_MONO_MEDIUM,
IBM_PLEX_MONO_SEMIBOLD,
IBM_PLEX_MONO_ITALIC,
]
}
#[cfg(not(feature = "bundled-fonts"))]
pub fn font_data() -> &'static [&'static [u8]] {
&[]
}
#[cfg(all(test, feature = "bundled-fonts"))]
mod tests {
use super::font_data;
use frust::authoring::text::{FontFamily, FontStyle, TextContext, TextStyle};
#[test]
fn font_data_registers_and_resolves_both_families_by_name() {
let mut cx = TextContext::new();
let mut seen_space_mono = false;
let mut seen_ibm_plex_mono = false;
for bytes in font_data() {
let families = cx
.register_fonts(bytes.to_vec())
.expect("bundled Glyph font bytes must register as valid faces");
for family in families {
if family.name == "Space Mono" {
seen_space_mono = true;
}
if family.name == "IBM Plex Mono" {
seen_ibm_plex_mono = true;
}
}
}
assert!(
seen_space_mono,
"expected `font_data()` to register a \"Space Mono\" family"
);
assert!(
seen_ibm_plex_mono,
"expected `font_data()` to register an \"IBM Plex Mono\" family"
);
}
#[test]
fn font_data_returns_all_seven_faces() {
assert_eq!(
font_data().len(),
7,
"expected 3 Space Mono + 4 IBM Plex Mono faces"
);
}
#[test]
fn named_face_indices_select_each_family_s_regular() {
let faces = font_data();
assert_eq!(
faces[super::SPACE_MONO_REGULAR_INDEX],
super::SPACE_MONO_REGULAR
);
assert_eq!(
faces[super::IBM_PLEX_MONO_REGULAR_INDEX],
super::IBM_PLEX_MONO_REGULAR
);
}
#[test]
fn italic_style_resolves_to_the_bundled_italic_face() {
let mut cx = TextContext::new();
for bytes in font_data() {
cx.register_fonts(bytes.to_vec())
.expect("bundled Glyph font bytes must register as valid faces");
}
let resolved_bytes = |cx: &mut TextContext, style: FontStyle| -> Vec<u8> {
let text_style = TextStyle {
family: FontFamily::named("Space Mono"),
style,
..TextStyle::new(16.0, peniko::Color::BLACK)
};
let layout = cx.layout("frust", &text_style, None);
let runs = layout.to_scene_runs(kurbo::Point::ORIGIN);
runs.first()
.expect("expected at least one glyph run")
.font
.font()
.data
.as_ref()
.to_vec()
};
let italic_run = resolved_bytes(&mut cx, FontStyle::Italic);
let normal_run = resolved_bytes(&mut cx, FontStyle::Normal);
assert_eq!(
italic_run,
super::SPACE_MONO_ITALIC,
"an italic-styled \"Space Mono\" run must resolve to the bundled \
italic face's own bytes, not a synthesized variant of another face"
);
assert_eq!(
normal_run,
super::SPACE_MONO_REGULAR,
"an upright-styled \"Space Mono\" run must resolve to the Regular face"
);
assert_ne!(
italic_run, normal_run,
"the italic and normal runs must resolve to two distinct registered \
faces while `SPACE_MONO_ITALIC` stays registered"
);
}
#[test]
fn font_data_hands_out_the_same_bytes_on_every_call() {
let (a, b) = (font_data(), font_data());
assert_eq!(a.len(), b.len());
for (i, (x, y)) in a.iter().zip(b.iter()).enumerate() {
assert!(
std::ptr::eq(*x, *y),
"face {i} must be the same `&'static [u8]` on every call"
);
}
}
}
#[cfg(all(test, not(feature = "bundled-fonts")))]
mod no_bundled_fonts_tests {
#[test]
fn font_data_is_empty_without_the_feature() {
assert!(super::font_data().is_empty());
}
}