Java绘制字符串:每次生成新Font还是使用预生成字体集合?
字体大小适配方案的资源消耗疑问
我实现了一个基于java.awt.Font的字符串绘制字体大小决策方法,字体大小由字符串长度和目标高度决定——通过do-while循环逐步减小字体大小,直到字符串高度适配目标值。
原实现方法
private void decideOnFontSize(String text) { int fontSize = 72; do { font = new Font("Arial", Font.PLAIN, fontSize); // 计算文本高度等逻辑... fontSize -= 2; } while (textHeight >= targetHeight); }
这个方法属于公共API服务,可能被频繁调用,每次循环都实例化新Font对象看起来会浪费资源。因此我设计了另一种方案:通过工具类预定义并缓存字体集合。
优化方案:预定义字体缓存工具类
public class FontsUtil { private static Map<Integer, Font> fonts = new HashMap<>(); public static final Integer MAX_FONT_SIZE = 72; public static final Integer MIN_FONT_SIZE = 10; static { String fontName = "Arial"; for(int fontSize = MAX_FONT_SIZE; fontSize >= MIN_FONT_SIZE; fontSize -= 2) { fonts.put(fontSize, new Font(fontName, Font.PLAIN, fontSize)); } } public static Font getFontBySize(Integer fontSize) { return fonts.get(fontSize); } }
修改后的字体大小决策方法
private void decideOnFontSize(String text) { int fontSize = FontsUtil.MAX_FONT_SIZE; do { font = FontsUtil.getFontBySize(fontSize); // 计算文本高度等逻辑... fontSize -= 2; } while (textHeight >= targetHeight); }
补充说明:实际业务逻辑
由于需要同时适配目标宽度和高度,实际会通过LineBreakMeasurer创建TextLayout对象,完整的do-while循环代码如下:
List<TextLayout> lines; int fontSize = font.getSize(); int textHeight; do { font = FontsUtil.getFontBySize(fontSize); g2d.setFont(font); lines = splitStringIntoPiecesToFitTargetWidth(text, targetWidth, g2d); textHeight = getTextHeight(lines); fontSize -= 2; } while (textHeight >= targetHeight);
注:font为实例变量
字符串拆分方法splitStringIntoPiecesToFitTargetWidth实现如下:
private List<TextLayout> splitStringIntoPiecesToFitTargetWidth(String string, int width, Graphics2D g2d) { List<TextLayout> lines = new ArrayList<>(); AttributedString attributedString = new AttributedString(string); attributedString.addAttribute(TextAttribute.FONT, font); LineBreakMeasurer lineBreakMeasurer = new LineBreakMeasurer(attributedString.getIterator(), g2d.getFontRenderContext()); while (lineBreakMeasurer.getPosition() < string.length()) { lines.add(lineBreakMeasurer.nextLayout(width)); } return lines; }
我认为第二种预缓存字体的方案理论上资源消耗更少,但不确定实际是否真的如此?
内容的提问来源于stack exchange,提问作者Alexander Novikov
相关产品推荐
相关产品推荐

