当字体尤其是宋体,不能从系统中识别到的时候会从jar中加载字体,并且每次访问都生成9个字体的临时文件。
解决办法是:将字体缓存下来,这样只需要加载一次即可,避免了产生大量的字体文件
private static final Map<String, java.awt.Font> FONT_MAP = new HashMap<String, java.awt.Font>(); 用来存储缓存;
/*******************************************************************************
* Copyright 2017 Bstek
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
******************************************************************************/
package com.bstek.ureport.export.pdf.font;
import com.bstek.ureport.exception.ReportComputeException;
import com.bstek.ureport.exception.ReportException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.pdf.BaseFont;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.List;
/**
* @author Jacky.gao
* @since 2014年4月22日
*/
public class FontBuilder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
private static final Map<String, BaseFont> fontMap = new HashMap<String, BaseFont>();
public static final Map<String, String> fontPathMap = new HashMap<String, String>();
private static final Map<String, java.awt.Font> FONT_MAP = new HashMap<String, java.awt.Font>();
private static List<String> systemFontNameList = new ArrayList<String>();
public static Font getFont(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean underLine) {
BaseFont baseFont = fontMap.get(fontName);
Font font = null;
if (baseFont != null) {
font = new Font(baseFont);
} else {
font = FontFactory.getFont(fontName);
}
font.setSize(fontSize);
int fontStyle = Font.NORMAL;
if (fontBold && fontItalic && underLine) {
fontStyle = Font.BOLD | Font.ITALIC | Font.UNDERLINE;
} else if (fontBold) {
if (fontItalic) {
fontStyle = Font.BOLD | Font.ITALIC;
} else if (underLine) {
fontStyle = Font.BOLD | Font.UNDERLINE;
} else {
fontStyle = Font.BOLD;
}
} else if (fontItalic) {
if (underLine) {
fontStyle = Font.ITALIC | Font.UNDERLINE;
} else if (fontBold) {
fontStyle = Font.ITALIC | Font.BOLD;
} else {
fontStyle = Font.ITALIC;
}
} else if (underLine) {
fontStyle = Font.UNDERLINE;
}
font.setStyle(fontStyle);
return font;
}
public static java.awt.Font getAwtFont(String fontName, int fontStyle, float size) {
if (systemFontNameList.contains(fontName)) {
return new java.awt.Font(fontName, fontStyle, new Float(size).intValue());
}
String fontPath = fontPathMap.get(fontName);
if (fontPath == null) {
fontName = "宋体";
fontPath = fontPathMap.get(fontName);
if (fontPath == null) {
return null;
}
}
System.out.println("--------------------------------请求字体---"+fontName);
java.awt.Font font = FONT_MAP.get(fontName);
if (font == null) {
InputStream inputStream = null;
try {
inputStream = applicationContext.getResource(fontPath).getInputStream();
font = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, inputStream);
System.out.println("--------------------------------第一次加载字体---"+fontName);
FONT_MAP.put(fontName, font);
} catch (Exception e) {
throw new ReportException(e);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
return font.deriveFont(fontStyle, size);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
FontBuilder.applicationContext = applicationContext;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = environment.getAvailableFontFamilyNames();
for (String name : fontNames) {
systemFontNameList.add(name);
}
Collection<FontRegister> fontRegisters = applicationContext.getBeansOfType(FontRegister.class).values();
for (FontRegister fontReg : fontRegisters) {
String fontName = fontReg.getFontName();
String fontPath = fontReg.getFontPath();
if (StringUtils.isEmpty(fontPath) || StringUtils.isEmpty(fontName)) {
continue;
}
try {
BaseFont baseFont = getIdentityFont(fontName, fontPath, applicationContext);
if (baseFont == null) {
throw new ReportComputeException("Font " + fontPath + " does not exist");
}
fontMap.put(fontName, baseFont);
} catch (Exception e) {
e.printStackTrace();
throw new ReportComputeException(e);
}
}
}
private BaseFont getIdentityFont(String fontFamily, String fontPath, ApplicationContext applicationContext) throws DocumentException, IOException {
if (!fontPath.startsWith(ApplicationContext.CLASSPATH_URL_PREFIX)) {
fontPath = ApplicationContext.CLASSPATH_URL_PREFIX + fontPath;
}
String fontName = fontPath;
int lastSlashPos = fontPath.lastIndexOf("/");
if (lastSlashPos != -1) {
fontName = fontPath.substring(lastSlashPos + 1, fontPath.length());
}
if (fontName.toLowerCase().endsWith(".ttc")) {
fontName = fontName + ",0";
}
InputStream inputStream = null;
try {
fontPathMap.put(fontFamily, fontPath);
inputStream = applicationContext.getResource(fontPath).getInputStream();
byte[] bytes = IOUtils.toByteArray(inputStream);
BaseFont baseFont = BaseFont.createFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, bytes, null);
baseFont.setSubset(true);
return baseFont;
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
}