[英]How to check that all used fonts are embedded in PDF with Java iText?
如何檢查PDF文件中使用的所有字體是否都嵌入到Java和iText文件中? 我有一些現有的PDF文檔,我想驗證他們只使用嵌入字體。
這需要檢查沒有使用PDF標准字體,並且其他使用的字體嵌入在文件中。
查看來自iText in Action的ListUsedFonts示例。
http://itextpdf.com/examples/iia.php?id=287
看起來這將打印出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();
}
}
/**
* 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);
}
}
上面的代碼可用於檢索未嵌入給定PDF文件中的字體。 我在Action中改進了iText的代碼,以便它也可以處理Font的DescendantFont節點。
創建Chunk時,聲明您使用的字體。
從您要使用的字體創建BaseFont並聲明為BaseFont.EMBEDDED。
請注意,如果未將option subset設置為true,則將嵌入整個字體。
請注意,嵌入字體可能會侵犯作者權限。
最簡單的答案是用Adobe Acrobat打開PDF文件,然后:
這將顯示文檔中所有字體的列表。 嵌入的任何字體都會在字體名稱旁邊顯示“(嵌入)”。
例如:
ACaslonPro-Bold(嵌入式)
其中ACaslonPro-Bold源自您嵌入它的文件名(例如FontFactory.register("/path/to/ACaslonPro-Bold.otf",...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.