From e2a63a8baf783620b6c5de8663586905bff95a4b Mon Sep 17 00:00:00 2001 From: Gert Pellin Date: Tue, 13 Oct 2026 02:24:28 +0200 Subject: [PATCH] EPS/PS import: Type 42 fonts set type at their size Interp::font took a font's FontMatrix times 1000 as the matrix of one em, the Type 1 convention (glyphs in 1000-unit space). A Type 42 font's glyph space is one unit an em, its FontMatrix usually the identity, so type in Type 42 fonts (cairo, Inkscape, LibreOffice) came in 1000 times too large and off the page. FontType 42 now takes the matrix as it is. Fixes #1552 --- crates/eps/src/import/tests.rs | 16 ++++++++++++++++ crates/eps/src/import/text.rs | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/eps/src/import/tests.rs b/crates/eps/src/import/tests.rs index 0fe18e63a..7ce8fa9d9 100644 --- a/crates/eps/src/import/tests.rs +++ b/crates/eps/src/import/tests.rs @@ -467,6 +467,22 @@ fn the_bounding_box_comes_from_the_header_or_the_trailer() { assert!(r.warnings.iter().any(|w| w.contains("first of the file's 2 pages")), "{:?}", r.warnings); } +/// #1552: a Type 42 font's glyph space is one unit an em, so its identity FontMatrix scaled to 12 +/// sets 12 pt type (a Type 1's 0.001 matrix needs the 1000-unit space). +#[test] +fn type_42_fonts_set_type_at_their_size() { + for (kind, matrix) in [(42, "[1 0 0 1 0 0]"), (1, "[0.001 0 0 0.001 0 0]")] { + let body = format!( + "/T 10 dict begin /FontName /T def /FontType {kind} def /FontMatrix {matrix} def /Encoding StandardEncoding def currentdict end /T exch definefont pop \ + /T findfont 12 scalefont setfont 10 20 moveto (Hi) show" + ); + let r = read(&body); + let NodeKind::Text(t) = &objects(&r.document)[0].kind else { panic!("{:?}", r.warnings) }; + let size = t.runs[0].style.size * t.xf.determinant().abs().sqrt(); + assert!((size - 12.0).abs() < 1e-6, "FontType {kind}: {size} pt"); + } +} + #[test] fn embedded_font_programs_are_skipped() { let body = "/MyFont 10 dict begin /FontName /MyFont def /FontMatrix [0.001 0 0 0.001 0 0] def currentdict end currentfile eexec\n\ diff --git a/crates/eps/src/import/text.rs b/crates/eps/src/import/text.rs index 716e3b405..9c8cd6736 100644 --- a/crates/eps/src/import/text.rs +++ b/crates/eps/src/import/text.rs @@ -403,7 +403,10 @@ impl Interp<'_> { let f = font.borrow(); let name = f.get(&Key::name("FontName")).and_then(Obj::text).map_or_else(|| DEFAULT_FONT.to_string(), |n| n.to_string()); let m = f.get(&Key::name("FontMatrix")).and_then(|o| o.items().and_then(|i| matrix_of(&i.borrow()))).unwrap_or(Affine::scale(0.001)); - Ok((name, m * Affine::scale(1000.0))) + // Type 1 glyphs are in 1000-unit space; a Type 42 font's glyph space is one unit an em + // (its FontMatrix, usually the identity, is already the em's). + let units = if f.get(&Key::name("FontType")).and_then(Obj::as_num) == Some(42.0) { 1.0 } else { 1000.0 }; + Ok((name, m * Affine::scale(units))) } /// `s` (read as Latin-1) set in the current font at user point `at`: point type placed there,