2

Context: In digging into How can I get Mathematica to not mis-align plot labels when exporting to pdf without rasterizing the text?, and getting an answer to How does pdf export compute the size of the bounding box of Inset?, I have come to discover that PNG export agrees with Mathematica rendering but disagrees with PDF export about the size of text, and that this disagreement is very pronounced for font size 12, but much smaller for font size 16.

I created the following example to demonstrate the disagreement:

ClearAll[NextSize, MakeBound, BoxChars, MakeG];
TextSize[text_] := 
  TextSize[text] = Rasterize[Text[text], "RasterSize"];
NextSize[opts___][{_, _, str_}, 
   ch_] := {If[str == "", 0, TextSize[Style[str, opts]][[1]]], ch, 
   str <> ch};
MakeBound[y_, opts___][{xmin_, ch_, _}] := {EdgeForm[Thin], White, 
   Rectangle[Offset[{xmin, 0}, {0, y}], 
    Offset[{xmin, 0} + TextSize[Style[ch, opts]], {0, y}]]};
BoxChars[Style[text_, opts___], y_] := 
  Join[Flatten[
    Map[MakeBound[y, opts], 
     Drop[FoldList[NextSize[opts], {0, "", ""}, Characters[text]],1]]], 
     {Black, Text[Style[text, opts], {0, y}, {-1, -1}]}];
MakeG[nmax_, fs_] := 
  Graphics[Flatten[
    Table[BoxChars[
      Style[StringJoin @@ Table["a", Mod[n, 2, 1]*10], fs], 
      n/nmax], {n, 1, nmax}]]];
Rasterize[p16 = MakeG[10, 16]]
Rasterize[p12 = MakeG[10, 12]]
Export[FileNameJoin[{NotebookDirectory[], "foo-p16.pdf"}], p16]
Export[FileNameJoin[{NotebookDirectory[], "foo-p16.png"}], p16]
Export[FileNameJoin[{NotebookDirectory[], "foo-p12.pdf"}], p12]
Export[FileNameJoin[{NotebookDirectory[], "foo-p12.png"}], p12]

In Mathematica as well as in PNG export, we get each character in a box:

foo-p12.png:

foo-p12.png

foo-p16.png:

foo-p16.png

However, in PDF export, the boxes do not align with the characters. At font-size 12, this is quite apparent after 6 or so characters, and by 20 characters, the text fits in only 19 boxes. At font-size 16, it is only barely apparent after 20 characters.

foo-p12.pdf:

foo-p12.pdf

foo-p16.pdf:

foo-p16.pdf

If it's relevant, this is on Mathematica 11.2.0.0 on Windows 10 64-bit.

My question is: What is going on here?

Jason Gross
  • 589
  • 2
  • 10
  • I don't see the misalignment on MacBook Pro with 11.1.1. Do you still have a problem if you print? It might be a screen rendering issue. – Themis Jan 12 '18 at 14:57
  • Tangentially relevant: "Monospaced fonts are not monospaced." Mathematica has serious problems with character positioning both in the FrontEnd and in Export, unfortunately. – Alexey Popkov Jan 12 '18 at 17:16
  • You shouldn't trust Rasterize in determining the size of anything, especially when it is a text string. Rasterize is known to be off by 1-2 pixels even in situations when it deals with exact objects. The case of textual primitives is especially painful. – Alexey Popkov Jan 12 '18 at 17:43
  • @Themis it shows up when I use pdf2png.com to convert the pdf to a png, and inspect the pixels of the png, so I don't think it's a screen rendering issue. – Jason Gross Jan 12 '18 at 18:36
  • @AlexeyPopkov Replacing Rasterize[..., "RasterSize"] with ImageDimensions[ImageCrop[Graphics[...]]] shows a very similar issue; does ImageDiminsions have the same problem? – Jason Gross Jan 12 '18 at 18:41
  • @AlexeyPopkov In any case, because I am aligning each box based on the raster size of the entire string up to that point, being consistently off by 1-2 pixels on an entire object shouldn't impact much of anything. Certainly, it should not accumulate as I add more characters. That is, if I have n "a"s followed by a "b", and I render that, and then I offset a box by the width of n "a"s, it seems odd that things would line up perfectly in the display in Mathematica, but be off in the pdf export by an amount that grows with n. (Though I guess monospaced fonts not being monospaced might do) – Jason Gross Jan 12 '18 at 18:43
  • ImageCrop uses Rasterize under the hood, it can't be avoided. Export to PostScript formats (PDF, EPS) seems to use it's own conversion rules which are independent from Rasterize. "Certainly, it should not accumulate as I add more characters." - Yes, the more identical characters, the lesser should be error. – Alexey Popkov Jan 12 '18 at 18:54
  • If you wish to add a frame around each character, it is possible to achieve with Grid: Grid[{Characters["aaaaaaaaaaaaaaaaa"]},Spacings->0,Frame->All,FrameStyle->AbsoluteThickness[0.01]]. But this approach will destroy the inter-character spacing in non-monospaced fonts (which is already wrong even for monospaced fonts, so it isn't a big deal). – Alexey Popkov Jan 13 '18 at 02:07
  • Thanks, but the box-around-each-character is actually just a contrived example for pushing on the bit I didn't understand (that rasterize / image dimensions gets more and more off from pdf export as the length of the string grows); my actual issue that I'm solving is https://mathematica.stackexchange.com/questions/162942/how-can-i-get-mathematica-to-not-mis-align-plot-labels-when-exporting-to-pdf-wit/163458#163458 – Jason Gross Jan 13 '18 at 05:38

0 Answers0