<div dir="ltr">Hi Karl,<div><br></div><div>it seems the primary problem is that pdftex tries to set font expansion parameters for a font without checking if the font has been successfully loaded (hence it modifies null_font which is totally wrong).</div><div><br></div><div>Please find the proposed patch attached. I have tested it against your test files (thanks again for making things easy to reproduce).</div><div><br></div><div>Regards,</div><div>Thanh</div><div><br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Mar 25, 2020 at 11:34 AM The Thanh Han <<a href="mailto:hanthethanh@gmail.com">hanthethanh@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Karl,<div><br></div><div>many thanks for the analysis and the proposed patch. I will take a close look and get back soon.</div><div><br></div><div>Regards,</div><div>Thanh</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 24, 2020 at 10:29 PM Karl Berry <<a href="mailto:karl@freefriends.org" target="_blank">karl@freefriends.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello Thanh (please ack :), and everyone else - Robert (cc'd) recently<br>
reported an "interesting" pdftex bug related to font expansion of vf<br>
files on the tex-live list. For the record, his original report is here:<br>
  <a href="https://tug.org/pipermail/tex-live/2020-March/045099.html" rel="noreferrer" target="_blank">https://tug.org/pipermail/tex-live/2020-March/045099.html</a><br>
but I'll quote as needed to make this email self-contained. Sorry, it's<br>
unavoidably long.<br>
<br>
I have a proposed fix (at the end) and am hoping for some kind of<br>
confirmation that it makes sense. (I am definitely not planning to<br>
make any change here for TL20. It's not that urgent, and testing is needed.)<br>
<br>
So, Robert found a case where pdftex mixes up two expanded fonts, when<br>
virtual fonts are involved. Here is a test file vfexp.tex, slightly<br>
modified from his original so it will run with -ini:<br>
<br>
-----------------------------------------------------------------------------<br>
\catcode`\{=1 \catcode`\}=2 \pdfoutput=1 \nonstopmode \hbadness=10000<br>
\vsize=20pc \hsize=30pt \parfillskip=0pt plus1fil<br>
\font\1=cmr10<br>
\font\2=bchr8t<br>
%\font\2=bchr8r<br>
\pdfmapfile{}<br>
\pdfmapline{+cmr10 CMR10 <cmr10.pfb}<br>
\pdfmapline{+bchr8r CharterBT-Roman " TeXBase1Encoding ReEncodeFont " <8r.enc <bchr8a.pfb}<br>
\pdfmapline{+bchr8r+20 CharterBT-Roman " 1.020 ExtendFont TeXBase1Encoding ReEncodeFont " <8r.enc <bchr8a.pfb}<br>
\pdfmapline{+bchr8r-20 CharterBT-Roman " 0.980 ExtendFont TeXBase1Encoding ReEncodeFont " <8r.enc <bchr8a.pfb}<br>
\pdffontexpand\1 100 100 5 %autoexpand<br>
\pdffontexpand\2 20  20 20<br>
\pdfadjustspacing=2<br>
\1 ABC<br>
<br>
\2 This is a paragraph with font expansion.<br>
\end<br>
-----------------------------------------------------------------------------<br>
<br>
bchr8t is a virtual font (otherwise the problem does not happen, per the<br>
commented-out \font\2 above), and we are not using autoexpand here (bug<br>
also goes away with autoexpand), and so Robert has actual tfm files for<br>
bchr8[rt][+-]20.tfm. (I'll also attach an archive with all files to<br>
reproduce.)<br>
<br>
Here are the errors from running (avoiding useless mktextfm calls)<br>
  env TEXFONTS=.: MKTEXTFM=0 pdftex -ini -file-line-error vfexp.tex<br>
now:<br>
./vfexp.tex:12:! Font \csname\endcsname=cmr10+100 at 10.0pt not loadable: Metric (TFM) file no<br>
./vfexp.tex:12:! Font \csname\endcsname=cmr10-100 at 10.0pt not loadable: Metric (TFM) file no<br>
./vfexp.tex:17:! Font \csname\endcsname=bchr8r+20-100 at 10.0pt not loadable: Metric (TFM) fil<br>
./vfexp.tex:17:! Font \csname\endcsname=bchr8r-20-100 at 10.0pt not loadable: Metric (TFM) fil<br>
<br>
The first two, about failing to make cmr10+100 and cmr10-100 at the<br>
first \pdffontexpand, are expected.  (Robert, to answer one of your<br>
questions: although you're right that those fonts will never be used,<br>
and the doc is not exactly clear on this point [I'll try to improve it],<br>
the reality is that pdftex immediately tries to make fonts for the<br>
stretch/shrink limit when it processes \pdffontexpand. I don't think<br>
this could/should be changed.)<br>
<br>
At the second \pdffontexpand line, it finds bchr8t.vf, and hence<br>
bchr8r.tfm, and and the +20/-20.tfm files. All that is fine.<br>
<br>
But then, when pdftex is generating the output (pdf_hlist_out, etc.), it<br>
needs to use the expanded bchr8r. The necessary tfms all exist (included<br>
in the attached) but it erroneously uses the max shrink (-100) from the<br>
cmr10 font \1, and tries to make the nonsensical bchr8r+20-100.<br>
<br>
I don't have any particular familiarity with this part of the code, but<br>
tracing through the execution in the debugger, it seems the bug is<br>
in vf_def_font, which calls set_expand_params (which makes the fonts)<br>
with this call:<br>
         set_expand_params(k, pdf_font_auto_expand[f],<br>
                           pdf_font_expand_ratio[pdf_font_stretch[f]],<br>
                           -pdf_font_expand_ratio[pdf_font_shrink[f]],<br>
                           pdf_font_step[f], pdf_font_expand_ratio[f]);<br>
<br>
The problem is that pdf_font_stretch[f] (and _shrink[f]) are both zero<br>
at this point. These are references to another font, i.e.,<br>
null_font. But the zeroth entry of pdf_font_expand_ratio is not the zero<br>
for null_font, but the -100 for the specified cmr10 (which doesn't make<br>
sense to me, but I took it as given).<br>
<br>
FWIW, here are the various arrays at the critical point:<br>
(gdb) ppool fontname[0]<br>
$91 = "nullfont"<br>
(gdb) ppool fontname[1]<br>
$92 = "cmr10"<br>
(gdb) ppool fontname[2]<br>
$93 = "bchr8t"<br>
(gdb) ppool fontname[3]<br>
$94 = "bchr8t+20"<br>
(gdb) ppool fontname[4]<br>
$95 = "bchr8t-20"<br>
(gdb) p pdffontstretch[0]@5<br>
$96 = {0, 0, 3, 0, 0}<br>
(gdb) p pdffontshrink[0]@5<br>
$97 = {0, 0, 4, 0, 0}<br>
(gdb) p pdffontexpandratio[0]@5<br>
$98 = {-100, 0, 0, 20, -20}<br>
<br>
In other places in the code, e.g., check_expand_pars, there is an<br>
explicit check for pdf_font_stretch and _shrink being null_font (= 0),<br>
so I added the same explicit checks to vf_def_font, which seemed to<br>
solve the problem. pdffonts reports the expanded/shrunken fonts used:<br>
$ pdffonts vfexp.pdf<br>
name                                 type              emb sub uni object ID<br>
------------------------------------ ----------------- --- --- --- ---------<br>
QBBONQ+CMR10                         Type 1            yes yes no       4  0<br>
DCAQPT+CharterBT-Roman-Extend_1020   Type 1            yes yes no       5  0<br>
OXEYKB+CharterBT-Roman-Extend_980    Type 1            yes yes no       6  0<br>
<br>
The same call to set_expand_params is in vf_expand_local_fonts, so<br>
if the above is right, the same fix would be needed there. I could not<br>
easily figure out how to exercise that code, though. Something like a vf<br>
that refers to another vf?<br>
<br>
I'll append the full patch I have.<br>
Thanh, anyone else, confirm/deny/comments?<br>
<br>
Robert, if you're willing, I could send you a new binary (x86_64-linux?)<br>
for you to try. I presume your microtype work has more tests that could<br>
go some way toward ensuring there's no unexpected side effect.<br>
<br>
Thanks,<br>
Karl<br>
<br>
--- pdftex.web  (revision 822)<br>
+++ pdftex.web  (working copy)<br>
@@ -17519,13 +17519,21 @@<br>
 procedure vf_expand_local_fonts(f: internal_font_number);<br>
 var lf: internal_font_number;<br>
     k: integer;<br>
+    shrink_limit, stretch_limit: integer;<br>
 begin<br>
     pdfassert(pdf_font_type[f] = virtual_font_type);<br>
     for k := 0 to vf_local_font_num[f] - 1 do begin<br>
         lf := vf_i_fnts[vf_default_font[f] + k];<br>
+       {Find stretch and shrink values, if any.}<br>
+        if pdf_font_stretch[f] = null_font then stretch_limit := 0<br>
+        else stretch_limit := pdf_font_expand_ratio[pdf_font_stretch[f]];<br>
+       {Ditto for shrink.}<br>
+        if pdf_font_shrink[f] = null_font then shrink_limit := 0<br>
+        else shrink_limit := pdf_font_expand_ratio[pdf_font_stretch[f]];<br>
+       {Now make the font(s) for |lf|.}<br>
         set_expand_params(lf, pdf_font_auto_expand[f],<br>
-                          pdf_font_expand_ratio[pdf_font_stretch[f]],<br>
-                          -pdf_font_expand_ratio[pdf_font_shrink[f]],<br>
+                          stretch_limit,<br>
+                          -shrink_limit,<br>
                           pdf_font_step[f], pdf_font_expand_ratio[f]);<br>
         if pdf_font_type[lf] = virtual_font_type then<br>
             vf_expand_local_fonts(lf);<br>
@@ -17962,6 +17970,7 @@ vf_def_font<br>
     s: str_number;<br>
     ds, fs: scaled;<br>
     cs: four_quarters;<br>
+    stretch_limit, shrink_limit: integer;<br>
 begin<br>
     cs.b0 := vf_byte; cs.b1 := vf_byte; cs.b2 := vf_byte; cs.b3 := vf_byte;<br>
     fs := store_scaled_f(vf_read_signed(4), font_size[f]);<br>
@@ -17992,9 +18001,16 @@<br>
             vf_local_font_warning(f, k, "design size mismatch");<br>
     end;<br>
     if (pdf_font_step[f] <> 0) then<br>
+       {Find stretch and shrink values, if any.}<br>
+        if pdf_font_stretch[f] = null_font then stretch_limit := 0<br>
+        else stretch_limit := pdf_font_expand_ratio[pdf_font_stretch[f]];<br>
+       {Ditto for shrink.}<br>
+        if pdf_font_shrink[f] = null_font then shrink_limit := 0<br>
+        else shrink_limit := pdf_font_expand_ratio[pdf_font_stretch[f]];<br>
+       {Now make the font(s) for |k|.}<br>
         set_expand_params(k, pdf_font_auto_expand[f],<br>
-                          pdf_font_expand_ratio[pdf_font_stretch[f]],<br>
-                          -pdf_font_expand_ratio[pdf_font_shrink[f]],<br>
+                          stretch_limit,<br>
+                          -shrink_limit,<br>
                           pdf_font_step[f], pdf_font_expand_ratio[f]);<br>
     vf_def_font := k;<br>
 end;<br>
<br>
</blockquote></div>
</blockquote></div>