我正在尝试在iText7中打开PDF文件,在那里写一些新文本,将原始PDF中的字体应用到它并将其保存在另一个PDF文档中。我正在使用Java 1.8
因此,我需要在原始pdf中使用一组字体名称,用户将从中选择一个,将应用于新段落。 我还需要以某种方式应用此字体。
现在我有这段代码,我是从here获取的:
public static void main(String[] args) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfReader("example.pdf"));
Set<PdfName> fonts = listAllUsedFonts(pdf);
fonts.stream().forEach(System.out::println);
}
public static Set<PdfName> listAllUsedFonts(PdfDocument pdfDoc) throws IOException {
PdfDictionary acroForm = pdfDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.AcroForm);
if (acroForm == null) {
return null;
}
PdfDictionary dr = acroForm.getAsDictionary(PdfName.DR);
if (dr == null) {
return null;
}
PdfDictionary font = dr.getAsDictionary(PdfName.Font);
if (font == null) {
return null;
}
return font.keySet();
}
它返回此输出:
/Helv
/ZaDb
然而,唯一的字体example.pdf是Verdana(它是Adobe Acrobat Pro中的文档属性所说的)。此外,Verdana有两种实现方式:粗体和普通。
所以,我有这些问题:
提前谢谢!
答案 0 :(得分:1)
如果您只想显示正在使用的字体的名称(您在法律上允许这样做),您可以使用以下代码:
public void go() throws IOException {
final Set<String> usedFontNames = new HashSet<>();
IEventListener fontNameExtractionStrategy = new IEventListener() {
@Override
public void eventOccurred(IEventData iEventData, EventType eventType) {
if(iEventData instanceof TextRenderInfo)
{
TextRenderInfo tri = (TextRenderInfo) iEventData;
String fontName = tri.getFont().getFontProgram().getFontNames().getFontName();
usedFontNames.add(fontName);
}
}
@Override
public Set<EventType> getSupportedEvents() {
return null;
}
};
PdfCanvasProcessor parser = new PdfCanvasProcessor(fontNameExtractionStrategy);
File inputFile = new File("YOUR_INPUT_FILE_HERE.pdf");
PdfDocument pdfDocument = new PdfDocument(new PdfReader(inputFile));
for(int i=1;i<=pdfDocument.getNumberOfPages();i++)
{
parser.processPageContent(pdfDocument.getPage(i));
}
pdfDocument.close();
for(String fontName : usedFontNames)
{
System.out.println(fontName);
}
}
答案 1 :(得分:0)
您不应该在另一个PDF中重复使用一个PDF中的字体,这就是原因:字体几乎不会完全嵌入到PDF文档中。例如:您使用Verdana字体常规(238 KB)和Verdana粗体字体(207 KB),但是当您创建一个简单的PDF文档,以常规和粗体显示“Hello World”时,文件大小将远小于238 + 207 KB。为什么是这样?因为PDF只包含Verdana字体的子集和Verdana粗体字体的子集。
您可能已经注意到我正在谈论字体 Verdana常规 和字体 Verdana粗体。这些是两种不同的字体 相同的字体系列。阅读你的问题,我注意到你没有做出这种区分。你谈到 font Verdana 两个实现粗体和正常。这是不正确的。你应该 谈谈字体系列 Verdana和两个字体 Verdana粗体和 Verdana定期。
PDF通常包含不同字体的子集。它甚至可以包含相同字体的两个不同子集。另请参阅What are the extra characters in the font name of my PDF?
您的目标是获取一个PDF的字体并使用另一个PDF的字体。但是,假设您的原始PDF仅包含编写“Hello World”所需的子集,并且您要创建一个名为“Hello Universe”的新PDF。这将永远不会起作用,因为子集将不包含用于呈现字母U
,n
,i
,v
,r
和{的字形。 {1}}。
还要考虑到字体通常是许可的。很多字体 有一个许可证,声明您可以使用字体来创建 文档和嵌入该文档中的字体。但是,有 通常是一条条款,说其他人不被允许 提取到字体以在不同的上下文中使用它。例如:您在购买MS Windows副本时支付了字体费用,但有人支付了费用 收到包含该字体的PDF的人可能没有使用许可 那个字体。见Does one need to have a license for fonts if we are using ttf files in itext?
鉴于与您的问题相关的技术和法律问题,我认为处理代码示例并不合理。你的设计有缺陷。您应该使用许可的字体程序,而不是尝试从现有的PDF中提取字体。这回答问题3:如何将原始文档中的字体应用到新段落?您不能:法律禁止它(请参阅下面的额外信息),如果子集不包含您需要的所有字符,那么技术上可能是不可能的!
此外,您在官方iText网站上找到的样本会查找以形式定义的字体。 s
和/Helv
指的是Helvetica和Zapfdingbats。这是一组14中的两种字体,称为标准类型1字体。这些字体从未嵌入在文档中,因为每个查看者都应该知道如何呈现它们。如果要使用这些字体,则不需要完整的字体程序;字体指标就足够了。例如:iText附带14个包含字体指标的AFM文件(AFM = Adobe字体指标)。
你想知道为什么你没有找到Verdana,因为Verdana被用作文档中文本的字体,但是你看错了地方。您要求iText提供用于表单的字体,而不是文本中使用的字体。这个答案问题1:为什么这个函数返回两个字体而不是一个(Verdana)。
至于你的问题2:你正在查看字体的内部名称,内部名称可以是任何内容(甚至是ZaDb
,{ {1},...)。字体的postscript名称存储在字体字典中。这就是你需要的名字。
额外信息:
我检查了Verdana许可证:
Microsoft提供的字体。您可以使用此字体创建,显示和打印Microsoft产品,服务或包含此字体的内容的许可条款或使用条款所允许的内容。您只能(i)将此字体嵌入到此字体中包含的嵌入限制允许的内容中; (ii)暂时将此字体下载到打印机或其他输出设备以帮助打印内容。禁止任何其他用途。
禁止使用您想要的字体。如果您拥有Verdana许可证,则可以将该字体嵌入PDF格式。但是,不允许提取该字体并将其用于其他目的。您需要使用原始字体程序。