XSLT-1.0中SVG文本水印引发InvocationTargetException问题求助
问题:SVG水印在FOP渲染PDF时抛出字体相关错误
我尝试用SVG文本作为PDF水印,对应的XSLT模板代码如下:
<xsl:template name="Draft"> <fo:block-container z-index="-1" position="absolute" right="-20mm"> <fo:block> <fo:instream-foreign-object> <svg:svg xmlns:svg="http://www.w3.org/2000/svg" height="157mm" width="190mm"> <svg:text x="140" y="520" transform="rotate(-46.5,50,350)" textLength="125mm" font-style="fill:rgb(0,0,0);fill-opacity:0.3" font-size="50mm" lengthAdjust="spacingAndGlyphs"> DRAFT </svg:text> </svg:svg> </fo:instream-foreign-object> </fo:block> </fo:block-container> </xsl:template>
执行时出现如下错误:
Exception in thread "main" java.lang.InternalError: java.lang.reflect.InvocationTargetException at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:87) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:75) at java.desktop/sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:139) at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:173) at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:201) at java.desktop/sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:80) at org.apache.batik.bridge.DefaultFontFamilyResolver.<clinit>(DefaultFontFamilyResolver.java:86) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.createImageInfo(PreloaderSVG.java:165) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.getImage(PreloaderSVG.java:131) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.access$200(PreloaderSVG.java:108) at org.apache.fop.image.loader.batik.PreloaderSVG.preloadImage(PreloaderSVG.java:76) at org.apache.xmlgraphics.image.loader.ImageManager.preloadImage(ImageManager.java:176) at org.apache.fop.render.intermediate.AbstractIFPainter.drawImageUsingDocument(AbstractIFPainter.java:323) at org.apache.fop.render.pdf.PDFPainter.drawImage(PDFPainter.java:290) at org.apache.fop.render.intermediate.IFRenderer.renderForeignObject(IFRenderer.java:1324) at org.apache.fop.render.AbstractRenderer.renderInlineViewport(AbstractRenderer.java:1034) at org.apache.fop.render.AbstractPathOrientedRenderer.renderInlineViewport(AbstractPathOrientedRenderer.java:836) at org.apache.fop.render.intermediate.IFRenderer.renderInlineViewport(IFRenderer.java:860) at org.apache.fop.render.AbstractRenderer.renderInlineArea(AbstractRenderer.java:877) at org.apache.fop.render.intermediate.IFRenderer.renderInlineArea(IFRenderer.java:924) at org.apache.fop.render.AbstractRenderer.renderLineArea(AbstractRenderer.java:845) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:704) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:758) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.AbstractPathOrientedRenderer.renderReferenceArea(AbstractPathOrientedRenderer.java:759) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:744) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.intermediate.IFRenderer.renderBlockViewport(IFRenderer.java:809) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:737) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.AbstractRenderer.renderRegion(AbstractRenderer.java:418) at org.apache.fop.render.AbstractRenderer.renderRegionViewport(AbstractRenderer.java:38
相关注意事项:
- 移除水印后PDF可正常渲染
- 其他未指定font-family的元素可自动转为UTF-8编码渲染
服务器日志对比
服务器1(水印渲染成功)
[WARN] FOUserAgent - Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400". [WARN] FOUserAgent - Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400". [WARN] FOUserAgent - Font "Arial,normal,400" not found. Substituting with "any,normal,400". [INFO] FOUserAgent - Rendered page #1. [INFO] FOUserAgent - Rendered page #2. [INFO] FOUserAgent - Rendered page #3.
服务器2(添加水印失败)
Jul 25, 2023 1:15:13 PM org.apache.fop.events.LoggingEventListener processEvent WARNING: Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400". Jul 25, 2023 1:15:13 PM org.apache.fop.events.LoggingEventListener processEvent WARNING: Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400". Exception in thread "main" java.lang.InternalError: java.lang.reflect.InvocationTargetException at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:87) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:75) at java.desktop/sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:139) at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:173) at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:201) at java.desktop/sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:80) at org.apache.batik.bridge.DefaultFontFamilyResolver.<clinit>(DefaultFontFamilyResolver.java:86) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.createImageInfo(PreloaderSVG.java:165) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.getImage(PreloaderSVG.java:131) at org.apache.fop.image.loader.batik.PreloaderSVG$Loader.access$200(PreloaderSVG.java:108) at org.apache.fop.image.loader.batik.PreloaderSVG.preloadImage(PreloaderSVG.java:76) at org.apache.xmlgraphics.image.loader.ImageManager.preloadImage(ImageManager.java:176) at org.apache.fop.render.intermediate.AbstractIFPainter.drawImageUsingDocument(AbstractIFPainter.java:323) at org.apache.fop.render.pdf.PDFPainter.drawImage(PDFPainter.java:290) at org.apache.fop.render.intermediate.IFRenderer.renderForeignObject(IFRenderer.java:1324) at org.apache.fop.render.AbstractRenderer.renderInlineViewport(AbstractRenderer.java:1034) at org.apache.fop.render.AbstractPathOrientedRenderer.renderInlineViewport(AbstractPathOrientedRenderer.java:836) at org.apache.fop.render.intermediate.IFRenderer.renderInlineViewport(IFRenderer.java:860) at org.apache.fop.render.AbstractRenderer.renderInlineArea(AbstractRenderer.java:877) at org.apache.fop.render.intermediate.IFRenderer.renderInlineArea(IFRenderer.java:924) at org.apache.fop.render.AbstractRenderer.renderLineArea(AbstractRenderer.java:845) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:704) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:758) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.AbstractPathOrientedRenderer.renderReferenceArea(AbstractPathOrientedRenderer.java:759) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:744) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.intermediate.IFRenderer.renderBlockViewport(IFRenderer.java:809) at org.apache.fop.render.AbstractRenderer.renderBlock(AbstractRenderer.java:737) at org.apache.fop.render.intermediate.IFRenderer.renderBlock(IFRenderer.java:1004) at org.apache.fop.render.AbstractRenderer.renderBlocks(AbstractRenderer.java:689) at org.apache.fop.render.AbstractRenderer.renderRegion(AbstractRenderer.java:418) at org.apache.fop.render.AbstractRenderer.renderRegionViewport(AbstractRenderer.java:38
服务器2(移除水印后正常)
Jul 25, 2023 1:15:13 PM org.apache.fop.events.LoggingEventListener processEvent WARNING: Font "Symbol,normal,700" not found. Substituting with "Symbol,normal,400". Jul 25, 2023 1:15:13 PM org.apache.fop.events.LoggingEventListener processEvent WARNING: Font "ZapfDingbats,normal,700" not found. Substituting with "ZapfDingbats,normal,400". INFO: Rendered page #1. INFO: Rendered page #2. INFO: Rendered page #3
解决方案
1. 修复SVG文本的属性错误
原SVG代码中错误地将填充样式写在font-style属性里,这不符合SVG规范,同时未明确指定字体族。修改后的代码如下:
<xsl:template name="Draft"> <fo:block-container z-index="-1" position="absolute" right="-20mm"> <fo:block> <fo:instream-foreign-object> <svg:svg xmlns:svg="http://www.w3.org/2000/svg" height="157mm" width="190mm"> <svg:text x="140" y="520" transform="rotate(-46.5,50,350)" textLength="125mm" font-family="Arial, sans-serif" font-size="50mm" lengthAdjust="spacingAndGlyphs" fill="rgb(0,0,0)" fill-opacity="0.3"> DRAFT </svg:text> </svg:svg> </fo:instream-foreign-object> </fo:block> </fo:block-container> </xsl:template>
2. 修复服务器2的字体环境问题
错误栈显示Batik在Headless环境下获取系统字体失败,可通过以下方式解决:
- 安装基础字体包,比如
fontconfig、dejavu-fonts,提供通用 fallback 字体 - 启动Java程序时添加Headless参数:
java -Djava.awt.headless=true ... - 在FOP配置文件
fop.xconf中明确指定字体映射,避免依赖系统自动检测:<fonts> <font kerning="yes" embed-url="file:///path/to/arial.ttf"> <font-triplet name="Arial" style="normal" weight="normal"/> </font> <font kerning="yes" embed-url="file:///path/to/arialbd.ttf"> <font-triplet name="Arial" style="normal" weight="bold"/> </font> </fonts>
3. 替换为纯FO实现(可选)
如果SVG字体问题难以解决,可直接用FO文本块实现水印,无需依赖Batik:
<xsl:template name="Draft"> <fo:block-container z-index="-1" position="absolute" left="0" top="0" width="100%" height="100%" text-align="center"> <fo:block font-family="Arial, sans-serif" font-size="50mm" color="black" opacity="0.3" writing-mode="rl" rotation="45"> DRAFT </fo:block> </fo:block-container> </xsl:template>
内容的提问来源于stack exchange,提问作者Rito Sarkar
相关产品推荐
相关产品推荐

