12

I give pdf files to a print-on-demand house (lulu.com) that is very picky about fonts. They want all fonts embedded, no multiply embedded fonts, and no subsetting. Recent versions of pdftex seem to automatically do all of this except that the pdfs produced do have subsetting. Currently what I'm doing is pdf->pdf filtering through ghostscript like this:

gs -q  -dCompatibilityLevel=1.4 -dSubsetFonts=false -dPDFSETTINGS=/printer -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=b.pdf a.pdf -c '.setpdfwrite'

This is slow, and it's also kludgy. Is there a better way to accomplish this?

If this problem can be solved more easily by switching to luatex or xetex, I'm open to that, but I haven't been sure which one to hitch my wagon to, and these are large book projects that may be nontrivial to get working with something other the pdftex.

2
  • 1
    I submitted a pdflatex pdf to lulu.com without any special effort to fully embed fonts. Are you sure this is necessary? Here is one version I submitted, and here is the lulu.com link.
    – Lev Bishop
    Jul 24, 2011 at 20:22
  • @Lev Bishop: My experience with lulu is that such things tend not to be easily reproducible. They send PDFs to subcontractors, and every subcontractor has a different setup. Sometimes a PDF that has successfully printed many times will fail to print at a later time. Then I have to pretend to upload a new version of the file, which may in fact be the same file, and it will work. I don't know for a fact that subsetting creates more problems than not subsetting. This is something that a poweruser on the lulu forums told me.
    – user6853
    Jul 25, 2011 at 1:19

2 Answers 2

21

Many font licenses disallow full font embedding. Assuming you're using only fonts that allow full embedding you can modify the map file (without really modifying it, of course).

It requires some work, but this work is incremental.

Suppose the document is

\documentclass{article}
\usepackage{lmodern}
\begin{document}
Hello world!
\end{document}

At the end of the log file you find a list of the used fonts, in this case lmr10.pfb:

</usr/local/texlive/2011/texmf-dist/fonts/type1/public/lm/lmr10.pfb>

You have also an encoding directive,

{/usr/local/texlive/2011/texmf-dist/fonts/enc/dvips/lm/lm-rm.enc}

With grep lmr10.pfb $(kpsewhich pdftex.map) you obtain the following output

cs-lmr10 LMRoman10-Regular " enclmcs ReEncodeFont " <lm-cs.enc <lmr10.pfb
dd-lmr10 LMRoman10-Regular <dotdigits.enc <lmr10.pfb " fontinst-autoenc-dotdigits ReEncodeFont " 
ec-lmr10 LMRoman10-Regular " enclmec ReEncodeFont " <lm-ec.enc <lmr10.pfb
l7x-lmr10 LMRoman10-Regular " enclml7x ReEncodeFont " <lm-l7x.enc <lmr10.pfb
lmr8ttl10 LMRoman10-Regular <t1-clm.enc <lmr10.pfb " fontinst-autoenc-t1-clm ReEncodeFont " 
qx-lmr10 LMRoman10-Regular " enclmqx ReEncodeFont " <lm-qx.enc <lmr10.pfb
rm-lmr10 LMRoman10-Regular " enclmrm ReEncodeFont " <lm-rm.enc <lmr10.pfb
t5-lmr10 LMRoman10-Regular " enclmt5 ReEncodeFont " <lm-t5.enc <lmr10.pfb
texnansi-lmr10 LMRoman10-Regular " enclmtexnansi ReEncodeFont " <lm-texnansi.enc <lmr10.pfb
ts1-lmr10 LMRoman10-Regular " enclmts1 ReEncodeFont " <lm-ts1.enc <lmr10.pfb

so the relevant line is the one starting with rm-lmr10. Prepare a fullembed.map file containing the relevant line, but slightly modified as to read

rm-lmr10 LMRoman10-Regular " enclmrm ReEncodeFont " <lm-rm.enc <<lmr10.pfb

If you're uncertain about what line to include, include all (but change the last < into <<).

Add to fullembed.map all the font lines you need and then teach pdftex to use it saying in your document

\pdfmapfile{=fullembed.map}

before \begin{document}. Now the fonts will be fully embedded. The fullembed.map can be placed in a directory searched by TeX: the current working directory or, on GNU/Linux systems, ~/texmf/fonts/map/pdftex (create the necessary path).

2
  • 3
    Excellent! Egreg, for the second time in 24 hours I am greatly indebted to you. Do you need your lawn mowed, dogs walked?
    – user6853
    Jul 25, 2011 at 2:24
  • Hm. Too bad there is no simple way of telling xelatex to not subset the fonts in the preamble of the document, e.g. with a \special directive :-\ May 5, 2021 at 9:56
9

The following is some perl code I wrote to automate the process suggested by egreg. Thought it might be helpful to others. It reads a log file from standard input and writes fullembed.map to standard output.

use strict;

my $default_map = `kpsewhich pdftex.map`;
open(F,"<$default_map");
my @map = ();
while (my $line=<F>) {
  chomp $line;
  # yvtri8r VenturisADF-Italic <8r.enc <yvtri8a.pfb "TeXBase1Encoding ReEncodeFont"
  # "..." may also be before <'s; just eliminate it:
  $line =~ s/".*"//;
  #print "=$line=\n";
  push @map,$line;

}
close(F);

local $/; # slurp whole file

my $log = <>;

#print "encs:\n";
my @enc = (''); # null string is because some lines in pdftex.map have no .enc
while ($log =~ /{([^}]+\.enc)}/g) {
  my $enc = $1;
  $enc =~ s/\n//g;
  if ($enc =~ /([^\/]+)\.enc/) {
    my $tail = $1;
    #print "enc=$tail\n";
    push @enc,$tail;
  }
}

#print "pfbs:\n";
my @pfb = ();
while ($log =~ /<([^>]+\.pfb)>/g) {
  my $pfb = $1;
  $pfb =~ s/\n//g;
  if ($pfb =~ /([^\/]+\.pfb)/) {
    my $tail = $1;
    #print "$tail\n";
    push @pfb,$tail;
  }

}

foreach my $enc(@enc) {
  my $e = quotemeta $enc;
  foreach my $pfb(@pfb) {
    my $p = quotemeta $pfb;
    foreach my $map(@map) {
      #if ($pfb =~ /tipasl10/ && $enc eq '') {print "trying enc=$enc, pfb=$pfb, map=$map\n"}
      if ( $map =~/$p/ && (($enc ne '' && $map =~ /$e/) || ($enc eq '' && ! ($map =~ /\.enc/)))) {
        $map =~ s/(<[^ ]+.pfb)/<$1/;
        #print "enc=$enc, pfb=$pfb, map=$map\n";
        print "$map\n";
      }
    }
  }
}

You must log in to answer this question.