2

I didn't realize that statistical charts and graphs made by R were using fonts not installed on my Windows machine, these are:
Helvetica
Helvetica-Bold
Helvetica-Oblique
ZapfDingbats

I discovered that by running pdffonts <file.name.pdf> from command line. So these fonts were not embedded in the PDF files.

I have my dissertation sent for printing but the printing house says these fonts need to be embedded in the PDF file. I have written it using LaTeX and included graphs as PDFs.

How to replace or substitute these fonts (some are licensed) with very similar ones without distorting the graphs in the individual PDFs? I don't intend to use commercial utilities.

Notes
- Windows 7 32 bit
- This post was similar:

https://superuser.com/a/223687/212779

However, it was done with a commercial program and is relatively old by now. There might be better new ideas to overcome this problem. I hope so.

My trial so far
I have succeeded to do the replacement using the procedure in the following post by some expert in Ghostscript: https://superuser.com/q/39167/212779

This requires Ghostscript to be installed (I have version 9.15) plus Adobe PostScript for Windows, a universal one and this script from command line:

gswin32c ^
 -dNOPAUSE ^
 -dBATCH ^
 -sDEVICE=pdfwrite ^
 -dPDFSETTINGS=/prepress ^
 -dCompatibilityLevel=1.4 ^
 -dHaveTrueTypes=true ^
 -dSubsetFonts=true ^
 -sOutputFile="c:\path\to\somename.pdf" ^
 -c ".setpdfwrite <</NeverEmbed [ ]>> setdistillerparams" ^
 -f "c:\path\to\somename.ps"

Question
How to get the generated .ps postscript file and subsequently the .pdf file (which is now gracefully embedded with a similar font) having the same size of the original PDF, i.e., cropped exactly to the same dimensions of the original PDF file?

If I leave all default settings in Adobe Reader (version XI) -- not to be confused with the commercial Adobe Professional, I get the same size in .ps file, so what I really need is some code in Ghostscript to preserved dimensions of the .ps file when generate the final PDF, any help? BTW, I open the .ps file with SumatraPDF viewer.

Community
  • 1
  • 1
doctorate
  • 1,381
  • 1
  • 19
  • 43
  • Have you tried the `-dEmbedAllFonts=true` option to gswin32c? It was mentioned in [12857849](http://stackoverflow.com/questions/12857849/how-to-repair-a-pdf-file-and-embed-missing-fonts). From that example, it imports and exports a PDF directly instead of postscript. – r2evans Feb 17 '15 at 20:33
  • Thanks a lot that worked very well. Feel free to post the code and make it an answer. Is there any way to batch process multiple PDFs? – doctorate Feb 17 '15 at 20:51

2 Answers2

1

All what is needed in Windows is the following steps:

Step 1
Install Ghostscript and add to the PATH variables (Win + break is useful shortcut)

Step 2
Run this script from command line and go the target folder where you have the bad PDF (I do this to avoid writing the whole path).

Step 3

Check your bad PDF by running pdffont from command line:

pdffonts input-pdf-where-some-fonts-are-not-embedded.pdf

Step 4
Run this code to get the desired PDF with embedded fonts:

gswin32c ^  
-sFONTPATH=C\Windows\Fonts ^
-o output-pdf-with-embedded-fonts.pdf  ^
-sDEVICE=pdfwrite ^
-dPDFSETTINGS=/prepress ^
"input-pdf-where-some-fonts-are-not-embedded.pdf"
doctorate
  • 1,381
  • 1
  • 19
  • 43
1

You were close: a previous SO question (12857849) mentioned adding -dEmbedAllFonts=true to the command line of gswin32c.

Your second question (in a comment) for batch-processing multiple PDFs can be done in multiple ways, the "best" being what is easiest for you to understand, maintain, and using a tool to which you have ready access.

In R:

fnames <- list.files(pattern = 'doctorate-.*.pdf')
for (fn in fnames) {
    ofn <- paste0(gsub('\\.pdf$', '', fn, ignore.case = TRUE), '-withfonts.pdf')
    message('Processing: ', fn, ' --> ', ofn)
    system2('gswin32c',
            paste0('-dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress ',
                   '-dCompatibilityLevel=1.4 -dHaveTrueTypes=true -dSubsetFonts=true ',
                   '-dEmbedAllFonts=true -sOutputFile="', ofn, '" ',
                   '-c ".setpdfwrite <</NeverEmbed [ ]>> setdistillerparams" ',
                   '-f "', fn, '"'))
}

This is a bit verbose. If you add stdout=FALSE in system2, all you should see is something like:

Processing: doctorate-1.pdf --> doctorate-1-withfonts.pdf
Processing: doctorate-2.pdf --> doctorate-2-withfonts.pdf
Processing: doctorate-3.pdf --> doctorate-3-withfonts.pdf

In bash:

for fn in doctorate-*.pdf ; do
    ofn="$(basename ${fn} .pdf)-withfonts.pdf"
    echo "Processing: ${fn} --> ${ofn}"
    gswin32c -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress ^
             -dCompatibilityLevel=1.4 -dHaveTrueTypes=true -dSubsetFonts=true ^
             -dEmbedAllFonts=true -sOutputFile="${ofn}" ^
             -c ".setpdfwrite <</NeverEmbed [ ]>> setdistillerparams" ^
             -f "${fn}"
done

(Note that if you are doing this in a bash terminal under msys2 in windows, this will likely fail since msys2 sees "/prepress" and assumes it is a path, converting it to c:/msys64/prepress, which obviously means nothing to gs ...)

Community
  • 1
  • 1
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • +1, for batch processing, is it required to run R session in the same folder? or is there a way to tell R where the path to folder is? – doctorate Feb 18 '15 at 07:22
  • Not strictly, though this example assumes both that and the fact that `gswin32c` is in your executable path. If you changed the first line to be `fnames <- list.files(path='/some/path', pattern = 'doctorate-.*.pdf', full.names=TRUE)`, it should still work just fine (haven't tested it). See `help(list.files)` for some other options. – r2evans Feb 18 '15 at 08:57