Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e18701d

Browse filesBrowse files
authored
Merge pull request #20450 from aitikgupta/font-subset-docs
[Doc] Font Types and Font Subsetting
2 parents 9e0bb9c + a94f521 commit e18701d
Copy full SHA for e18701d

File tree

Expand file treeCollapse file tree

2 files changed

+131
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+131
-0
lines changed

‎doc/users/fonts.rst

Copy file name to clipboard
+130Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
Fonts in Matplotlib Text Engine
2+
===============================
3+
4+
Matplotlib needs fonts to work with its text engine, some of which are shipped
5+
alongside the installation. However, users can configure the default fonts, or
6+
even provide their own custom fonts! For more details, see :doc:`Customizing
7+
text properties </tutorials/text/text_props>`.
8+
9+
However, Matplotlib also provides an option to offload text rendering to a TeX
10+
engine (``usetex=True``),
11+
see :doc:`Text rendering with LaTeX </tutorials/text/usetex>`.
12+
13+
Font Specifications
14+
-------------------
15+
Fonts have a long and sometimes incompatible history in computing, leading to
16+
different platforms supporting different types of fonts. In practice, there are
17+
3 types of font specifications Matplotlib supports (in addition to 'core
18+
fonts', more about which is explained later in the guide):
19+
20+
.. list-table:: Type of Fonts
21+
:header-rows: 1
22+
23+
* - Type 1 (PDF)
24+
- Type 3 (PDF/PS)
25+
- TrueType (PDF)
26+
* - One of the oldest types, introduced by Adobe
27+
- Similar to Type 1 in terms of introduction
28+
- Newer than previous types, used commonly today, introduced by Apple
29+
* - Restricted subset of PostScript, charstrings are in bytecode
30+
- Full PostScript language, allows embedding arbitrary code
31+
(in theory, even render fractals when rasterizing!)
32+
- Include a virtual machine that can execute code!
33+
* - These fonts support font hinting
34+
- Do not support font hinting
35+
- Hinting supported (virtual machine processes the "hints")
36+
* - Non-subsetted through Matplotlib
37+
- Subsetted via external module `ttconv <https://github.com/sandflow/ttconv>`_
38+
- Subsetted via external module `fonttools <https://github.com/fonttools/fonttools>`_
39+
40+
NOTE: Adobe will disable support for authoring with Type 1 fonts in
41+
January 2023. `Read more here. <https://helpx.adobe.com/fonts/kb/postscript-type-1-fonts-end-of-support.html>`_
42+
43+
Special Mentions
44+
^^^^^^^^^^^^^^^^
45+
Other font specifications which Matplotlib supports:
46+
47+
- Type 42 fonts (PS):
48+
49+
- PostScript wrapper around TrueType fonts
50+
- 42 is the `Answer to Life, the Universe, and Everything! <https://en.wikipedia.org/wiki/Answer_to_Life,_the_Universe,_and_Everything>`_
51+
- Matplotlib uses an external library called `fonttools <https://github.com/fonttools/fonttools>`_
52+
to subset these types of fonts
53+
54+
- OpenType fonts:
55+
56+
- OpenType is a new standard for digital type fonts, developed jointly by
57+
Adobe and Microsoft
58+
- Generally contain a much larger character set!
59+
- Limited Support with Matplotlib
60+
61+
Subsetting
62+
----------
63+
Matplotlib is able to generate documents in multiple different formats. Some of
64+
those formats (for example, PDF, PS/EPS, SVG) allow embedding font data in such
65+
a way that when these documents are visually scaled, the text does not appear
66+
pixelated.
67+
68+
This can be achieved by embedding the *whole* font file within the
69+
output document. However, this can lead to very large documents, as some
70+
fonts (for instance, CJK - Chinese/Japanese/Korean fonts) can contain a large
71+
number of glyphs, and thus their embedded size can be quite huge.
72+
73+
Font Subsetting can be used before generating documents, to embed only the
74+
*required* glyphs within the documents. Fonts can be considered as a collection
75+
of glyphs, so ultimately the goal is to find out *which* glyphs are required
76+
for a certain array of characters, and embed only those within the output.
77+
78+
.. note::
79+
The role of subsetter really shines when we encounter characters like **ä**
80+
(composed by calling subprograms for **a** and **¨**); since the subsetter
81+
has to find out *all* such subprograms being called by every glyph included
82+
in the subset, this is a generally difficult problem!
83+
84+
Luckily, Matplotlib uses a fork of an external dependency called
85+
`ttconv <https://github.com/sandflow/ttconv>`_, which helps in embedding and
86+
subsetting font data. (however, recent versions have moved away from ttconv to
87+
pure Python for certain types: for more details visit
88+
`these <https://github.com/matplotlib/matplotlib/pull/18370>`_, `links <https://github.com/matplotlib/matplotlib/pull/18181>`_)
89+
90+
| *Type 1 fonts are still non-subsetted* through Matplotlib. (though one will encounter these mostly via *usetex*/*dviread* in PDF backend)
91+
| **Type 3 and Type 42 fonts are subsetted**, with a fair amount of exceptions and bugs for the latter.
92+
93+
What to use?
94+
------------
95+
Practically, most fonts that are readily available on most operating systems or
96+
are readily available on the internet to download include *TrueType fonts* and
97+
its "extensions" such as MacOS-resource fork fonts and the newer OpenType
98+
fonts.
99+
100+
PS and PDF backends provide support for yet another type of fonts, which remove
101+
the need of subsetting altogether! These are called **Core Fonts**, and
102+
Matplotlib calls them via the keyword **AFM**; all that is supplied from
103+
Matplotlib to such documents are font metrics (specified in AFM format), and it
104+
is the job of the viewer applications to supply the glyph definitions.
105+
106+
This is especially helpful to generate *really lightweight* documents.::
107+
108+
# trigger core fonts for PDF backend
109+
plt.rcParams["pdf.use14corefonts"] = True
110+
# trigger core fonts for PS backend
111+
plt.rcParams["ps.useafm"] = True
112+
113+
chars = "AFM ftw!"
114+
fig, ax = plt.subplots()
115+
ax.text(0.5, 0.5, chars)
116+
117+
fig.savefig("AFM_PDF.pdf", format="pdf")
118+
fig.savefig("AFM_PS.ps", format="ps)
119+
120+
.. note::
121+
These core fonts are limited to PDF and PS backends only; they can not be
122+
rendered in other backends.
123+
124+
Another downside to this is that while the font metric are standardized,
125+
different PDF viewer applications will have different fonts to render these
126+
metrics. In other words, the **output might look different on different
127+
viewers**, as well as (let's say) Windows and Linux, if Linux tools included
128+
free versions of the proprietary fonts.
129+
130+
This also violates the *what-you-see-is-what-you-get* feature of Matplotlib.

‎doc/users/index.rst

Copy file name to clipboardExpand all lines: doc/users/index.rst
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ User's guide
1313
:maxdepth: 2
1414

1515
interactive.rst
16+
fonts.rst
1617
release_notes.rst
1718
license.rst
1819
../citing.rst

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.