Matplotlib PDF 导出使用错误字体
我想为演示生成高质量的图表。我正在使用 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
字体或 fantasy
或 <代码>等宽字体。但所有无衬线字体似乎都默认为 Helvetica。
I want to generate high-quality diagrams for a presentation. I’m using Python’s matplotlib to generate the graphics. Unfortunately, the PDF export seems to ignore my font settings.
I tried setting the font both by passing a FontProperties
object to the text drawing functions and by setting the option globally. For the record, here is a MWE to reproduce the problem:
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)
In both cases, the produced output is identical and uses Helvetica (and yes, I do have both fonts installed).
Just to be sure, the following doesn’t help either:
matplotlib.rc('font', family = 'Gill Sans')
Finally, if I replace the backend, instead using the native viewer:
matplotlib.use('MacOSX')
I do get the correct font displayed – but only in the viewer GUI. The PDF output is once again wrong.
To be sure – I can set other fonts – but only other classes of font families: I can set serif
fonts or fantasy
or monospace
. But all sans-serif fonts seem to default to Helvetica.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上,@Jouni 是正确的答案,但由于我在使其工作时仍然遇到一些麻烦,这是我的最终解决方案:
请注意,必须使用
fontproperties
键显式设置字体。显然,fname
属性没有rc
设置(至少我没有找到它)。此处并不严格需要在
font
实例化中提供family
键,它会被 PDF 后端忽略。此代码仅适用于
cairo
后端。使用MacOSX
不起作用。Basically, @Jouni’s is the right answer but since I still had some trouble getting it to work, here’s my final solution:
Notice that the font has to be set explicitly using the
fontproperties
key. Apparently, there’s norc
setting for thefname
property (at least I didn’t find it).Giving a
family
key in the instantiation offont
isn’t strictly necessary here, it will be ignored by the PDF backend.This code works with the
cairo
backend only. UsingMacOSX
won’t work.“family”参数和相应的rc参数
并不是用来指定字体的名称,实际上可以这样使用。有一个(可以说是巴洛克式的)类似 CSS 的字体选择系统,可以帮助相同的脚本在不同的计算机上工作,选择最接近的可用字体。通常推荐使用例如 Gill Sans 的方法是将其添加到 rc 参数 font.sans-serif 值的前面(请参阅 示例 rc 文件),然后将 font.family 设置为 sans-serif。如果字体管理器出于某种不明原因决定 Gill Sans 与您的规范不最接近,这可能会很烦人。绕过字体选择逻辑的一种方法是使用
FontProperties(fname='/path/to/font.ttf')
(文档字符串)。就您而言,我怀疑MacOSX后端通过操作系统的机制使用字体,因此自动支持各种字体,但pdf后端有自己的字体支持代码,不支持您的Gill Sans版本。
The "family" argument and the corresponding rc parameter
are not meant to specify the name of the fontcan actually be used this way. There's an (arguably baroque) CSS-like font selection system that helps the same script work on different computers, selecting the closest font available. The usually recommended way to use e.g. Gill Sans is to add it to the front of the value of the rc parameter font.sans-serif (see sample rc file), and then set font.family to sans-serif.This can be annoying if the font manager decides for some obscure reason that Gill Sans is not the closest match to your specification. A way to bypass the font selection logic is to use
FontProperties(fname='/path/to/font.ttf')
(docstring).In your case, I suspect that the MacOSX backend uses fonts via the operating system's mechanisms and so automatically supports all kinds of fonts, but the pdf backend has its own font support code that doesn't support your version of Gill Sans.
如果您来到这里是为了非开罗后端,这是对上述答案的补充。
matplotlib 的 pdf 后端尚不支持 true type 字体集合(另存为 .ttc 文件)。请参阅此问题。
当前建议的解决方法是从 .ttc 文件中提取感兴趣的字体并将其另存为 .ttf 文件。然后按照 Konrad Rudolph 描述的方式使用该字体。
您可以使用 python-package fonttools 来实现此目的:
据我所知,它不是通过将此新
.ttf
文件的路径传递给 rc.如果您真的很绝望,您可以尝试将.ttc
中的所有字体提取到单独的.ttf
文件中,卸载.ttc
并安装单独的ttf
。要将提取的字体与.ttc
中的原始字体并排,您需要使用 FontForge。不过我还没有测试过这个。This is an addition to the answers above if you came here for a non-cairo backend.
The pdf-backend of matplotlib does not yet support true type font collections (saved as .ttc files). See this issue.
The currently suggested workaround is to extract the font-of-interest from a .ttc file and save it as a .ttf file. And then use that font in the way described by Konrad Rudolph.
You can use the python-package fonttools to achieve this:
As far as I can see, it is not possible to make this setting "global" by passing the path to this new
.ttf
file to the rc. If you are really desperate, you could try to extract all fonts from a.ttc
into separate.ttf
files, uninstall the.ttc
and install thettf
s separately. To have the extracted font side-by-side with the original font from the.ttc
, you need to change the font name with tools like FontForge. I haven't tested this, though.检查您是否使用 LaTeX 渲染文本,即
text.usetex
是否设置为True
。由于 LaTeX 渲染仅支持几种字体,因此它很大程度上会忽略/覆盖您的其他字体设置。这可能就是原因。Check if you are rendering the text with LaTeX, i.e., if
text.usetex
is set toTrue
. Because LaTeX rendering only supports a few fonts, it largely ignores/overwrites your other fonts settings. This might be the cause.