前一篇文章中,给大家介绍了Graphviz这个强大的工具,不过学习过程中还是遇到一些麻烦,比如说输出PNG格式图像时,中文显示为乱码。
(图源 :pixabay)
这篇文章着手解决我们之前遇到的这个问题,毕竟作为一个讲中文的中国人,作图中肯定经常用到中文呀。
问题描述
以之前的Hello World示例为例,我们对其进行修改,将:
digraph G {Hello->World}
修改为:
digraph G {"你好"->"世界"}
将文件保存为hello.dot
(UTF-8 No-BOM)并使用如下指令生成PNG格式的图像:
dot -Tpng hello.dot -o hello.png
生成的图像是这个样子:
咦,中文显示成了什么鬼样子,呜呜呜。
解决方案一:使用SVG
经过一番搜索以及探索以后,我发现了上述问题的一个解决方案,那就是使用SVG格式生成图像。
亦即相关的命令修改为:
dot -Tsvg hello.dot -o hello.svg
运行上述指令,我们会得到hello.svg
文件,使用浏览器等支持SVG格式图像的工具打开后,我们会得到如下图像:
哇,中文版的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啦:
从fontname的文档中,我们得知,fontname可以分别地作用于图表、节点、集群、边缘,比如上边的例子就是作用于节点(node)。
假定我们有这样一个文件:
digraph G {
fontname="FangSong"
label="世界你好 by @oflyhigh"
"你好"->"世界"
}
那么生成的图像会是什么样子呢?
当当当当,谜题揭晓:
之所以有些中文正确显示,有些显示成乱码,就是因为我们指定了图(digraph)的fontname属性,而并没有指定节点(node)的fontname属性。
所以想让中文都正确地显示,代码应该是这个样子:
digraph G {
fontname="FangSong"
label="世界你好 by @oflyhigh"
node [fontname="FangSong"]
"你好"->"世界"
}
输出如下:
补充说明:fontname的设置
经过我们的探索,我们得出结论,通过对相应的对象设置fontname,可以实现正确的中文显示,比如我们之前设置的fontname="FangSong"
。
那么问题来了,我们怎么知道我们系统中支持哪些字体,而且这些字体的名字又是什么呢?
经过我不懈探索,发现了两种方法(欢迎补充)。
方法一:C:\Windows\Fonts 目录
打开这个目录后,我们就可以看到一大堆字体文件,以及相应的名字。
方法二:settings->Fonts
打开Windows的设置界面,搜索Fonts,就会到达如下界面:
然后就可以在里边挑选自己喜欢的字体啦。
以下示例digraph字体选择为:Microsoft YaHei,node字体设置为:FangSong。你能看出来两者的区别嘛?
相应代码如下:
digraph G {
fontname="Microsoft YaHei"
label="世界你好 by @oflyhigh"
node [fontname="FangSong"]
"你好"->"世界"
}