PDFOne (for Java)
Create, edit, view, print & enhance PDF documents and forms in Java SE/EE
Compatibility
J2SE J2EE Windows Linux Mac (OS X)

Providing Custom Substitutes For Non-Embedded PDF Fonts With PDFOne

Learn to provide substitute fonts when rendering PDF documents.
By V. Subhash

It is not unusual for PDF documents to use certain fonts but does not have them embedded in it. (Who wants to embed Times New Roman?) This is usually never a problem, as the the fonts are likely to be installed in your computer. Sometimes, though, the fonts are neither embedded in the document nor installed in your OS. PDF viewer applications such as Adobe Reader will try to do some guesswork on these fonts and substitute them with an installed font or a font from its own collection.

PDF Documents With Non-Embedded But Installed Fonts

Here is an example. This document uses two non-embedded fonts Gentium and Anonymous Pro. On my computer, where these fonts are installed, the document would look like this.

PDF Document With Non-Embedded Fonts (On A Computer That Has Those Fonts)

PDF Documents With Non-Embedded And Non-Installed Fonts

On a computer that does not have these fonts, the document would look as below.

PDF Document With Non-Embedded Fonts (On A Computer That Does Not Have Those Fonts)

Although Adobe Reader tries to do a good job, it has replaced a serif font with a sans serif font and a monospace font with a serif font. Oh, the abominations!

Automatic PDF Font Substitution by Adobe Reader

Default Font Substitution In PDFOne

PDFOne's document, viewer and printer components also do something similar. It replaces the missing fonts with Arial. So, the bottom line is clear. If you want the output to be true to its source, you need to have non-embedded fonts installed. Installing fonts just to support a few documents is a waste of computer resources, as it slows down the OS.

Custom Font Substitution In PDFOne

A simpler alternative is to have the fonts available in some local folder and make PDFOne aware of this location. Here is my code example.

import java.awt.Font;
import java.awt.FontFormatException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import com.gnostice.pdfone.PDFOne;
import com.gnostice.pdfone.PdfDocument;
import com.gnostice.pdfone.PdfException;
import com.gnostice.pdfone.PdfRenderFontHandler;


public class Supply_Missing_Fonts implements  PdfRenderFontHandler {
    
  public static void main(String[] args) throws IOException, PdfException {
    // Load an existing document
    PdfDocument doc = new PdfDocument();
    doc.load("PDF_with_non_embedded_fonts.pdf");
    
    // Ensure this class calls PdfRenderFontHandler methods 
    doc.getRenderingOptions().setRenderFontHandler(new Supply_Missing_Fonts());    
    
    // Export pages 1 and 2 to a BMP - this method may encounter
    // non-embedded fonts that are not installed in the host OS
    doc.saveAsImage("bmp", "1-2", "exported_image", ".", 96);
    
    // Clean up
    doc.close();
  }

  // onFontNotFound event handler that supplies substitute fonts
  public Font onFontNotFound(Font arg0, String arg1, int arg2) {
    Font fnt = null;
    String fontPathname = null;
    FileInputStream fis;
    int fontType = -1;
    
    System.out.println(
        "Font \"" + 
         arg1 + 
         "\" is neither installed in the host OS nor embedded in the PDF. ");
    
    
    // --- PUT YOUR FONT SUBSTITUTIONS BELOW ---
    // Specify correct pathname and font type of the substitute font files
    if (arg1.contentEquals("Gentium") || arg1.contentEquals("Gentium,Bold")) {
      fontPathname = ".\\GenR102.TTF";
      fontType = Font.TRUETYPE_FONT;      
    } else if (arg1.contentEquals("AnonymousPro")) {
      fontPathname = ".\\Anonymous Pro.ttf";
      fontType = Font.TRUETYPE_FONT;
    }
    // --- PUT YOUR FONT SUBSTITUTIONS ABOVE ---

    // Create a font object created from the substitute font file
    try {      
      fis = new FileInputStream(fontPathname);
      try {
        fnt = Font.createFont(fontType, fis);  
        System.out.println(
            "\tIt has been substituted with \"" + 
            fnt.getName() + 
            "\" from \"" + 
            fontPathname + "\"");
      } catch (FontFormatException e) {         
          System.out.println("\tERROR: Wrong font format specified .");
      } catch (IOException e) {          
        System.out.println("\tERROR: IO error while creating substitute font object.");
      }
    } catch (FileNotFoundException e) {        
      System.out.println("\tERROR: Incorrect pathname for substitute font file.");
    } catch (NullPointerException e) {           
      System.out.println("\tERROR: No alternative font specified.");
    }    
    
    // Return the substitute font object
    return(fnt);    
  }  
}

This Java program loads a PDF document and exports the pages to bitmaps. Usually, the page export function would have substituted all (Gentium and Anonymous Pro) text with Arial. In the example, though, custom substitute fonts were provided and exported images look like the original PDF document.

You can run this code on any PDF document. Whenever a non-embedded and non-installed font is found, the name of the font is printed on the console. After that, you need to either find appropriate font files with these names or choose close alternatives, copy the files to a folder location, modify the part where the font pathnames and types are specified in the onFontNotFound event handler, and run the program again. Please note that this ability to provide custom substitute fonts was introduced in PDFOne in Version 3.5.3 (released on February 17, 2011). If you have not updated your PDFOne jar, then do so now.

Custom PDF Font Substitution By PDFOne
----oO0Oo---
Downloads
  1. Original code example by Gnostice DevTools member Abhishek - FontNotFoundDemo.java
  2. For those who are totally hamstrung creating a document with non-embedded fonts:
    1. PDF_with_non_embedded_fonts.pdf
    2. Website for Gentium font
    3. Website for Anonymous Pro font

---o0O0o---

Our .NET Developer Tools
XtremeDocumentStudio .NET

Multi-format document-processing component suite for .NET developers.

PDFOne .NET

A .NET PDF component suite to create, edit, view, print, reorganize, encrypt, annotate, and bookmark PDF documents in .NET applications.

Our Delphi/C++Builder developer tools
XtremeDocumentStudio Delphi

Multi-format document-processing component suite for Delphi/C++Builder developers, covering both VCL and FireMonkey platforms.

eDocEngine VCL

A Delphi/C++Builder component suite for creating documents in over 20 formats and also export reports from popular Delphi reporting tools.

PDFtoolkit VCL

A Delphi/C++Builder component suite to edit, enhance, view, print, merge, split, encrypt, annotate, and bookmark PDF documents.

Our Java developer tools
XtremeDocumentStudio (for Java)

Multi-format document-processing component suite for Java developers.

PDFOne (for Java)

A Java PDF component suite to create, edit, view, print, reorganize, encrypt, annotate, bookmark PDF documents in Java applications.

Our Platform-Agnostic Cloud and On-Premises APIs
StarDocs

Cloud-hosted and On-Premises REST-based document-processing and document-viewing APIs

Privacy | Legal | Feedback | Newsletter | Blog | Resellers © 2002-2017 Gnostice Information Technologies Private Limited. All rights reserved.