Skip to main content
Skip table of contents

Unembed a font

How to unembed a font from a PDF


unembedfont

JAVA
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2023 Apryse Group NV
    Authors: Apryse Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.sandbox.fonts;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.font.PdfFontFactory.EmbeddingStrategy;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.PdfDictionary;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

public class UnembedFont {
    public static final String DEST = "./target/sandbox/fonts/unembed_font.pdf";

    public static final String SRC = "./target/sandbox/fonts/withSerifFont.pdf";
    public static final String FONT = "./src/main/resources/font/PT_Serif-Web-Regular.ttf";

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();

        new UnembedFont().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {

        // Create a pdf file with an embedded font in memory.
        byte[] sourcePdfBytes = createSourcePdf().toByteArray();
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(sourcePdfBytes)),
                new PdfWriter(dest));

        for (int i = 0; i < pdfDoc.getNumberOfPdfObjects(); i++) {
            PdfObject obj = pdfDoc.getPdfObject(i);

            // Skip all objects that aren't a dictionary
            if (obj == null || !obj.isDictionary()) {
                continue;
            }

            // Process all dictionaries
            unembedTTF((PdfDictionary) obj);
        }

        pdfDoc.close();
    }

    /*
     * Creates a PDF with an embedded font.
     */
    public ByteArrayOutputStream createSourcePdf() throws Exception {
        ByteArrayOutputStream resultFile = new ByteArrayOutputStream();
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(resultFile));
        Document doc = new Document(pdfDoc);

        PdfFont font = PdfFontFactory.createFont(FONT, PdfEncodings.WINANSI, EmbeddingStrategy.PREFER_EMBEDDED);
        doc.add(new Paragraph("This is a test with Times New Roman.").setFont(font));

        doc.close();
        return resultFile;
    }

    /*
     * Unembeds a font dictionary.
     */
    public void unembedTTF(PdfDictionary dict) {

        // Ignore all dictionaries that aren't font dictionaries
        if (!PdfName.Font.equals(dict.getAsName(PdfName.Type))) {
            return;
        }

        // Only TTF fonts should be removed
        if (dict.getAsDictionary(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.getValue().getBytes()[6] == '+') {
            baseFont = new PdfName(baseFont.getValue().substring(7));
            dict.put(PdfName.BaseFont, baseFont);
        }

        // Check if there's a font descriptor
        PdfDictionary fontDescriptor = dict.getAsDictionary(PdfName.FontDescriptor);
        if (fontDescriptor == null) {
            return;
        }

        // Replace the fontname and remove the font file
        fontDescriptor.put(PdfName.FontName, baseFont);
        fontDescriptor.remove(PdfName.FontFile2);
    }
}

UnembedFont C#

C#
using System;
using System.IO;
using System.Text;
using iText.IO.Font;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;

namespace iText.Samples.Sandbox.Fonts
{
    public class UnembedFont
    {
        public static readonly String DEST = "results/sandbox/fonts/unembed_font.pdf";

        public static readonly String SRC = "results/sandbox/fonts/withSerifFont.pdf";
        public static readonly String FONT = "../../../resources/font/PT_Serif-Web-Regular.ttf";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new UnembedFont().ManipulatePdf(DEST);
        }

        protected void ManipulatePdf(String dest)
        {
            
            // Create a pdf file with an embedded font in memory.
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(new MemoryStream(CreatePdf().ToArray())),
                new PdfWriter(dest));

            for (int i = 0; i < pdfDoc.GetNumberOfPdfObjects(); i++)
            {
                PdfObject obj = pdfDoc.GetPdfObject(i);

                // Skip all objects that aren't a dictionary
                if (obj == null || !obj.IsDictionary())
                {
                    continue;
                }

                // Process all dictionaries
                UnembedTTF((PdfDictionary) obj);
            }

            pdfDoc.Close();
        }

        /*
         * Creates a PDF with an embedded font.
         */
        public MemoryStream CreatePdf()
        {
            MemoryStream resultFile = new MemoryStream();
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(resultFile));
            Document doc = new Document(pdfDoc);

            PdfFont font = PdfFontFactory.CreateFont(FONT, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
            doc.Add(new Paragraph("This is a test with Times New Roman.").SetFont(font));

            doc.Close();
            return resultFile;
        }

        /*
         * Unembeds a font dictionary.
         */
        public void UnembedTTF(PdfDictionary dict)
        {
            // Ignore all dictionaries that aren't font dictionaries
            if (!PdfName.Font.Equals(dict.GetAsName(PdfName.Type)))
            {
                return;
            }

            // Only TTF fonts should be removed
            if (dict.GetAsDictionary(PdfName.FontFile2) != null)
            {
                return;
            }

            // Check if a subset was used (in which case we remove the prefix)
            PdfName baseFont = dict.GetAsName(PdfName.BaseFont);
            if (Encoding.UTF8.GetBytes(baseFont.GetValue())[6] == '+')
            {
                baseFont = new PdfName(baseFont.GetValue().Substring(7));
                dict.Put(PdfName.BaseFont, baseFont);
            }

            // Check if there's a font descriptor
            PdfDictionary fontDescriptor = dict.GetAsDictionary(PdfName.FontDescriptor);
            if (fontDescriptor == null)
            {
                return;
            }

            // Replace the fontname and remove the font file
            fontDescriptor.Put(PdfName.FontName, baseFont);
            fontDescriptor.Remove(PdfName.FontFile2);
        }
    }
}

Results


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.