问题描述

使用 Graphics2D 画图的时候出现乱码情况,本地测试是没问题,放在linux服务器就出现乱码

DEMO代码

File file = new File("/home/war/test.png");
        BufferedImage bi = new BufferedImage(400, 200, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = (Graphics2D) bi.getGraphics();
        g2.setBackground(Color.WHITE);
        g2.clearRect(0, 0, 400, 200);
        g2.setColor(Color.BLACK);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.drawString("为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特殊不?@¥¥¥ 为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特 ", 0, 10);
        g2.dispose();
        ImageIO.write(bi, "PNG", file);

linux 上面运行结果

java graphviz解析dot文件_core graphics

问题排查

源码

java graphviz解析dot文件_linux_02

首先Graphics2D 继承了 Graphics 类,可以看到该类使用的是模板方法模式

java graphviz解析dot文件_Java_03

java graphviz解析dot文件_core graphics_04


接着点击去

java graphviz解析dot文件_linux_05


再点

java graphviz解析dot文件_core graphics_06


这里判断是否设置字体,为空则为默认字体

java graphviz解析dot文件_java_07


java graphviz解析dot文件_java_08

java graphviz解析dot文件_core graphics_09

网上冲浪了一下,发现原来JVM创建Font的时候会使用FontManagerFactory获取FontManager,而不同的系统使用的FontManager是不同的!Mac用的是CFontManager,而Linux用的是X11FontManager!

Java 运行时环境支持的 Java 平台所定义的五种字体系列:Serif、SansSerif、Monospaced、Dialog 和 DialogInput。这些逻辑字体不是实际的字体库。此外,由 Java 运行时环境将逻辑字体名称映射到物理字体。映射关系与实现和通常语言环境相关,因此它们提供的外观和规格各不相同。通常,为了覆盖庞大的字符范围,每种逻辑字体名称都映射到几种物理字体。

rt.jar

java graphviz解析dot文件_Image_10

解决方法

原因:Linux环境加载字体问题
解决:

一、更改代码,指定字体

File file = new File("/home/war/test.png");
        Font font = new Font("Serif", Font.PLAIN, 10);//指定字体
        BufferedImage bi = new BufferedImage(400, 200, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = (Graphics2D) bi.getGraphics();
        g2.setBackground(Color.WHITE);
        g2.clearRect(0, 0, 400, 200);
        g2.setFont(font);
        g2.setColor(Color.BLACK);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.drawString("为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特殊不?@¥¥¥ 为什么没有(ꐚꌒꑿꆺ)(ꐚꌒꑿꆺ)这名字特 ", 0, 10);
        g2.dispose();
        ImageIO.write(bi, "PNG", file);

二、Linux安装字体

C:\Windows\Fonts 这个目录下的文件可以全部打包上传,按照以下方式照样是可以使用的

java graphviz解析dot文件_core graphics_11


Linux 命令

cd /usr/share/fonts #进入到该目录
mkdir myfonts #创建文件
cd myfonts #进入到该目录

#建立字体索引信息,更新字体缓存
mkfontscale 
mkfontdir
fc-cache

三、柳暗花开

重启应用,再次生成图片

java graphviz解析dot文件_java_12