How to Test If My Font Is Rendered Correctly in PDF

How can I test if my font is rendered correctly in pdf?

Since jasper report use the itext library the easiest way to test if your font will be rendered correctly in pdf is to test it directly with itext.

Example program*, adapted from iText: Chapter 11: Choosing the right font

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.PdfWriter;

public class FontTest {

/** The resulting PDF file. */
public static final String RESULT = "fontTest.pdf";
/** the text to render. */
public static final String TEST = "Test to render this text with the turkish lira character \u20BA";

public void createPdf(String filename) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
document.open();
BaseFont bf = BaseFont.createFont(
"pathToMyFont/myFont.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font font = new Font(bf, 20);
ColumnText column = new ColumnText(writer.getDirectContent());
column.setSimpleColumn(36, 730, 569, 36);
column.addElement(new Paragraph(TEST, font));
column.go();
document.close();
}

public static void main(String[] args) throws IOException, DocumentException {
new FontTest().createPdf(RESULT);
}
}

Some notes (seen in example):

  • To render special characters use it's encoded value example
    \u20BA to avoid problems of encoding type on your file.
  • Consider to always use Unicode encoding, this is recommended approach
    in the newer PDF standard (PDF/A, PDF/UA) and gives you the possibility to mix
    different encoding types, with the only dis-advantage of slightly
    larger file size.

Conclusion:

If your font is rendered correctly in the "fontTest.pdf", you have a
problem with your font-extensions in jasper report.

If you font is not rendered correctly in the "fontTest.pdf", there is
nothing you can do in jasper reports, you need to find another font.


*Latest jasper-reports distribution use a special version itext-2.1.7, the imports in this version is com.lowagie.text, if you are using later version the imports are com.itextpdf.text as in adapted example.

PDF – A font displays correctly even it is not installed in PC?

Fonts can be embedded in PDF files. If one font is missing, the text is displayed anyway using another classic font. You can have a great explanation here : http://www.prepressure.com/pdf/basics/fonts

java / pdf text rendering

This answer essentially is a roundup of my comments.

The first attempt which involved using the font "Time New Roman" (actually Times-Roman) which is one of the PDF base font (not to compute and output all the font metrics into the pdf) for the PDF and "TimesRoman" for Java AWT, resulted in

Attempt with standard-14 Times-Roman

Essentially: your app uses what the Java AWT considers TimesRoman plain at 16pt applying font metrics in its own manner; your PDF viewer uses what it considers Times-Roman at 16 user space units applying font metrics as specified in the PDF spec. All you can expect is some similarity (otherwise one of those contexts would have made a very bad choice) but not at all identity.

David actually explained that in more detail in item 1 (different fonts) and item 3 (different application of kerning and substitutions) in his answer.

Furthermore,

BTW: Beginning with PDF 1.5, the special treatment given to the standard 14 fonts is deprecated. (section 9.6.2.1 in ISO 32000-1). Thus by not including the font metrics explicitly in the PDF, you do something that has been deprecated for many many years.

The next attempt which involved not using pdf base fonts to be sure that the same font (ttf file) is used by Java and Adobe Reader, required calculation of character widths to embed in the PDF. In this context the assumption was made that all number (widths, ascent, descent,...) are relative to glyph unit (1em based?), where 1em = 1000 (and 1em is the width of the M character). Consequentially it was attempted to find the correct java font size to have the width of the M character to be equal to 1000 and then generate all requiered parameters from that font.

no, not em-based, but instead: A font defines the glyphs at one standard size. This standard is arranged so that the nominal height of tightly spaced lines of text is 1 unit. Thus, 1000 glyph space units are the height of that nominal line.

This led to the question what exactly is that "nominal line". Fortunately it is easier to approach this the other way around: A font at size 1 by definition is a font for which that "nominal line" has a height of 1. Thus,

shouldn't the Widths array be be filled with 1000 * fm.charWidth(i) where fm are the metrics of the font at size 1? Or, as AWT works with int widths, with fm.charWidth(i) where fm are the metrics of the font at size 1000?

Taking this into account, simply setting font size to 1000 and without bruteforcing to found the EM/Line height size, the result in pdf is really to java. But there is still a little difference, maybe it is due to the text drawing algorigthm (kerning maybe differ from java and adobe reader?). See image below, we can see, with Verdana, that the text is a little bit smaller (in width) in pdf than in java.

Attempt with embedded fonts and correct character widths

Have a look at the FontMetrics.charWidth method comment: Note that the advance of a String is not necessarily the sum of the advances of its characters. AWT additionally applies kerning etc resulting in slight deviations. In a PDF, though, using a single Tj operation, those advances do add up.

If you want to use kerning in PDFs, you have to explicitly write those deviations from the standard widths. Here the TJ operator is quite handy allowing a mixed array of Strings and offsets as parameter.

If you want to substitute some characters by e.g. ligatures, you also have to do that yourself

PDF: how do I find how much space will the text occupy when rendered?

The mechanisms and math of PDF text rendering are exhaustively explained in the PDF specification ISO 32000-1. Most important are chapters 8 Graphics and 9 Text.

Essentially you need to know the current graphic state (which should be easy because you after all are the one who creates the PDF) and the metrics of the font you use and then calculate.

Most of these details are governed by the operators and calculations described in chapter 9 but one should not forget the current transformation matrix described in chapter 8.

PDF font mapping error

The first point is that the file opens and renders correctly in Acrobat, so its almost certain that the file is correct. In fact it opens and renders correctly in a wide range of PDF consumers, so in fact it is correct.

The font in question is a TrueType font, so actually yes, there are two kinds of 'encoding'. First there is PDF/PostScript Encoding. This maps a character code into a glyph name. In your case it maps character code 1 to glyph name /A.

In a PostScript font we would then look up the name /A in the CharStrings dictionary, and that would give us the character description, which we would then execute. Things are different with a TrueType font though.

You can find this on page 430 of the 1.7 PDF Reference Manual, where it states that:

"A TrueType font program’s built-in encoding maps directly from character codes to glyph descriptions by means of an internal data structure called a “cmap” (not to be confused with the CMap described in Section 5.6.4, “CMaps”)."

I believe in your case that you simply need to use the character code (0x01) directly in the CMAP sub table. This will give you a GID of 36.



Related Topics



Leave a reply



Submit