【问题标题】:How to install cursive fonts for matplotlib: Font family ['cursive'] not found如何为 matplotlib 安装草书字体:找不到字体系列 ['cursive']
【发布时间】:2021-01-10 00:45:08
【问题描述】:

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

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

这告诉我我没有matplotlib 想要用于the cursive font family 的任何草书字体。 当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'"

什么都不返回。

问题

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

相关链接

【问题讨论】:

    标签: python matplotlib fonts


    【解决方案1】:

    由于似乎没有明确的方法可以从任何 Ubuntu PPA 获取这些字体,因此可以直接从 Google Fonts 下载 Felipa,这是一种草书字体系列字体。这就是maptlotlib 团队在mpl-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
    

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

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

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

    为了给出这个工作的可重现示例,我已将原始 Dockerfile 编辑为wgetFelipa,如上所述,然后还创建了一个非 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制作这个情节:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 2016-10-21
      • 2017-06-25
      • 2014-11-23
      相关资源
      最近更新 更多