3

我们从版本 2(目前使用 4.2.2)开始使用 BIRT,并且一直受到 PDF(itext?)字体注册时间的困扰。

org.eclipse.birt.report.engine.layout.pdf.font.FontMappingManagerFactory$2 run
INFO: register fonts in c:/windows/fonts cost:17803ms

此过程仅在第一次使用渲染时发生。后续渲染没有问题。

问题似乎是访问所有系统连接的驱动器时浪费的时间。

在org.eclipse.birt.report.engine.fonts 插件中编辑 fontsConfig.xml ,减少搜索路径并不能解决问题。BIRT 可以访问所有连接的驱动器

<font-paths>
    <path path="/windows/fonts" />
</font-paths>

是否有一个简单的解决方案,而无需呈现“虚拟”报告以在后台初始化 BIRT?

4

2 回答 2

3

这不一定是解决方案,但可能是我在注意到相同问题并进行一些调查后提出的另一种解决方法。它也(IMO)比生成虚拟报告更好。

在启动时(或根据您的需要在其他时间点),进行以下调用:

FontMappingManagerFactory.getInstance().getFontMappingManager(format, Locale.getDefault());

为什么?

BIRT 使用com.lowagie.text.FontFactory( iText ) 注册字体。对该类的调用也会从该类中 org.eclipse.birt.report.engine.layout.pdf.font.FontMappingManagerFactory吐出问题中给出的日志条目。

在里面FontMappingManagerFactory我们可以看到日志条目的来源:

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;
        }
    } );
}

向后工作,我们看到registerFontPath(String)loadFontMappingConfig(URL)等调用,导致以下调用层次结构:

getFontMappingManager(String, Locale)
`-- createFontMappingManager(String, Locale)
    `-- loadFontMappingConfig(String)
        `-- loadFontMappingConfig(URL)
            `-- registerFontPath(String)

并且getFontMappingManager(String, Locale)是我们可以调用的公共方法。然而,更重要的是,该方法还缓存了FontMappingManager被创建的内容:

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;
}

因此,当您准备好生成 PDF 时,它已经在缓存中,并且 BIRT 不必向下调用 FontFactory 并重新注册字体。

但是格式字符串呢?

这一点是一些猜测,但我认为有效的选项OUTPUT_FORMAT_XXX StringIRenderOption. 出于我们的目的,我进行了调试以查看我们想要Stringpdf. 考虑到这也是方便的输出格式,我认为 IRenderOption.OUTPUT_FORMAT_PDF这是要走的路。

如果您最终同时创建 PDF 和 HTML 文件,您似乎可以进行两次调用(一次使用IRenderOption.OUTPUT_FORMAT_PDF,一次使用IRenderOption.OUTPUT_FORMAT_HTML),并且只会考虑不同的字体配置文件(即,您不会从c:/windows/fonts两次)。


话虽如此,但还是要加一粒盐。我相信这是完全安全的,因为 的目的getFontMappingManager(String, Locale)是获取一个用于访问可用字体等的对象,并且它可以方便地缓存结果。但是,如果将来要改变这种情况,您最终可能会遇到一个难以发现的错误。

于 2017-05-10T21:51:37.870 回答
0

我建议您可以修改 fontsConfig.xml 并删除不再需要的字体。还要删除您不希望 birt 检查字体的驱动器。

于 2014-03-06T15:01:50.883 回答