EPS import: cshow over a descendant without a matrix sees it at its drawn scale

When a Type 2 CIDFont or a Type 42 descendant of a composite font has no FontMatrix, the
font a cshow procedure sees as current now takes the identity as its default, as glyph
measuring and drawing do, instead of the 1/1000 default of other fonts.
This commit is contained in:
dotCooCoo
2026-11-14 11:03:23 -08:00
parent b12d4794a0
commit b374d1f2c0
3 changed files with 42 additions and 1 deletions
+16
View File
@@ -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() {
+17
View File
@@ -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`).
+9 -1
View File
@@ -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);