Unembed a font

Tags: fontsembedded fontsiText 5
Files: 
/**
 * Example written by Bruno Lowagie in answer to a question by a customer.
 */
package sandbox.fonts;
 
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
 
import sandbox.WrapToTest;
 
@WrapToTest
public class UnembedFont {
 
    public static final String SRC = "results/fonts/withSerifFont.pdf";
    public static final String DEST = "results/fonts/withoutSerifFont.pdf";
 
    public static void main(String[] args) throws DocumentException, IOException {
        UnembedFont app = new UnembedFont();
        app.manipulatePdf(SRC, DEST);
    }
 
    /**
     * Creates a PDF with an embedded font.
     */
    public void createPdf(String file) throws DocumentException, IOException {
        // step 1
        Document document = new Document();
        // step 2
        OutputStream os = new FileOutputStream(file);
        PdfWriter.getInstance(document, os);
        // step 3
        document.open();
        // step 4
        BaseFont bf = BaseFont.createFont("resources/fonts/PT_Serif-Web-Regular.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED);
        Font f = new Font(bf, 12);
        document.add(new Paragraph("This is a test with Times New Roman.", f));
        // step 5
        document.close();
    }
 
    /**
     * Removes the embedded font
     */
    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
	    createPdf(src);
        // we create a reader instance
        PdfReader reader = new PdfReader(src);
        // we loop over all objects
        PdfObject obj;
        for (int i = 1; i < reader.getXrefSize(); i++) {
            obj = reader.getPdfObject(i);
            // we skip all objects that aren't a dictionary
            if (obj == null || !obj.isDictionary())
                continue;
            // we process all dictionaries
            unembedTTF((PdfDictionary)obj);
        }
        // removing unused objects will remove unused font file streams
        reader.removeUnusedObjects();
        // we persist the altered document
        OutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = new PdfStamper(reader, os);
        stamper.close();
    }
 
    /**
     * Processes a dictionary.
     * In case of font dictionaries, the dictionary is processed.
     */
    public void unembedTTF(PdfDictionary dict) {
        // we ignore all dictionaries that aren't font dictionaries
        if (!dict.isFont())
            return;
        // we only remove TTF fonts
        if (dict.getAsDict(PdfName.FONTFILE2) != null) {
            return;
        }
        // check if a subset was used (in which case we remove the prefix)
        PdfName baseFont = dict.getAsName(PdfName.BASEFONT);
        if (baseFont.getBytes()[7] == '+') {
            baseFont = new PdfName(baseFont.toString().substring(8));
            dict.put(PdfName.BASEFONT, baseFont);
        }
        // we check if there's a font descriptor
        PdfDictionary fontDescriptor = dict.getAsDict(PdfName.FONTDESCRIPTOR);
        if (fontDescriptor == null)
            return;
        // is there is, we replace the fontname and remove the font file
        fontDescriptor.put(PdfName.FONTNAME, baseFont);
        fontDescriptor.remove(PdfName.FONTFILE2);
    }
}
File nameRaw URLUpdated
UnembedFont.javaUnembedFont.java2015-11-07 5:28 pm
Results: 
File nameRaw URLUpdated
cmp_withSerifFont.pdfcmp_withSerifFont.pdf2015-11-07 5:30 pm
cmp_withoutSerifFont.pdfcmp_withoutSerifFont.pdf2015-11-07 5:30 pm