Matplotlib PDF导出使用错误的字体

时间:2010-05-09 11:46:17

标签: python macos matplotlib cairo

我想为演示文稿生成高质量的图表。我正在使用Python的matplotlib来生成图形。不幸的是,PDF导出似乎忽略了我的字体设置。

我尝试通过将FontProperties对象传递给文本绘制函数并全局设置选项来设置字体。为了记录,这里有一个重现问题的MWE:

import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm

data = scipy.arange(5)

for font in ['Helvetica', 'Gill Sans']:
    fig = pylab.figure()
    ax = fig.add_subplot(111)
    ax.bar(data, data)
    ax.set_xticks(data)
    ax.set_xticklabels(data, fontproperties = fm.FontProperties(family = font))
    pylab.savefig('foo-%s.pdf' % font)

在这两种情况下,生成的输出都是相同的并使用Helvetica(是的,我安装了两种字体)。

可以肯定的是,以下内容也无济于事:

matplotlib.rc('font', family = 'Gill Sans')

最后,如果我替换后端,而是使用本机查看器:

matplotlib.use('MacOSX')

显示正确的字体 - 但仅限于查看器GUI。 PDF输出再次出错。

可以肯定 - 我可以设置其他字体 - 但只能设置其他类型的字体系列:我可以设置serif字体或fantasymonospace。但是所有sans-serif字体似乎都默认为Helvetica。

3 个答案:

答案 0 :(得分:8)

基本上,@ Jouni是正确的答案,但由于我仍然遇到一些麻烦,所以这是我的最终解决方案:

#!/usr/bin/env python2.6

import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm

font = fm.FontProperties(
        family = 'Gill Sans', fname = '/Library/Fonts/GillSans.ttc')

data = scipy.arange(5)
fig = pylab.figure()
ax = fig.add_subplot(111)
ax.bar(data, data)
ax.set_yticklabels(ax.get_yticks(), fontproperties = font)
ax.set_xticklabels(ax.get_xticks(), fontproperties = font)
pylab.savefig('foo.pdf')

请注意,必须使用fontproperties键明确设置字体。显然,rc属性没有fname设置(至少我没有找到它)。

family的实例化中给出font密钥在这里并不是绝对必要的,它将被PDF后端忽略。

此代码仅适用于cairo后端。使用MacOSX将无效。

答案 1 :(得分:3)

“family”参数和相应的rc参数并不意味着指定字体的名称实际上可以这种方式使用。有一个(可以说是巴洛克式的)类似CSS的字体选择系统,可以帮助相同的脚本在不同的计算机上工作,选择最接近的字体。通常推荐使用的方法,例如Gill Sans将它添加到rc参数font.sans-serif的值的前面(参见sample rc file),然后将font.family设置为sans-serif。

如果字体管理器因某些模糊的原因决定Gill Sans不是与您的规格最接近的匹配,这可能会很烦人。绕过字体选择逻辑的一种方法是使用FontProperties(fname='/path/to/font.ttf')docstring)。

在您的情况下,我怀疑MacOSX后端通过操作系统的机制使用字体,因此自动支持各种字体,但pdf后端有自己的字体支持代码,不支持您的Gill Sans版本。

答案 2 :(得分:0)

如果您是来这里访问非开罗后端的,这是对以上答案的补充。

matplotlib的pdf后端尚不支持真实类型的字体集合(另存为.ttc文件)。参见this issue

当前建议的解决方法是从.ttc文件中提取感兴趣的字体并将其保存为.ttf文件。然后以Konrad Rudolph所描述的方式使用该字体。

您可以使用python-package fonttools实现此目的:

font = TTFont("/System/Library/Fonts/Helvetica.ttc", fontNumber=0)
font.save("Helvetica-regular.ttf")

据我所知,不可能通过将此新.ttf文件的路径传递到rc来使此设置为“全局”。如果您真的很绝望,则可以尝试将.ttc中的所有字体提取到单独的.ttf文件中,卸载.ttc并分别安装ttf。要使提取的字体与.ttc中的原始字体并排放置,您需要使用FontForge之类的工具来更改字体名称。我还没有测试过。