簡體   English   中英

如何使用Java iText檢查所有使用的字體是否嵌入到PDF中?

[英]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文件,然后:

  1. 單擊文件
  2. 選擇屬性
  3. 單擊“字體”選項卡

這將顯示文檔中所有字體的列表。 嵌入的任何字體都會在字體名稱旁邊顯示“(嵌入)”。

例如:

ACaslonPro-Bold(嵌入式)

其中ACaslonPro-Bold源自您嵌入它的文件名(例如FontFactory.register("/path/to/ACaslonPro-Bold.otf",...

我不認為這是一個“iText”用例。 使用PDFBoxjPod 這些實現了PDF模型,因此您可以:

  • 打開文件
  • 從文檔根據對象樹遞減
  • 檢查這是否是一個字體對象
  • 檢查字體文件是否可用

如果只使用嵌入字體支票是要復雜得多(這是,未嵌入,但沒有使用的罰款字體)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM