我有一些输入PDF都带有全套字体,我想“缩小”它们所有创建字体的子集。我知道可以使用unembed fonts和embed subset font的方法,但是问题是我没有字体的源文件。我只是在源PDF中嵌入了字体。
有人可以帮助我解决此问题吗?
ENV:java8,itext7.1.5
答案 0 :(得分:0)
这里有一个类似问题的话题(尽管有OP的问题,但关于嵌入而不是子集):How to subset fonts into an existing PDF file。以下声明是相关的:
如果要对其进行子集化,则需要解析所有内容流 在PDF中查找使用了哪些字形。那不是小事 任务。
除非确实需要,否则我不建议在iText中尝试此操作。除非您对PDF规范有非常全面的了解,否则它可能最终会成为越野车。可能值得寻求其他途径,例如更改PDF的创建方式,或使用Distiller之类的工具为您完成此任务。
如果您确实想在iText中执行此操作,恐怕您可能必须使用PdfCanvasProcessor和一些自定义运算符处理程序。您将需要找到所有文本字段,确定它们使用的字体,使用适用的字形构建新的子集字体,并用新的子集副本替换字体。这样,您将创建完整字体的副本以准备子集(假设您没有字体文件的副本):
String encoding = PdfEncodings.WINANSI; // or another encoding if needed for more glyph support
PdfFont completeFont = ...; // get complete font from font dictionary
PdfFont subsetFont = PdfFontFactory.createFont(completeFont.getFontProgram(), encoding, true);
subsetFont.setSubset(true);
遇到字体更改运算符(Tf
)时,您需要在字体字典中查找该字体并创建该字体的新(或查找已创建的)子集副本,以准备将来使用文本字段。别忘了将字体保留在堆栈中,这样您就可以弹出回到先前的字体(查找q和Q运算符)。并且,如果当前字体不在当前XObject或页面资源字典中,请不要忘记检查父表单和页面组中的字体。
遇到文本(Tj
,TJ
,'
或"
运算符)时,您需要使用完整的字体对文本进行解码,然后重新输入-将其编码为新的子集字体的编码(除非您确定所有源字体都兼容ASCII)。像这样将文本的字符添加到子集中:
subsetFont.addSubsetRange(new int[]{character});