1. 程式人生 > >解決jasperreports中自定義字型在linux沒有生效和不加粗問題

解決jasperreports中自定義字型在linux沒有生效和不加粗問題

我的jasper的maven配置

<dependency>
	<groupId>net.sf.jasperreports</groupId>
	<artifactId>jasperreports</artifactId>
	<version>6.3.0</version>
</dependency>
<dependency>
	<groupId>net.sf.jasperreports</groupId>
	<artifactId>jasperreports-fonts</artifactId>
	<version>5.6.1</version>
</dependency>

1:我們開發報表有些時候官方預設的字型包不能滿足我們的需要,所以我們開始自定義字型,於是在網上查了很多資料,按照網上的方式自定義的字型檔案放到jasperreports-fonts-5.6.1.jar的net\sf\jasperreports\fonts\dejavu目錄下,字型檔案要求必須ttf格式,然後在net\sf\jasperreports\fonts\fonts.xml檔案中增加字型配置,我的配置如下:

<fontFamily name="DejaVu 宋體">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
	</fontFamily>
	
<fontFamily name="DejaVu 仿宋_GB2312">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
</fontFamily>

2:將修改後的jasperreports-fonts-5.6.1.jar包檔案放到專案的lib下,最後到linux環境測試生成PDF的效果,有沒有使用到自己定義的宋體字型,但是現實總是如此,結果給了我一個很響亮的大嘴巴子,根本沒有任何效果,於是我百思不得其解,又開始了漫長的百度和google里程,講道理啥結果也沒找過,但是還是有些文章給了我一定的啟發,於是我在想既然配置了字型,那麼jasperreports在生成時肯定會解析字型檔案,我一步一步去遠端debug除錯,最後定位到一段程式碼,跟蹤到FontUtil的getFontInfo方法,發現有個變數是用來儲存解析fonts.xml的字型配置的,程式碼如下:

public FontInfo getFontInfo(String name, Locale locale) {
        FontInfo awtFamilyMatchFontInfo = null;
        //families實際解析fonts.xml檔案的結果
        List<FontFamily> families = this.jasperReportsContext.getExtensions(FontFamily.class);
        Iterator itf = families.iterator();

        while(true) {
            FontFamily family;
            do {
                if(!itf.hasNext()) {
                    return awtFamilyMatchFontInfo;
                }

                family = (FontFamily)itf.next();
            } while(locale != null && !family.supportsLocale(locale));

            if(name.equals(family.getName())) {
                return new FontInfo(family, (FontFace)null, 0);
            }

            FontFace face = family.getNormalFace();
            if(face != null) {
                if(name.equals(face.getName())) {
                    return new FontInfo(family, face, 0);
                }

                if(awtFamilyMatchFontInfo == null && name.equals(face.getFont().getFamily())) {
                    awtFamilyMatchFontInfo = new FontInfo(family, face, 0);
                }
            }

            face = family.getBoldFace();
            if(face != null) {
                if(name.equals(face.getName())) {
                    return new FontInfo(family, face, 1);
                }

                if(awtFamilyMatchFontInfo == null && name.equals(face.getFont().getFamily())) {
                    awtFamilyMatchFontInfo = new FontInfo(family, face, 1);
                }
            }

            face = family.getItalicFace();
            if(face != null) {
                if(name.equals(face.getName())) {
                    return new FontInfo(family, face, 2);
                }

                if(awtFamilyMatchFontInfo == null && name.equals(face.getFont().getFamily())) {
                    awtFamilyMatchFontInfo = new FontInfo(family, face, 2);
                }
            }

            face = family.getBoldItalicFace();
            if(face != null) {
                if(name.equals(face.getName())) {
                    return new FontInfo(family, face, 3);
                }

                if(awtFamilyMatchFontInfo == null && name.equals(face.getFont().getFamily())) {
                    awtFamilyMatchFontInfo = new FontInfo(family, face, 3);
                }
            }
        }
    }

3:好了找到解析字型檔案的位置了,於是我就像到底有沒解析到配置的字型呢,於是debug看了下這個變數的值,結果是沒有的,只有三個值也就是fonts.xml預設的其中三個配置,配置如下:

<fontFamily name="SansSerif">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
		</exportFonts>
	</fontFamily>
<fontFamily name="Serif">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export>
		</exportFonts>
</fontFamily>
<fontFamily name="Monospaced">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
		</exportFonts>
</fontFamily>

但是我在windows環境看了下,解析的結果卻是fonts.xml所有的配置,結果完全不一致,這就很苦惱了,最後對比下解析的配置差異,發現linux環境只會解析我上面發的那三個配置資訊,而不會解析這樣的配置:

<fontFamily name="DejaVu 宋體">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
</fontFamily>
	
<fontFamily name="DejaVu 仿宋_GB2312">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
</fontFamily>

好了原因找到了,我就嘗試著去按照linux環境解析的配置xml格式配置了一下,最終配置如下:

<?xml version="1.0" encoding="UTF-8"?>

<fontFamilies>

	<fontFamily name="DejaVu Sans">
		<normal>net/sf/jasperreports/fonts/dejavu/DejaVuSans.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Bold.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-Oblique.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSans-BoldOblique.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
		</exportFonts>
		<!--
		<locales>
			<locale>en_US</locale>
			<locale>de_DE</locale>
		</locales>
		-->
	</fontFamily>

	<fontFamily name="DejaVu Serif">
		<normal>net/sf/jasperreports/fonts/dejavu/DejaVuSerif.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Bold.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-Italic.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSerif-BoldItalic.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export>
		</exportFonts>
	</fontFamily>

	<fontFamily name="DejaVu Sans Mono">
		<normal>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Bold.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-Oblique.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/DejaVuSansMono-BoldOblique.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
		</exportFonts>
	</fontFamily>
	
	<!--
		Mapping Java logical fonts, for the sake of HTML export only.
	-->
	
	<fontFamily name="SansSerif">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans', Arial, Helvetica, sans-serif</export>
		</exportFonts>
	</fontFamily>
	<fontFamily name="Serif">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Serif', 'Times New Roman', Times, serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Serif', 'Times New Roman', Times, serif</export>
		</exportFonts>
	</fontFamily>
	<fontFamily name="Monospaced">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu Sans Mono', 'Courier New', Courier, monospace</export>
		</exportFonts>
	</fontFamily>
    <!--自定義字型配置開始-->
	<fontFamily name="宋體">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu 宋體', Arial, Helvetica, sans-serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu 宋體', Arial, Helvetica, sans-serif</export>
		</exportFonts>
	</fontFamily>
	<fontFamily name="仿宋_GB2312">
		<exportFonts>
			<export key="net.sf.jasperreports.html">'DejaVu 仿宋_GB2312', Arial, Helvetica, sans-serif</export>
			<export key="net.sf.jasperreports.xhtml">'DejaVu 仿宋_GB2312', Arial, Helvetica, sans-serif</export>
		</exportFonts>
	</fontFamily>
	
	<fontFamily name="DejaVu 宋體">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
	</fontFamily>
	
	<fontFamily name="DejaVu 仿宋_GB2312">
		<normal>net/sf/jasperreports/fonts/dejavu/simsun.ttf</normal>
		<bold>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</bold>
		<italic>net/sf/jasperreports/fonts/dejavu/simsun.ttf</italic>
		<boldItalic>net/sf/jasperreports/fonts/dejavu/simsunbd.ttf</boldItalic>
		<pdfEncoding>Identity-H</pdfEncoding>
		<pdfEmbedded>true</pdfEmbedded>
		<exportFonts>
			<export key="net.sf.jasperreports.html">'宋體','simsun'</export>
			<export key="net.sf.jasperreports.xhtml">'宋體','simsunbd'</export>
		</exportFonts>
	</fontFamily>
   <!--自定義字型配置結束-->
</fontFamilies>

4:最後將修改後的fonts.xml放到jasperreports-fonts-5.6.1.jar包中,丟到linux環境測試,結果很出乎意料字型解析到,加粗也沒問題了,至此解決了自定義字型加粗和字型未生效問題

5:最後宣告伺服器JDK最好使用jdk1.7.45~1.7.80版本不要使用linux自帶的JDK版本會存在一些問題,比如說不正常換行問題。