diff --git a/crates/eps/src/import/tests_cid.rs b/crates/eps/src/import/tests_cid.rs index a8ec2304b3..d43a80d782 100644 --- a/crates/eps/src/import/tests_cid.rs +++ b/crates/eps/src/import/tests_cid.rs @@ -213,6 +213,22 @@ fn type2_cidfonts_draw_their_truetype_glyphs_through_cidmap() { } } +/// A `cshow` procedure over a Type 2 CIDFont without a `FontMatrix` sees the CIDFont current at +/// the scale its glyphs are drawn at: an em of the composite font's size, as with the identity. +#[test] +fn cshow_over_a_type2_cidfont_without_a_matrix_sees_it_at_its_drawn_scale() { + let (h, i) = (glyph('H').0, glyph('I').0); + let with = cid2_font(&format!("<0000{h:04x}{i:04x}>")); + let without = with.replace("/FontMatrix [1 0 0 1 0 0] def", ""); + assert_ne!(with, without); + for fonts in [with, without] { + check(&format!( + "{fonts}/T2 /Identity-H [/TestCID2] composefont 50 scalefont setfont \ + {{pop pop pop currentfont /FontMatrix get 0 get /m exch def}} <0001> cshow m 50 sub abs 0.01 lt" + )); + } +} + /// `Identity-V`: each glyph an em below the one before (writing mode 1). #[test] fn identity_v_sets_glyphs_downwards() { diff --git a/crates/eps/src/import/tests_composite.rs b/crates/eps/src/import/tests_composite.rs index 47e8bfd574..ff3b3382d3 100644 --- a/crates/eps/src/import/tests_composite.rs +++ b/crates/eps/src/import/tests_composite.rs @@ -141,6 +141,23 @@ fn cshow_runs_once_for_each_composite_character_in_its_descendant() { super::tests::check(&format!("{two} /Comp findfont 50 scalefont setfont [ {{pop pop}} (\\001\\002) cshow ] dup length 1 eq exch 0 get 2 eq and")); } +/// A `cshow` procedure over a Type 42 descendant without a `FontMatrix` sees it current at the +/// scale its characters are drawn at: another character it measures there is as wide as the +/// composite font sets it, as with the identity. +#[test] +fn cshow_over_a_type42_descendant_without_a_matrix_sees_it_at_its_drawn_scale() { + let (_, wi) = glyph('I'); + let with = fonts(); + let without = with.replacen("/FontType 42 def /FontMatrix [1 0 0 1 0 0] def", "/FontType 42 def", 1); + assert_ne!(with, without); + for fonts in [with, without] { + super::tests::check(&format!( + "{fonts} /Comp findfont 50 scalefont setfont {{pop pop pop (\\002) stringwidth pop /w exch def}} (\\000\\001) cshow w {} sub abs 0.01 lt", + 50.0 * wi + )); + } +} + /// `kshow` runs its procedure between each two characters of a composite font, with the values of /// their codes (font number times 256 plus code), and the next character follows where it moves /// the current point (PLRM 3rd ed., `kshow`). diff --git a/crates/eps/src/import/text.rs b/crates/eps/src/import/text.rs index 4a52aed9a5..1c76af774c 100644 --- a/crates/eps/src/import/text.rs +++ b/crates/eps/src/import/text.rs @@ -1377,7 +1377,15 @@ impl Interp<'_> { // size, so a huge font dictionary in a loop runs out of the budget. let entries = g.font.borrow().len(); self.spend(entries as u64)?; - let selected = transformed(&g.font, g.outer); + // Without a matrix, a Type 42 font or a Type 2 CIDFont is in ems, as `composite_glyph` + // and `cid_glyph_at` draw it. + let selected = { + let f = g.font.borrow(); + let default = if units(&f) == 1.0 { 1.0 } else { 0.001 }; + let mut d = f.clone(); + d.insert(Key::name("FontMatrix"), matrix_obj(g.outer * font_matrix(&f, default))); + DictRef::new(d) + }; self.cshow = Some(CShowFont { selected: selected.clone(), root: composite.clone(), code: None, mapped: Some(g.clone()) }); self.g.font = Some(selected); let go = self.body(proc);