我需要使用
lualatex
而不是 pdflatex
生成 matplotlib 绘图。除此之外,我使用 fontspec
来更改文档字体。下面我以此为例,将字体设置为lmroman10-regular.otf
。这会产生一些问题。一是图例中的手柄没有完全居中,并且在右边框之前有一些空白:
生成中间
.pgf
文件的 python 代码如下所示:
import matplotlib
import numpy
from matplotlib import pyplot
x = numpy.linspace(-1, 1)
y = x ** 2
matplotlib.rcParams["figure.figsize"] = (3, 2.5)
matplotlib.rcParams["font.family"] = "serif"
matplotlib.rcParams["font.size"] = 10
matplotlib.rcParams["legend.fontsize"] = 8
matplotlib.rcParams["pgf.texsystem"] = "lualatex"
PREAMBLE = r"""\usepackage{ifluatex}
\ifluatex
\usepackage{fontspec}
\setmainfont{lmroman10-regular.otf}
\fi
"""
matplotlib.rcParams["text.latex.preamble"] = PREAMBLE
matplotlib.rcParams["pgf.preamble"] = PREAMBLE
matplotlib.rcParams["text.usetex"] = True
pyplot.plot(x, y, label="this is the data")
pyplot.legend()
pyplot.xlabel("xlabel")
pyplot.tight_layout()
pyplot.savefig("lualatex_test.pgf")
然后将 .pgf
文件嵌入到乳胶文档中。似乎不可能直接编译为
.pdf
,因为文档字体将不是选定的字体,例如可以通过将字体设置为更不同的字体(如
AntPoltExpd-Italic.otf
)来查看。另请注意,必须在仅限
\ifluatex
的代码周围添加
lualatex
语句,因为
matplotlib
使用
pdflatex
来确定文本片段的尺寸,如下所示。对于这个简单的示例,用于渲染
.tex
的
.pgf
文件可能只是:
\documentclass[11pt]{scrbook}
\usepackage{pgf}
\usepackage{fontspec}
\setmainfont{lmroman10-regular.otf}
\newcommand{\mathdefault}[1]{#1}
\begin{document}
\input{lualatex_test.pgf}
\end{document}
可以使用lualatex <filename>
进行排版,结果如上图所示(没有红色箭头)。我以为我已经找到了原因,但似乎我错过了一些东西。如上所述,matplotlib 通过将文本块实际放置在乳胶模板中并使用
pdflatex
进行编译来计算文本块的尺寸。例如,这发生在主分支上相应的文件中的
matplotlib.texmanager.TexManager
类中。我想我可以这样解决它:
class TexManager:
...
@classmethod
def get_text_width_height_descent(cls, tex, fontsize, renderer=None):
"""Return width, height and descent of the text."""
if tex.strip() == '':
return 0, 0, 0
dvifile = cls.make_dvi(tex, fontsize)
dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:
page, = dvi
# A total height (including the descent) needs to be returned.
w = page.width
# !!!
if tex == "this is the data":
w /= 1.14
print("fixed width")
# !!!
return w, page.height + page.descent, page.descent
据我了解,这应该会欺骗 matplotlib 认为文本短了 1.14 倍(只是猜测,一旦解决方案有效,就应该进行调整)。该代码肯定会被调用,因为会打印“固定宽度”。但差距并不是固定的:
如何解决这个问题? matplotlib 如何计算图例内容的宽度,我可以修补它以说明正确的宽度吗?假设我知道字体大小 8 的宽度误差系数约为 1.14。我可以轻松确定其他字体和字体大小。
matplotlib.rcParams["pgf.rcfonts"] = False
否则,如果我理解正确的话,字体设置将从 rcParams 应用。
这解决了您的示例的间距问题:
.pgf
后端的 文档,其中解释了此参数。