Fonts: Palatino Linotype and Book Antiqua prefer Palatino look-alikes (#670) (#677)

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
Valentin Klein 2026-10-12 04:42:05 +02:00 committed by GitHub
parent 4fffa81003
commit b75bd3c56a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View File

@ -130,6 +130,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
## Progress log
| Date | What landed |
| 2026-10-11 | Fonts: Palatino Linotype and Book Antiqua fall back to Palatino (macOS) or TeX Gyre Pagella / P052 / URW Palladio (Linux) before generic serif (#670) |
|---|---|
| 2026-10-11 | Word XML files (#548): Word XML Document (Flat OPC `.xml`) opens and saves through the DOCX reader and writer; Word 2003 XML opens (styles, lists, tables, sections, notes, comments, pictures, hyperlinks) |
| 2026-10-11 | Font fallback indexes which characters each installed font maps, reading each font file once (#605): text in a script no installed font covers no longer re-reads every system font per distinct character (200 such characters: 13 s → 0.2 s) |

View File

@ -36,6 +36,24 @@ fn substitutes(family: &str) -> &'static [&'static str] {
// headings and screens. Open fonts with full Persian coverage first.
const NASKH: &[&str] = &["Noto Naskh Arabic", "XB Zar", "XB Niloofar", "Amiri", "Vazirmatn", "Noto Sans Arabic", "DejaVu Sans", "Source Serif 4"];
const ARABIC_SANS: &[&str] = &["Vazirmatn", "Sahel", "Shabnam", "Samim", "Noto Sans Arabic", "Noto Naskh Arabic", "DejaVu Sans", "Source Sans 3"];
// Palatino Linotype / Book Antiqua: macOS ships the same design as "Palatino"; open
// look-alikes with matching metrics (TeX Gyre Pagella, URW P052 / Palladio) on Linux.
const PALATINO: &[&str] = &[
"Palatino Linotype",
"Palatino",
"Book Antiqua",
"TeX Gyre Pagella",
"P052",
"URW Palladio L",
"Palladio",
"Caladea",
"Times New Roman",
"Liberation Serif",
"Georgia",
"Noto Serif",
"DejaVu Serif",
"Source Serif 4",
];
let f = family.to_ascii_lowercase();
if is_persian_naskh(&f) {
return NASKH;
@ -44,6 +62,7 @@ fn substitutes(family: &str) -> &'static [&'static str] {
return ARABIC_SANS;
}
match f.as_str() {
"palatino linotype" | "book antiqua" | "palatino" => PALATINO,
"arial" | "helvetica" | "arial nova" => ARIAL,
"times new roman" | "times" => TIMES,
"courier new" | "courier" | "consolas" | "lucida console" | "cascadia code" | "cascadia mono" => MONO,
@ -52,8 +71,6 @@ fn substitutes(family: &str) -> &'static [&'static str] {
| "cambria math"
| "georgia"
| "garamond"
| "book antiqua"
| "palatino linotype"
| "constantia"
| "baskerville old face"
| "century"
@ -250,6 +267,19 @@ mod tests {
assert!(a > 0.0 && d >= 0.0);
}
#[test]
fn palatino_family_prefers_palatino_look_alikes_over_generic_serif() {
for name in ["Palatino Linotype", "Book Antiqua", "palatino"] {
let list = substitutes(name);
let pos = |n: &str| list.iter().position(|x| *x == n);
assert!(pos("Palatino").is_some() && pos("TeX Gyre Pagella").is_some() && pos("P052").is_some(), "{name}");
// All of them come before the generic serif fallbacks (Caladea, Times New Roman).
assert!(pos("Palatino") < pos("Caladea") && pos("TeX Gyre Pagella") < pos("Times New Roman"), "{name}");
}
// Other serif families are unchanged.
assert_eq!(substitutes("Georgia").first(), Some(&"Caladea"));
}
#[test]
fn symbol_font_chars_map_to_unicode() {
assert_eq!(symbol_font_char("Symbol", '\u{F0B7}'), Some('\u{2022}'));