Note

Go to the endto download the full example code.

Fonts in Matplotlib#

Matplotlib needs fonts to work with its text engine, some of which are shippedalongside the installation. The default font isDejaVu Sans which covers most European writing systems.However, users can configure the default fonts, and provide their own customfonts. SeeCustomizing text properties fordetails andText with non-latin glyphs in particular for glyphs not supported byDejaVu Sans.

Matplotlib also provides an option to offload text rendering to a TeX engine(usetex=True), seeText rendering with LaTeX.

Fonts in PDF and PostScript#

Fonts have a long (and sometimes incompatible) history in computing, leading todifferent platforms supporting different types of fonts. In practice,Matplotlib supports three font specifications (in addition to pdf 'core fonts',which are explained later in the guide):

Types of Fonts#

Type 1 (PDF with usetex)

Type 3 (PDF/PS)

TrueType (PDF) / Type 42 (PS)

Old font types introduced by Adobe.

Newer font type introduced byApple; commonly used today.

Restricted subset ofPostScript, charstringsare in bytecode.

Full PostScript language,allows embedding arbitrarycode.

Includes a virtual machinethat can execute code.

Supports font hinting.

Does not support fonthinting.

Supports font hinting,through the virtual machine.

Subsetted by code inmatplotlib._type1font.

Subsetted via external modulefontTools.

Note

Adobedisabled support for authoring with Type 1 fonts in January 2023.Matplotlib uses Type 1 fonts for compatibility with TeX; when the usetexfeature is used with the PDF backend, Matplotlib reads the fonts used bythe TeX engine, which are usually Type 1.

Matplotlib also provides limited support for OpenType fonts, a newer standarddeveloped jointly by Adobe and Microsoft; such fonts generally contain a muchlarger character set.

Font subsetting#

The PDF and PostScript formats support embedding fonts in files, allowing thedisplay program to correctly render the text, independent of what fonts areinstalled on the viewer's computer and without the need to pre-rasterize the text.This ensures that if the output is zoomed or resized the text does not becomepixelated. However, embedding full fonts in the file can lead to large outputfiles, particularly with fonts with many glyphs such as those that support CJK(Chinese/Japanese/Korean).

To keep the output size reasonable while using vector fonts,Matplotlib embeds only the glyphs that are actually used in the document.This is known as font subsetting.Computing the font subset and writing the reduced font are both complex problems,which Matplotlib solves in most cases by using thefontTools library.

Core Fonts#

In addition to the ability to embed fonts, as part of thePostScript andPDFspecificationthere are 14 Core Fonts that compliant viewers must ensure are available. Ifyou restrict your document to only these fonts you do not have to embed anyfont information in the document but still get vector text.

This is especially helpful to generatereally lightweight documents:

# trigger core fonts for PDF backendplt.rcParams["pdf.use14corefonts"]=True# trigger core fonts for PS backendplt.rcParams["ps.useafm"]=Truechars="AFM ftw!"fig,ax=plt.subplots()ax.text(0.5,0.5,chars)fig.savefig("AFM_PDF.pdf",format="pdf")fig.savefig("AFM_PS.ps",format="ps")

Fonts in SVG#

Text can output to SVG in two ways controlled byrcParams["svg.fonttype"] (default:'path'):

  • as a path ('path') in the SVG

  • as string in the SVG with font styling on the element ('none')

When saving via'path' Matplotlib will compute the path of the glyphs usedas vector paths and write those to the output. The advantage of doing so isthat the SVG will look the same on all computers independent of what fonts areinstalled. However the text will not be editable after the fact.In contrast, saving with'none' will result in smaller files and thetext will appear directly in the markup. However, the appearance may varybased on the SVG viewer and what fonts are available.

Fonts in Agg#

To output text to raster formats via Agg, Matplotlib relies onFreeType. Because the exact rendering of the glyphschanges between FreeType versions we pin to a specific version for our imagecomparison tests.

How Matplotlib selects fonts#

Internally, using a font in Matplotlib is a three step process:

  1. aFontProperties object is created (explicitly or implicitly)

  2. based on theFontProperties object the methods onFontManager are usedto select the closest "best" font Matplotlib is aware of (except for'none' mode of SVG).

  3. the Python proxy for the font object is used by the backend code to renderthe text -- the exact details depend on the backend viafont_manager.get_font.

The algorithm to select the "best" font is a modified version of the algorithmspecified by theCSS1 Specifications which is used by web browsers.This algorithm takes into account the font family name (e.g. "Arial", "NotoSans CJK", "Hack", ...), the size, style, and weight. In addition to familynames that map directly to fonts there are five "generic font family names"(serif, monospace, fantasy, cursive, and sans-serif) that will internally bemapped to any one of a set of fonts.

Currently the public API for doing step 2 isFontManager.findfont (and thatmethod on the globalFontManager instance is aliased at the module level asfont_manager.findfont), which will only find a single font and return the absolutepath to the font on the filesystem.

Font fallback#

There is no font that covers the entire Unicode space thus it is possible for theusers to require a mix of glyphs that cannot be satisfied from a single font.While it has been possible to use multiple fonts within a Figure, on distinctText instances, it was not previous possible to use multiple fonts in thesameText instance (as a web browser does). As of Matplotlib 3.6 the Agg,SVG, PDF, and PS backends will "fallback" through multiple fonts in a singleText instance:

fig,ax=plt.subplots()ax.text(.5,.5,"There are 几个汉字 in between!",family=['DejaVu Sans','Noto Sans CJK JP','Noto Sans TC'],ha='center')

(Sourcecode,2x.png,png)

The string "There are 几个汉字 in between!" rendered with 2 fonts.

Internally this is implemented by setting The "font family" onFontProperties objects to a list of font families. A (currently)private API extracts a list of paths to all of the fonts found and thenconstructs a singleft2font.FT2Font object that is aware of all of the fonts.Each glyph of the string is rendered using the first font in the list thatcontains that glyph.

A majority of this work was done by Aitik Gupta supported by Google Summer ofCode 2021.

Gallery generated by Sphinx-Gallery