每天进步一点点:解决Windows下Graphviz输出图像中文显示的问题

前一篇文章中,给大家介绍了Graphviz这个强大的工具,不过学习过程中还是遇到一些麻烦,比如说输出PNG格式图像时,中文显示为乱码。

image.png
(图源 :pixabay)

这篇文章着手解决我们之前遇到的这个问题,毕竟作为一个讲中文的中国人,作图中肯定经常用到中文呀。

问题描述

以之前的Hello World示例为例,我们对其进行修改,将:

digraph G {Hello->World}

修改为:

digraph G {"你好"->"世界"}

将文件保存为hello.dotUTF-8 No-BOM)并使用如下指令生成PNG格式的图像:

dot -Tpng hello.dot -o hello.png

生成的图像是这个样子:

image.png

咦,中文显示成了什么鬼样子,呜呜呜。

解决方案一:使用SVG

经过一番搜索以及探索以后,我发现了上述问题的一个解决方案,那就是使用SVG格式生成图像。

亦即相关的命令修改为:

dot -Tsvg hello.dot -o hello.svg

运行上述指令,我们会得到hello.svg文件,使用浏览器等支持SVG格式图像的工具打开后,我们会得到如下图像:
image.png

哇,中文版的Hello World(你好,世界),总算可以正确运行啦。

但是问题是,SVG图像格式我并不常用,在HIVE上插图之类的操作也很不方便。

而生成SVG之所以可以正确地显示中文,其实相当于把展现中文的功能留给了SVG浏览器。所以,我们想用BMP、JPG甚至PDF格式作为替代,它们通通不工作。

解决方案二:使用fontname

之前的生成SVG虽然能解决问题,但是还是不太方便,确切地说,不太优雅。那么有没有一种更好的方式呢?

答案是有的,那就是为图中各个元素设置fontname属性,并指定系统中被支持的中文字体。

比如将文件修改为:

digraph G {
    node [fontname="FangSong"]
    "你好"->"世界"
}

再使用如下指令生成PNG图像:

dot -Tpng hello.dot -o hello.png

然后我们就会顺利地生成hello.png啦:
image.png

从fontname的文档中,我们得知,fontname可以分别地作用于图表、节点、集群、边缘,比如上边的例子就是作用于节点(node)。

假定我们有这样一个文件:

digraph G {
    fontname="FangSong"
    label="世界你好 by @oflyhigh"
    "你好"->"世界"
}

那么生成的图像会是什么样子呢?

当当当当,谜题揭晓:
image.png

之所以有些中文正确显示,有些显示成乱码,就是因为我们指定了图(digraph)的fontname属性,而并没有指定节点(node)的fontname属性。

所以想让中文都正确地显示,代码应该是这个样子:

digraph G {
    fontname="FangSong"
    label="世界你好 by @oflyhigh"

    node [fontname="FangSong"]
    "你好"->"世界"
}

输出如下:

image.png

补充说明:fontname的设置

经过我们的探索,我们得出结论,通过对相应的对象设置fontname,可以实现正确的中文显示,比如我们之前设置的fontname="FangSong"

那么问题来了,我们怎么知道我们系统中支持哪些字体,而且这些字体的名字又是什么呢?

经过我不懈探索,发现了两种方法(欢迎补充)。

方法一:C:\Windows\Fonts 目录

1697772927454.png

打开这个目录后,我们就可以看到一大堆字体文件,以及相应的名字。

方法二:settings->Fonts

打开Windows的设置界面,搜索Fonts,就会到达如下界面:
image.png

然后就可以在里边挑选自己喜欢的字体啦。

以下示例digraph字体选择为:Microsoft YaHei,node字体设置为:FangSong。你能看出来两者的区别嘛?
image.png

相应代码如下:

digraph G {
    fontname="Microsoft YaHei"
    label="世界你好 by @oflyhigh"

    node [fontname="FangSong"]
    "你好"->"世界"
}

相关链接

H2
H3
H4
Upload from PC
Video gallery
3 columns
2 columns
1 column
10 Comments