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
This commit is contained in:
Gert Pellin
2026-10-13 08:11:27 +07:00
committed by bflatastic
parent 44d170f059
commit e2a63a8baf
2 changed files with 20 additions and 1 deletions
+16
View File
@@ -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\
+4 -1
View File
@@ -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,