关闭 pdftex 中的字体子集?

关闭 pdftex 中的字体子集?

我将 pdf 文件交给一家按需印刷公司 (lulu.com),这家公司对字体非常挑剔。他们希望嵌入所有字体,不嵌入多种字体,也不进行子集设置。pdftex 的最新版本似乎可以自动完成所有这些操作,只是生成的 pdf 确实有子集设置。目前,我正在做的是通过 ghostscript 进行 pdf->pdf 过滤,如下所示:

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

这很慢,而且也很笨拙。有没有更好的方法来实现这一点?

如果通过切换到 luatex 或 xetex 可以更轻松地解决此问题,我愿意接受,但我不确定要选择哪一个,而且这些都是大型图书项目,使用 pdftex 以外的其他工具可能并不简单。

答案1

许多字体许可证不允许完全嵌入字体。假设您只使用允许完全嵌入的字体,您可以修改映射文件(当然,无需真正修改它)。

这需要一些工作,但这项工作是渐进的。

假设文档是

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

在日志文件的末尾,您可以找到所用字体的列表,在本例中lmr10.pfb

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

你还有一个编码指令,

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

您将grep lmr10.pfb $(kpsewhich pdftex.map)获得以下输出

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

因此相关行是以 开头的行rm-lmr10。准备一个fullembed.map包含相关行的文件,但稍作修改,如下所示

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

如果您不确定要包含哪一行,请包含全部(但将最后一行更改<<<)。

添加fullembed.map您需要的所有字体行,然后教 pdftex 在您的文档中使用它

\pdfmapfile{=fullembed.map}

之前\begin{document}。现在字体将完全嵌入。fullembed.map可以将其放置在 TeX 搜索的目录中:当前工作目录,或者在 GNU/Linux 系统上~/texmf/fonts/map/pdftex(创建必要的路径)。

答案2

以下是我编写的一些 perl 代码,用于自动执行 egreg 建议的流程。我认为它可能对其他人有帮助。它从标准输入读取日志文件并将 fullembed.map 写入标准输出。

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";
      }
    }
  }
}

相关内容