This isn't necessarily a solution, but potentially another option as a workaround that I came up with after we noticed the same issue and did some investigating. It's also (IMO) better than generating a dummy report.
On startup (or at some other point depending on your needs), make the following call:
FontMappingManagerFactory.getInstance().getFontMappingManager(format, Locale.getDefault());
Why?
BIRT uses com.lowagie.text.FontFactory (iText) to register the fonts. Calls to that class are made from
org.eclipse.birt.report.engine.layout.pdf.font.FontMappingManagerFactory which also spits out the log entries given in the question.
Within FontMappingManagerFactory we can see where the log entries are coming from:
private static void registerFontPath( final String fontPath )
{
AccessController.doPrivileged( new PrivilegedAction<Object>( ) {
public Object run( )
{
long start = System.currentTimeMillis( );
File file = new File( fontPath );
if ( file.exists( ) )
{
if ( file.isDirectory( ) )
{
FontFactory.registerDirectory( fontPath );
}
else
{
FontFactory.register( fontPath );
}
}
long end = System.currentTimeMillis( );
logger.info( "register fonts in " + fontPath + " cost:"
+ ( end - start ) + "ms" ); // <-- Here!
return null;
}
} );
}
Working backwards, we see that registerFontPath(String) is called by loadFontMappingConfig(URL), etc etc resulting in the following call hierarchy:
getFontMappingManager(String, Locale)
`-- createFontMappingManager(String, Locale)
`-- loadFontMappingConfig(String)
`-- loadFontMappingConfig(URL)
`-- registerFontPath(String)
And getFontMappingManager(String, Locale) is the public method we can call. More importantly, however, is that the method also caches the FontMappingManager that gets created:
public synchronized FontMappingManager getFontMappingManager(
String format, Locale locale )
{
HashMap managers = (HashMap) cachedManagers.get( format );
if ( managers == null )
{
managers = new HashMap( );
cachedManagers.put( format, managers );
}
FontMappingManager manager = (FontMappingManager) managers.get( locale );
if ( manager == null )
{
manager = createFontMappingManager( format, locale );
managers.put( locale, manager );
}
return manager;
}
As a result, when you're ready to go generate your PDF, it will already be in the cache and BIRT won't have to go call down to the FontFactory and re-register the fonts.
But what about the format String?
This bit is some speculation, but I think the valid options are the OUTPUT_FORMAT_XXX Strings in IRenderOption. For our purposes I debugged to see that we want the String to be pdf. Considering that's also conveniently the desired output format, I assume IRenderOption.OUTPUT_FORMAT_PDF is the route to go.
If you're ultimately creating both PDFs and HTML files, it appears that you could make the call twice (once with IRenderOption.OUTPUT_FORMAT_PDF and once with IRenderOption.OUTPUT_FORMAT_HTML) and only the font config files which are different will be considered (ie. you won't be reading from c:/windows/fonts twice).
All that said, take this with a grain of salt. I believe this is completely safe, since the purpose of getFontMappingManager(String, Locale) is to get an object for accessing available fonts, etc., and it conveniently caches the result. However, if that were to change in the future you may end up with a tricky-to-find bug on your hands.