繁体   English   中英

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

[英]How to install cursive fonts for matplotlib: Font family ['cursive'] not found

When trying to run a script (given below in the minimal working example) on Ubuntu 20.04 that uses the cursive fonts in matplotlib I am getting the matplotlib warnings:

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

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

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

如何以编程方式在 Ubuntu 上找到并安装这些 fonts? 我知道我可以在互联网上寻找免费版本,但如果我想在 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'"

什么都不返回。

问题

如何以编程方式查找和安装 matplotlib 所需的草书matplotlib (在 Ubuntu 20.04 上)?

相关链接

As it seems there is no clear way to get these fonts from any Ubuntu PPA, what can be done instead is to just directly download Felipa , one of the cursive font family fonts, from Google Fonts. 这就是maptlotlib团队在mpl-docker docker testing Docker image中所做的。

所以对于我本地机器上的编程解决方案,我能做的就是

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

虽然不是必需的,但我还创建了一个符号链接,指向我的 fonts 的 rest 用于簿记的位置

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

当然,虽然这是程序化的,但如果您在本地机器上并且具有交互功能,那么访问Felipa 的 Google Fonts 页面可能会更好/更容易,下载字体系列 zip 文件并在本地解压缩,然后打开带有Ubuntu 字体管理器Felipa-Regular.ttf Regular.ttf 并让它为您安装。

为了给出这个工作的可重现示例,我将原始 Dockerfile 编辑为wget Felipa,如上所述,然后还创建一个非 root 用户“docker”,以使容器默认以非 root 身份运行并避免出现问题使用--user 1000:1000运行时拥有一个HOME -less 用户。 有一些方法可以使这个 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 制作这个family_cursive.png

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM