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)
Link the font with the font_manager
API¶
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!