Jaspersoft Font Extensions
Background
To get reports to display exactly the way that you want them to display you need to ensure that you have exactly the font that you want. Jaspersoft makes this relatively easy through the mechanism of “Font Extensions”. To understand the technical workings of font extensions well, your best resources is the JasperReports Ultimate Guide. If you are working with JasperReports you owe it to yourself to buy a subscription to this resources; it’s great.
I’m not writing about the details of how font extensions work.
In the past creating font extensions was relatively difficult. I wrote about it in this post. It wasn’t really overly difficult if you refer to the documentation and took your time, but it involves creating XML files and is certainly not a point-and-click process. With the release of iReport 3.7 it’s much easier. For details on how to use the wizard to create font extensions, take a look at the iReport Ultimate Guide. It has a whole chapter on “Fonts and Styles”. It’s great.
I’m not trying to replace the content already included in the iReport premium documentation.
So what is the point of this article? This is an example of the complete process of creating a new report, specifying fonts, confirming that the report works well, then deploying the report to a server where the font doesn’t already exist and configuring that server correctly.
Create a report and specify fonts
In the attached report “FontExtensions.jrxml” you can see that I have selected 4 different fonts for the 4 different text fields. The title is set to “DejaVu Serif”. I chose this because it is already installed as a font extension by default in iReport (and JasperServer). How do I know that it’s already installed? You can see the installed fonts from the menu Tools -> Options -> Fonts. You can also tell by looking at the dropdown list of fonts in the property “Font name” for the field. DejaVu Serif is above the line. That means it’s installed. The fonts below the line are on my machine, but they aren’t registered as font extensions, so there could be trouble at deployment time.
Next, I want to set the subtitle to Microsoft’s Comic Sans font. (Please note: I forbid you to use this font in your own reports. It’s terrible. Maybe if you’re creating a report on preschool statistics it would be OK. I only chose it for this article because it’s well known and distinctive.) Oh no! This font appears only below the line! (as “Comic Sans MS”)
Don’t worry: installing a font is simple. From the Tools -> Options -> Fonts screen shown above click “Install Font”. On the first step of the wizard browse to the font file. On the second step specify the separate file with the bold version of the font. The final steps of the wizard are described in detail in the iReport Ultimate Guide, so I won’t bother with details here. For our purposes we can skip through these steps with no changes.
Hooray. Now Comic Sans MS appears “above the line” as well as on the window Tools -> Options -> Fonts. It can safely be selected as the font for the subtitle field.
Next, I created a field for my group header. I included the Japanese characters “日本語” in this field to test support for non-ascii characters. Of course I need to select a font that includes support for these characters. I chose Code2000. It’s not a particularly elegant font visually. But it supports lots and lots of characters. As before, the next step is to install Code2000 as a font extension.
This time be sure to set the PDF Encoding to “Identity-H”. If you forget to set it during the initial run of the wizard, you can edit the font details later as shown in the screenshot here. Embedding the font in the PDF document is not required, but I recommend it. Without that option you are at the mercy of the machine viewing the PDF document to supply the font. With the font embedded you are sure to get what you’re expecting. The file size will be larger, but it’s really not a big difference. The PDF creation process is smart enough to embed only the characters that are required; you don’t get the entire font file embedded into the document.
My final text field is in the detail band. For this field I went with the simple option of using the Java logical font “SansSerif”. This logical font will get translated to some physical font by the JVM when the report gets run. It’s impossible for the report designer to know what font will be selected, so this option is appropriate only when you don’t need a precise font. As a practical matter, one can make a good guess. I see that my JVM on Windows XP is configured to use Arial for its SansSerif font. I see that my JVM on CentOS will use lucidasans. These are common default values, but they are not guaranteed.
Run the report in iReport
Now that the report is created, I’ll run it to confirm that all fonts are working as expected. But to make the details perfectly clear I first deleted my font extensions. Let’s see what this report looks like without the font extensions defined in iReport.
The good news is that the report looks good without the font extensions. The bad news is that the report looks good without the font extensions. It’s bad news because it can make you think that things are configured correctly. Only the PDF export of the report shows the problems caused by not defining the needed font extensions.
Now I put the font extensions back and re-run the report. The internal preview and HTML were already fine before, so they remain fine. But with the font extensions PDF is working well too.
The sharp-eyed reader may notice that the Japanese characters in the detail band still do not display well. I’m willing to ignore this for now. It happens because my JVM translates SansSerif to Arial, and Arial does not include support for Japanese characters. I could solve the problem by updating my JVM properties to use another font or by modifying my report to use Code2000 or Arial Unicode MS or another font with support for these characters.
Deploy the Report to JasperServer
From iReport use the Repository Navigator to deploy the report to JasperServer. Open a browser, find the report, and woo hoo! Everything is good: the title uses DevaVu Serif, the subtitle uses MS Comic Sans, the group header shows Japanese characters correctly using Code2000, and the detail band shows Japanese characters correctly using some unspecified sans serif font.
Just to be sure, let’s take a look at the report in PDF format. On no! It looks exactly like it did in iReport before we defined the font extensions. Japanese characters are missing and it uses the wrong fonts.
If you have been following along closely, you should already know what is wrong. Although we defined the font extensions in iReport, we have not deployed them to JasperServer. That’s the final step we need before the reports will work exactly as intended.
Export and upload the font extensions
We need to get the font extension from iReport over to JasperServer. In JasperServer 3.5 this required tracking down (or creating) the relevant XML files, properties files, and TTF font files. I wrote about font extensions in JasperServer 3.5 previously. In JasperServer 3.7 it’s a single click to export the extension and only a few more clicks to load it up to JasperServer.
Return to the window Tools -> Options -> Fonts and click the button “Export as extension”. That was easy.
In the Repository Navigator pane right-click a folder and choose Add -> Jar Archive. Then on the report unit add a reference to this JAR file. It is possible to add the JAR Archive directly into the report unit. But it’s better to add the JAR independently so that it may be referenced by many reports. In the screenshot below you can see that MyFontExtensions.jar has already been added, and now I am just adding a reference link from my report unit to this resource.
Success
Now that the font extensions have been loaded up into JasperServer—and the report makes use of it—the report works perfectly. HTML, XLS, OpenOffice.org spreadsheets and text documents, and even PDF are all rendered as intended. Don’t forget that most formats, like the ODS file below, refer to the correct font but do not embed it. So these will not render as intended on client machines lacking the relevant font. But PDF with its font embedding can be counted on to produce a pixel-perfect output.
Appendix
One way to be more certain that your reports are well defined is to tell JasperServer to more rigorously enforce fonts. By default JasperServer makes a best guess and substitutes another font in place of one that cannot be found. This is helpful in some respects, but I find that it promotes laziness. I much prefer to set the following option in …/WEB-INF/classes/jasperreports.properties:
# ignore missing fonts in reports net.sf.jasperreports.awt.ignore.missing.font=false
The default value is true. By setting it to false JasperServer will throw an exception when it cannot find the font that it needs. Here’s what the user sees when running the above report before deploying the font extensions when JasperServer does not ignore missing fonts:
net.sf.jasperreports.engine.util.JRFontNotFoundException: Font 'Comic Sans MS' is not available to the JVM. See the Javadoc for more details. at net.sf.jasperreports.engine.util.JRFontUtil.checkAwtFont(JRFontUtil.java:321) at net.sf.jasperreports.engine.util.JRStyledText.getAwtAttributedString(JRStyledText.java:226) at net.sf.jasperreports.engine.fill.TextMeasurer.measure(TextMeasurer.java:362) at net.sf.jasperreports.engine.util.JdkGlyphFixTextMeasurer.measure(JdkGlyphFixTextMeasurer.java:133) at net.sf.jasperreports.engine.fill.JRFillTextElement.chopTextElement(JRFillTextElement.java:1008) at net.sf.jasperreports.engine.fill.JRFillTextField.prepare(JRFillTextField.java:539) at net.sf.jasperreports.engine.fill.JRFillElementContainer.prepareElements(JRFillElementContainer.java:327) at net.sf.jasperreports.engine.fill.JRFillBand.fill(JRFillBand.java:402) ...
or in other languages you get the equivalent error like this:
標楷體 is not available to the jvm.
Of course you wouldn’t want to let errors like this creep into a production system. But that’s why we have testing. During testing it’s far better to see these errors. Without this error I might not have noticed that a report was rendering without Comic Sans MS. This way I see exactly what the problem is, so I can take steps to fix it.