如何使用 Java iText 检查所有使用的字体是否嵌入在 PDF 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4646130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check that all used fonts are embedded in PDF with Java iText?
提问by Juha Syrj?l?
How to check that all fonts that are used in a PDF file are embedded in the file with Java and iText? I have some existing PDF documents, and I'd like to validate that they use onlyembedded fonts.
如何使用 Java 和 iText 检查 PDF 文件中使用的所有字体是否嵌入到文件中?我有一些现有的 PDF 文档,我想验证它们是否仅使用嵌入字体。
This would require checking that no PDF standard fonts are used and other used fonts are embedded in the file.
这将需要检查是否未使用 PDF 标准字体,并且文件中嵌入了其他使用的字体。
采纳答案by Mark
Look at the ListUsedFonts example from iText in Action.
查看 iText in Action 中的 ListUsedFonts 示例。
http://itextpdf.com/examples/iia.php?id=287
http://itextpdf.com/examples/iia.php?id=287
Looks like this will print out the fonts used in a pdf and if they are embedded.
看起来这将打印出 pdf 中使用的字体以及它们是否被嵌入。
/*
* This class is part of the book "iText in Action - 2nd Edition"
* written by Bruno Lowagie (ISBN: 9781935182610)
* For more info, go to: http://itextpdf.com/examples/
* This example only works with the AGPL version of iText.
*/
package part4.chapter16;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;
import java.util.TreeSet;
import part3.chapter11.FontTypes;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
public class ListUsedFonts {
/** The resulting PDF file. */
public static String RESULT
= "results/part4/chapter16/fonts.txt";
/**
* Creates a Set containing information about the fonts in the src PDF file.
* @param src the path to a PDF file
* @throws IOException
*/
public Set<String> listFonts(String src) throws IOException {
Set<String> set = new TreeSet<String>();
PdfReader reader = new PdfReader(src);
PdfDictionary resources;
for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
resources = reader.getPageN(k).getAsDict(PdfName.RESOURCES);
processResource(set, resources);
}
reader.close();
return set;
}
/**
* Extracts the font names from page or XObject resources.
* @param set the set with the font names
* @param resources the resources dictionary
*/
public static void processResource(Set<String> set, PdfDictionary resource) {
if (resource == null)
return;
PdfDictionary xobjects = resource.getAsDict(PdfName.XOBJECT);
if (xobjects != null) {
for (PdfName key : xobjects.getKeys()) {
processResource(set, xobjects.getAsDict(key));
}
}
PdfDictionary fonts = resource.getAsDict(PdfName.FONT);
if (fonts == null)
return;
PdfDictionary font;
for (PdfName key : fonts.getKeys()) {
font = fonts.getAsDict(key);
String name = font.getAsName(PdfName.BASEFONT).toString();
if (name.length() > 8 && name.charAt(7) == '+') {
name = String.format("%s subset (%s)", name.substring(8), name.substring(1, 7));
}
else {
name = name.substring(1);
PdfDictionary desc = font.getAsDict(PdfName.FONTDESCRIPTOR);
if (desc == null)
name += " nofontdescriptor";
else if (desc.get(PdfName.FONTFILE) != null)
name += " (Type 1) embedded";
else if (desc.get(PdfName.FONTFILE2) != null)
name += " (TrueType) embedded";
else if (desc.get(PdfName.FONTFILE3) != null)
name += " (" + font.getAsName(PdfName.SUBTYPE).toString().substring(1) + ") embedded";
}
set.add(name);
}
}
/**
* Main method.
*
* @param args no arguments needed
* @throws DocumentException
* @throws IOException
*/
public static void main(String[] args) throws IOException, DocumentException {
new FontTypes().createPdf(FontTypes.RESULT);
Set<String> set = new ListUsedFonts().listFonts(FontTypes.RESULT);
PrintWriter out = new PrintWriter(new FileOutputStream(RESULT));
for (String fontname : set)
out.println(fontname);
out.flush();
out.close();
}
}
回答by K?van? Sahici
/**
* Creates a set containing information about the not-embedded fonts within the src PDF file.
* @param src the path to a PDF file
* @throws IOException
*/
public Set<String> listFonts(String src) throws IOException {
Set<String> set = new TreeSet<String>();
PdfReader reader = new PdfReader(src);
PdfDictionary resources;
for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
resources = reader.getPageN(k).getAsDict(PdfName.RESOURCES);
processResource(set, resources);
}
reader.close();
return set;
}
/**
* Finds out if the font is an embedded subset font
* @param font name
* @return true if the name denotes an embedded subset font
*/
private boolean isEmbeddedSubset(String name) {
//name = String.format("%s subset (%s)", name.substring(8), name.substring(1, 7));
return name != null && name.length() > 8 && name.charAt(7) == '+';
}
private void processFont(PdfDictionary font, Set<String> set) {
String name = font.getAsName(PdfName.BASEFONT).toString();
if(isEmbeddedSubset(name))
return;
PdfDictionary desc = font.getAsDict(PdfName.FONTDESCRIPTOR);
//nofontdescriptor
if (desc == null) {
PdfArray descendant = font.getAsArray(PdfName.DESCENDANTFONTS);
if (descendant == null) {
set.add(name.substring(1));
}
else {
for (int i = 0; i < descendant.size(); i++) {
PdfDictionary dic = descendant.getAsDict(i);
processFont(dic, set);
}
}
}
/**
* (Type 1) embedded
*/
else if (desc.get(PdfName.FONTFILE) != null)
;
/**
* (TrueType) embedded
*/
else if (desc.get(PdfName.FONTFILE2) != null)
;
/**
* " (" + font.getAsName(PdfName.SUBTYPE).toString().substring(1) + ") embedded"
*/
else if (desc.get(PdfName.FONTFILE3) != null)
;
else {
set.add(name.substring(1));
}
}
/**
* Extracts the names of the not-embedded fonts from page or XObject resources.
* @param set the set with the font names
* @param resources the resources dictionary
*/
public void processResource(Set<String> set, PdfDictionary resource) {
if (resource == null)
return;
PdfDictionary xobjects = resource.getAsDict(PdfName.XOBJECT);
if (xobjects != null) {
for (PdfName key : xobjects.getKeys()) {
processResource(set, xobjects.getAsDict(key));
}
}
PdfDictionary fonts = resource.getAsDict(PdfName.FONT);
if (fonts == null)
return;
PdfDictionary font;
for (PdfName key : fonts.getKeys()) {
font = fonts.getAsDict(key);
processFont(font, set);
}
}
The code above could be used to retrieve the fonts that are not embedded in the given PDF file. I've improved the code from iText in Action so that it can handle Font's DescendantFontnode, too.
上面的代码可用于检索未嵌入给定 PDF 文件中的字体。我已经改进了来自 iText in Action 的代码,以便它也可以处理 Font 的DescendantFont节点。
回答by Danubian Sailor
When you create Chunk, you declare what font you use.
Create BaseFont from the font you want to use and declare is as BaseFont.EMBEDDED.
Note that when you not set option subsetto true, the whole font will be embedded.
当你创建 Chunk 时,你声明了你使用的字体。
从要使用的字体创建 BaseFont 并声明为 BaseFont.EMBEDDED。
请注意,当您未将选项子集设置为 true 时,将嵌入整个字体。
Be aware that embedding font might violate authorship rights.
请注意,嵌入字体可能会侵犯作者权利。
回答by mtraut
I don't think this is an "iText" use case. Use either PDFBoxor jPod. These implement the PDF model and as such enable you to:
我认为这不是“iText”用例。使用PDFBox或jPod。这些实现了 PDF 模型,因此使您能够:
- open the document
- recurse from the document root down the object tree
- check if this is a font object
- check if the font file is available
- 打开文档
- 从文档根向下递归对象树
- 检查这是否是字体对象
- 检查字体文件是否可用
A check if only embedded fonts are usedis by far more complex (this is , fonts that are not embedded but not used are fine).
如果只嵌入字体的复用是要复杂得多(这是,未嵌入,但没有使用的罚款字体)。
回答by ggkmath
The simplest answer, is to open the PDF file with Adobe Acrobat then:
最简单的答案是使用 Adobe Acrobat 打开 PDF 文件,然后:
- click on File
- select Properties
- click on the Fonts tab
- 点击文件
- 选择属性
- 单击“字体”选项卡
This will show you a list of all fonts in the document. Any font that is embedded will display "(Embedded)" next to the font name.
这将显示文档中所有字体的列表。任何嵌入的字体都会在字体名称旁边显示“(Embedded)”。
For example:
例如:
ACaslonPro-Bold (Embedded)
ACaslonPro-Bold(嵌入式)
where ACaslonPro-Bold is derived from the file name that you embedded it with (e.g. FontFactory.register("/path/to/ACaslonPro-Bold.otf",...
其中 ACaslonPro-Bold 源自您嵌入它的文件名(例如 FontFactory.register("/path/to/ACaslonPro-Bold.otf",...