Skip to article frontmatterSkip to article content

Load and plot a remote font with Matplotlib

As part of my sphinx-social-previews prototype, I wanted to be able to use the Roboto Font from Google in image previews. However, Roboto is often not loaded on your local filesystem, so it took some digging to figure out how to make it possible to load via Matplotlib’s text plotting functionality.

Here’s the solution that finally worked for me, inspired from this Tweet with a similar implementation from the dmol book.

Below I’ll use the Fira Code font from Mozilla but you could do this with any open font that you have the .ttf file for.

Create a temporary folder and download the font file

I’ll show how to do this with a local folder, so it’ll re-download each time you run the code. Alternatively you could download the font locally and just register the path instead of downloading it:

First, download the .ttf of the font locally via urlretrieve. For example, the Fira Code font from Mozilla is located at this URL. To download it locally into a temporary folder using the tempfile.mkdtemp function, run this code:

import tempfile
from pathlib import Path
import urllib
from rich import print

# Create a temporary directory for the font file
path = Path(tempfile.mkdtemp())

# URL and downloaded path of the font
url_font = "https://github.com/google/fonts/raw/main/ofl/firacode/FiraCode%5Bwght%5D.ttf"
path_font = path / "Fira-Code.ttf"


# Download the font to our temporary directory
urllib.request.urlretrieve(url_font, path_font)

Now that the file is loaded, we can link it using Matplotlib’s font_manager API. This allows you to register fonts that Matplotlib knows how to use.

from matplotlib import font_manager

# Create a Matplotlib Font object from our `.ttf` file
font = font_manager.FontEntry(fname=str(path_font), name="Fira-Downloaded")

# Register this object with Matplotlib's ttf list
font_manager.fontManager.ttflist.append(font)
# Print the last few items to see what they look like
print(font_manager.fontManager.ttflist[-3:])

Make a plot with this font

Now that we’ve registered the font, we can plot it with ax.text. To do so, use the plt.rc_context context manager to temporarily update our default font:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 3, figsize=(9, 5))

# This will now render as a `Roboto Flex` font
axs[0].text(.1, .5, "The default font!", fontdict={"fontsize": 15})
axs[1].text(.1, .5, "A Matplotlib font", fontdict={"fontsize": 15, "family": "cmmi10"})
axs[2].text(.1, .5, "The Fira Code font!", fontdict={"fontsize": 15, "family": font.name})

for ax in axs:
  ax.set_axis_off()

And that’s it!