First what you do, is you're trying to install some TTF fonts into your JVM, somewhere in $JRE/lib/fonts, map them and hope things will fly. Then you probably specify that your new font in Jasper Report XML file, something like:
<font fontName="Great Font" />
...and you finding it not working: in your PDF you see Helvetica. If you expect some Asian support (Japanese, e.g.), then you will find blank space there. Familiar, eh? Of course, you go around the XML Schema and finding that Jasper Reports actually has some more arguments to the "font" aggregate, so you adding it:
<font fontName="Great Font" ispdfembedded="true"/>
...and you finding it not working: in your PDF you see Helvetica. Then you, puzzled, finding out that there is also some more attributes (although they are quite odd anyway), so you use them too:
<font fontName="Great Font" ispdfembedded="true"
pdffontname="/madly/hardcoded/path/on/the/system/to/your/greatfont.ttf"/>
...and you still finding it not working: in your PDF you see Helvetica. Then you, angry, yelling "WTF!!!", googling around and you finding a lots of people, suffering from the same problem.
The key to solve this puzzle is to deal with completely stupid implementation of Jasper Reports engine: you have to package these fonts into JAR file and embed into your application. They (developers) think that since it is Java, so "run everywhere", therefore you take your .WAR or .JAR or .EAR file and put on any possible container and it will just work, so no need to setup the environment. In reality, however, when you deploy 1000 applications like this, you also have 1000 duplications of the same stuff. It results to a horrible mess and very very VERY angry sysadmins that literally hates all the guts of Java. Moral: keep it simple, stupid.
So anyways, how to use own TTFs or at least find Japanese visible? JaperReport's answer is: put this stuff into JAR and toss in into the classpath. Here is how to do it:
- In the default, root package, create a property file with a magic name: jasperreports_extension.properties
Developers could not name it more elegant, like fonts.properties or, perfectly elegant, having none of it at all. - Create a package for your fonts. Let's say it is foo.bar.fonts
- In this strange properties file we've made above, you have to put two things at least. One is very magical static property that normally can be hardcoded once and forever somewhere deep in the guts of JasperReports and never ever remembered anymore:
net.sf.jasperreports.extension.registry.factory.simple.font.families
=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
Can you read that wide? - Another property is to reference the reference to the reference of the actual files, embedded into the JAR:
net.sf.jasperreports.extension.simple.font.families.somebullshit
=foo/bar/fonts/fonts.xml
That's how to let finally Jasper find the fonts.xml file. Please not one very nasty and ugly thing: there is no leading slash prior to "foo". Noticed? If you put it (as it should be), then forget it working. - Now, in the foo.bar.fonts package create "fonts.xml". You can change its name in step #4.
- Map your fonts there as it is in examples of JasperReports (demo/fonts).
- Compile all this assembly into a JAR file and toss in somewhere in your app $CLASSPATH. Now your PDF should pick up the font finally.
- Phew!
If you still find this idiotic (like I do), you'd better try Dynamic Jasper http://http://dynamicjasper.sourceforge.net/ and it suppose to help you.
You might ask: how it should be better implemented? OK, you ever heard about X11 and how fonts are mapped there? In the same fashion. Why not use just fontmap.properties file in the JAR and just simply drop fonts there and have zero XML? Yes, it is magic name, but it is the only magic name. And then stick to something like one line per font, e.g.:
family=weight,encoding,embedded,file.ttf
Said that, it might look this way:
greatfamily=n,UTF-8,t,greatfont-nnormal.ttf
greatfamily=i,UTF-8,t,greatfont-italic.ttf
greatfamily=b,UTF-8,t,greatfont-bold.ttf
greatfamily=bi,UTF-8,t,greatfont-bold-italic.ttf
Then, you run something like $JASPER_REPORTS/bin/fontpack ...and it would create such a JAR right away for you. How that sounds? That sounds just greatly simplified yet idiotism. What it actually should be: you specify font name "Great Font" (not path to actual TTF!) in the XML and it picks up automatically from the JVM right away. If font is not installed, then it has to fall-back to the default (Helvetica, in this case) by warning the user to the log file (instead of crashing, by the way).
Still, I suffer from its performance, if this is the word. Generating PDFs are still hell very slow for my requirements. My next step will be ditching JasperReports and go OpenOffice.org as template editor and renderer iText based engine. Well, if company will pay for that. :-)
No comments:
Post a Comment