Matplotlib PDF 导出使用错误字体

发布于 2024-09-01 01:00:14 字数 1040 浏览 4 评论 0原文

我想为演示生成高质量的图表。我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尐偏执 2024-09-08 01:00:15

基本上,@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 键显式设置字体。显然,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:

#!/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')

Notice that the font has to be set explicitly using the fontproperties key. Apparently, there’s no rc setting for the fname property (at least I didn’t find it).

Giving a family key in the instantiation of font isn’t strictly necessary here, it will be ignored by the PDF backend.

This code works with the cairo backend only. Using MacOSX won’t work.

孤者何惧 2024-09-08 01:00:15

“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 font can 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.

任性一次 2024-09-08 01:00:15

如果您来到这里是为了非开罗后端,这是对上述答案的补充。

matplotlib 的 pdf 后端尚不支持 true type 字体集合(另存为 .ttc 文件)。请参阅此问题

当前建议的解决方法是从 .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。不过我还没有测试过这个。

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:

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

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 the ttfs 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.

笑红尘 2024-09-08 01:00:15

检查您是否使用 LaTeX 渲染文本,即 text.usetex 是否设置为 True。由于 LaTeX 渲染仅支持几种字体,因此它很大程度上会忽略/覆盖您的其他字体设置。这可能就是原因。

Check if you are rendering the text with LaTeX, i.e., if text.usetex is set to True. Because LaTeX rendering only supports a few fonts, it largely ignores/overwrites your other fonts settings. This might be the cause.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文