如何为matplotlib安装草书字体:找不到字体系列['cursive']

3

在尝试在Ubuntu 20.04上运行下面的最小工作示例脚本时,使用matplotlib中的草书字体会收到matplotlib警告:

findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.

这告诉我,我没有任何 matplotlib 想要用于 草书字体族 的草书字体。 在下面的最小失败示例中似乎得到了证实,当 matplotlib 的字体管理器或 fc-list 找不到任何草书字体时。

# on my local machine
$ fc-list : family | grep -i "chancery\|textile\|sand\|script\|felipa\|cursive"
URW Chancery L
Free Chancery

我该如何通过编程的方式在Ubuntu上找到并安装这些字体?我知道我可以在互联网上寻找免费版本,但如果我想将它们安装到Docker镜像中,该如何通过apt-get这样的CLI API进行安装?

最小失败示例

对于以下Dockerfile

FROM ubuntu:20.04

RUN apt-get update -y && \
    apt-get install -y \
        fontconfig \
        fonts-dejavu \
        fonts-freefont-ttf \
        python3 \
        python3-dev \
        python3-pip \
        python3-venv \
        vim && \
        apt-get -y autoclean && \
        apt-get -y autoremove && \
        rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel && \
    python3 -m pip install --no-cache-dir "matplotlib~=3.3" && \
    python3 -m pip list && \
    python3 -c "import matplotlib.pyplot" # generate font list cache

ENV MPLCONFIGDIR /tmp/.config # make writeable to non-root user

WORKDIR /code

COPY example.py example.py

使用example.py

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager


def make_plot(font_family):
    fig, ax = plt.subplots()
    x = np.linspace(0, 10, 101)
    y = np.square(x)
    ax.plot(x, y)
    ax.semilogy()

    ax.set_xlabel("$x$")
    ax.set_ylabel("$x^2$")
    ax.set_title(f"Default matplotlib settings for {font_family} font family")

    return fig, ax


def main():

    image_types = ["pdf", "png"]
    for font_family in ["sans-serif", "serif", "cursive"]:
        plt.rcParams.update({"font.family": font_family})
        fig, ax = make_plot(font_family=font_family)

        for type in image_types:
            fig.savefig(f"family_{font_family}.{type}")

    cursive_family = matplotlib.rcParams["font.cursive"]
    print(f"\nmatplotlib cursive family: {cursive_family}")
    tff_fonts = sorted(
        set([font.name for font in matplotlib.font_manager.fontManager.ttflist])
    )
    afm_fonts = sorted(
        set([font.name for font in matplotlib.font_manager.fontManager.afmlist])
    )
    all_fonts = sorted(set([*tff_fonts, *afm_fonts]))
    print(f"\ntff fonts: {tff_fonts}")
    print(f"\nafm fonts: {afm_fonts}")
    print(f"\nall fonts: {all_fonts}")
    found_cursive_fonts = [font for font in cursive_family if font in all_fonts]
    print(f"\nfound cursive fonts: {found_cursive_fonts}")


if __name__ == "__main__":
    main()

如果使用了构建工具

docker build . \
--pull \
-f Dockerfile \
-t matplotlib-cursive-fonts-question:debug-local

然后运行

$ docker run --rm --user 1000:1000 -v $PWD:$PWD -w $PWD matplotlib-cursive-fonts-question:debug-local /bin/bash -c "python3 /code/example.py"
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.

matplotlib cursive family: ['Apple Chancery', 'Textile', 'Zapf Chancery', 'Sand', 'Script MT', 'Felipa', 'cursive']

tff fonts: ['DejaVu Math TeX Gyre', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif Display', 'FreeMono', 'FreeSans', 'FreeSerif', 'STIXGeneral', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

afm fonts: ['Computer Modern', 'Courier', 'Helvetica', 'ITC Avant Garde Gothic', 'ITC Bookman', 'ITC Zapf Chancery', 'ITC Zapf Dingbats', 'New Century Schoolbook', 'Palatino', 'Symbol', 'Times', 'Utopia', 'ZapfDingbats']

all fonts: ['Computer Modern', 'Courier', 'DejaVu Math TeX Gyre', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif Display', 'FreeMono', 'FreeSans', 'FreeSerif', 'Helvetica', 'ITC Avant Garde Gothic', 'ITC Bookman', 'ITC Zapf Chancery', 'ITC Zapf Dingbats', 'New Century Schoolbook', 'Palatino', 'STIXGeneral', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'Symbol', 'Times', 'Utopia', 'ZapfDingbats', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

found cursive fonts: []

并且

docker run --rm --user 1000:1000 -v $PWD:$PWD -w $PWD matplotlib-cursive-fonts-question:debug-local /bin/bash -c "fc-list : family | grep -i 'chancery\|textile\|sand\|script\|felipa\|cursive'"

不返回任何内容。

问题

如何在Ubuntu 20.04上编程查找并安装matplotlib所需的草书字体?

相关链接

1个回答

1
似乎在Ubuntu PPA中没有明确的方法来获取这些字体,相反可以直接从Google Fonts下载一种草书字体系列字体Felipa。这就是maptlotlib团队在mpl-docker测试Docker镜像中所做的。因此,对于我本地机器上的编程解决方案,我可以这样做:
mkdir -p ~/.local/share/fonts/truetype/felipa
wget --no-clobber https://github.com/google/fonts/blob/master/ofl/felipa/Felipa-Regular.ttf?raw=true -O ~/.local/share/fonts/truetype/felipa/Felipa-Regular.ttf
fc-cache --force --verbose # rebuild font cache for system
rm -rf ~/.cache/matplotlib/* # remove the matplotlib cache to force rebuild

虽然不是必需的,但我也创建了一个符号链接到我的其他字体所在的位置以便于管理。

sudo ln -s "${HOME}/.local/share/fonts/truetype/felipa" /usr/share/fonts/truetype/felipa

当然,如果您在本地机器上拥有交互功能,这是编程的一部分,最好/更容易的方法是直接访问 Felipa 的 Google Fonts 页面,将字体系列 zip 文件下载到本地并提取它,然后使用 Ubuntu 字体管理器 打开 Felipa-Regular.ttf 并让其为您安装。为了提供一个可重现的示例,请编辑原始 Dockerfile 以像上述方式 wget Felipa,并创建一个非根用户“docker”,以使容器默认运行为非根用户并避免在使用 --user 1000:1000 运行时出现没有HOME 的用户问题。有很多方法可以使这个 Dockerfile 更紧凑,但在这个示例中,我选择可读性优先于大小优化。
FROM ubuntu:20.04

RUN apt-get update -y && \
    apt-get install -y \
        fontconfig \
        fonts-dejavu \
        fonts-freefont-ttf \
        python3 \
        python3-dev \
        python3-pip \
        python3-venv \
        vim \
        wget && \
        apt-get -y autoclean && \
        apt-get -y autoremove && \
        rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade --no-cache-dir pip setuptools wheel && \
    python3 -m pip install --no-cache-dir "matplotlib~=3.3" && \
    python3 -m pip list

# Create user "docker"
RUN useradd -m docker && \
    cp /root/.bashrc /home/docker/
ENV HOME /home/docker

# felipa provides a cursive font
RUN mkdir -p "${HOME}/.local/share/fonts/truetype/felipa" && \
    wget --no-clobber "https://github.com/google/fonts/blob/master/ofl/felipa/Felipa-Regular.ttf?raw=true" -O "${HOME}/.local/share/fonts/truetype/felipa/Felipa-Regular.ttf" && \
    ln -s "${HOME}/.local/share/fonts/truetype/felipa" /usr/share/fonts/truetype/felipa && \
    fc-cache --force --verbose

WORKDIR /code

COPY example.py example.py

# give non-root user docker ownership of files
RUN chown -R --from=root docker /home/docker && \
    chown -R --from=root docker /code
USER docker

# Create font list cache and config dir
RUN python3 -c "import matplotlib.pyplot"

重新构建此 Docker 镜像与以前相同,然后允许以下内容无警告或错误运行。
$ docker run --rm -v $PWD:$PWD -w $PWD matplotlib-cursive-fonts-question:debug-local /bin/bash -c "python3 /code/example.py"

matplotlib cursive family: ['Apple Chancery', 'Textile', 'Zapf Chancery', 'Sand', 'Script MT', 'Felipa', 'cursive']

tff fonts: ['DejaVu Math TeX Gyre', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif Display', 'Felipa', 'FreeMono', 'FreeSans', 'FreeSerif', 'STIXGeneral', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

afm fonts: ['Computer Modern', 'Courier', 'Helvetica', 'ITC Avant Garde Gothic', 'ITC Bookman', 'ITC Zapf Chancery', 'ITC Zapf Dingbats', 'New Century Schoolbook', 'Palatino', 'Symbol', 'Times', 'Utopia', 'ZapfDingbats']

all fonts: ['Computer Modern', 'Courier', 'DejaVu Math TeX Gyre', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif Display', 'Felipa', 'FreeMono', 'FreeSans', 'FreeSerif', 'Helvetica', 'ITC Avant Garde Gothic', 'ITC Bookman', 'ITC Zapf Chancery', 'ITC Zapf Dingbats', 'New Century Schoolbook', 'Palatino', 'STIXGeneral', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'Symbol', 'Times', 'Utopia', 'ZapfDingbats', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

found cursive fonts: ['Felipa']

生成这个名为 family_cursive.png 的图表:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接