Files
vectorcraft/crates/pdf/tests/system_fonts.rs
T
Matthew FarrowandClaude Sonnet 5.5 d35db792dc PDF tests: the system-fonts test checks the first installed family that stays live text
The test took the first installed family that isn't bundled and expected its
PDF text to stay live. The PDF doesn't embed the font, so the page draws a
stand-in and text stays live only where the installed font's glyphs match it.
With suitcase fonts now found, the first family on a Mac is a condensed
display face whose glyphs don't, so the importer rightly kept outlines and the
test failed. Which family comes first depends on the machine's fonts: the test
now tries up to 200 families and checks the first that stays live.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 10:29:11 -04:00

50 lines
2.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! PDF import names type by the installed fonts in a new session (#130). One test in its own
//! process, so the process-wide font database starts fresh, as it does when the app starts.
// Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness).
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use vectorcraft_doc::NodeKind;
use vectorcraft_pdf::{ImportOptions, import_with_report};
use vectorcraft_testkit::pdf::{PdfPage, pdf_with};
use vectorcraft_text::{FontDb, system_font_dirs};
#[test]
fn a_fresh_session_resolves_pdf_fonts_to_installed_families() {
let bundled = FontDb::with_font_dirs(vec![]).families();
let probe = FontDb::with_font_dirs(system_font_dirs());
probe.load_system_fonts();
let installed = probe.families();
// Families whose PDF name is their name without the spaces (as "TimesNewRoman"). The font
// isn't embedded, so the page draws a stand-in; text stays live only where the installed
// font's glyphs match it, as a plain sans-serif's do and a condensed display face's don't:
// which family that is depends on the machine's fonts, so the first of them to do is checked.
let candidates: Vec<&String> = installed
.iter()
.filter(|f| !bundled.contains(f) && f.contains(' ') && f.chars().all(|c| c.is_ascii_alphanumeric() || c == ' '))
.take(200)
.collect();
if candidates.is_empty() {
eprintln!("no system fonts installed: nothing to check");
return;
}
let import = |family: &str| {
let resources = format!("/Font << /F1 << /Type /Font /Subtype /TrueType /BaseFont /{} >> >>", family.replace(' ', ""));
let page = PdfPage { resources, ..PdfPage::new(100.0, 100.0, "BT /F1 12 Tf 10 30 Td (Hi) Tj ET") };
let r = import_with_report(&pdf_with(&[page], &[], None), &ImportOptions::default()).unwrap();
let mut families = vec![];
r.document.walk(|n| {
if let NodeKind::Text(t) = &n.kind {
families.extend(t.runs.iter().map(|r| r.style.font_family.clone()));
}
});
(families, r.warnings)
};
let found = candidates.iter().find_map(|family| {
let (families, warnings) = import(family);
(!families.is_empty()).then_some((family, families, warnings))
});
let (family, families, warnings) = found.expect("one of the installed families stays live text");
assert_eq!(families, std::slice::from_ref(*family));
assert!(!warnings.iter().any(|w| w.contains(family.as_str())), "{warnings:?}");
}