Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0a43f82

Browse files
committed
DOC: Fix fonts [ci doc]
1 parent 3af6a59 commit 0a43f82

File tree

1 file changed

+179
-188
lines changed

1 file changed

+179
-188
lines changed

galleries/users_explain/text/fonts.py

Lines changed: 179 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""
1+
r"""
22
.. redirect-from:: /users/fonts
33
.. redirect-from:: /users/explain/fonts
44
@@ -16,192 +16,183 @@
1616
DejaVu Sans.
1717
1818
Matplotlib also provides an option to offload text rendering to a TeX engine
19-
(``usetex=True``), see :ref:`Text rendering with LaTeX <usetex>`.
20-
"""
21-
22-
import matplotlib.pyplot as plt
23-
24-
fig, ax = plt.subplots()
25-
ax.text(
26-
.5, .5, "There are 几个汉字 in between!",
27-
family=['DejaVu Sans', 'WenQuanYi Zen Hei'],
28-
ha='center'
29-
)
30-
31-
32-
# %%
33-
#
34-
# Fonts in PDF and PostScript
35-
# ---------------------------
36-
#
37-
# Fonts have a long (and sometimes incompatible) history in computing, leading to
38-
# different platforms supporting different types of fonts. In practice,
39-
# Matplotlib supports three font specifications (in addition to pdf 'core fonts',
40-
# which are explained later in the guide):
41-
#
42-
# .. list-table:: Type of Fonts
43-
# :header-rows: 1
44-
#
45-
# * - Type 1 (PDF)
46-
# - Type 3 (PDF/PS)
47-
# - TrueType (PDF)
48-
# * - One of the oldest types, introduced by Adobe
49-
# - Similar to Type 1 in terms of introduction
50-
# - Newer than previous types, used commonly today, introduced by Apple
51-
# * - Restricted subset of PostScript, charstrings are in bytecode
52-
# - Full PostScript language, allows embedding arbitrary code
53-
# (in theory, even render fractals when rasterizing!)
54-
# - Include a virtual machine that can execute code!
55-
# * - These fonts support font hinting
56-
# - Do not support font hinting
57-
# - Hinting supported (virtual machine processes the "hints")
58-
# * - Non-subsetted through Matplotlib
59-
# - Subsetted via external module ttconv
60-
# - Subsetted via external module `fontTools <https://github.com/fonttools/fonttools>`__
61-
#
62-
# .. note::
63-
#
64-
# Adobe disabled__ support for authoring with Type 1 fonts in January 2023.
65-
#
66-
# __ https://helpx.adobe.com/fonts/kb/postscript-type-1-fonts-end-of-support.html
67-
#
68-
# Other font specifications which Matplotlib supports:
69-
#
70-
# - Type 42 fonts (PS):
71-
#
72-
# - PostScript wrapper around TrueType fonts
73-
# - 42 is the `Answer to Life, the Universe, and Everything! <https://en.wikipedia.org/wiki/Answer_to_Life,_the_Universe,_and_Everything>`_
74-
# - Matplotlib uses the external library `fontTools <https://github.com/fonttools/fonttools>`__
75-
# to subset these types of fonts
76-
#
77-
# - OpenType fonts:
78-
#
79-
# - OpenType is a new standard for digital type fonts, developed jointly by
80-
# Adobe and Microsoft
81-
# - Generally contain a much larger character set!
82-
# - Limited support with Matplotlib
83-
#
84-
# Font subsetting
85-
# ~~~~~~~~~~~~~~~
86-
#
87-
# The PDF and PostScript formats support embedding fonts in files, allowing the
88-
# display program to correctly render the text, independent of what fonts are
89-
# installed on the viewer's computer and without the need to pre-rasterize the text.
90-
# This ensures that if the output is zoomed or resized the text does not become
91-
# pixelated. However, embedding full fonts in the file can lead to large output
92-
# files, particularly with fonts with many glyphs such as those that support CJK
93-
# (Chinese/Japanese/Korean).
94-
#
95-
# The solution to this problem is to subset the fonts used in the document and
96-
# only embed the glyphs actually used. This gets both vector text and small
97-
# files sizes. Computing the subset of the font required and writing the new
98-
# (reduced) font are both complex problem and thus Matplotlib relies on
99-
# `fontTools <https://fonttools.readthedocs.io/en/latest/>`__ and a vendored fork
100-
# of ttconv.
101-
#
102-
# Currently Type 3, Type 42, and TrueType fonts are subsetted. Type 1 fonts are not.
103-
#
104-
# Core Fonts
105-
# ~~~~~~~~~~
106-
#
107-
# In addition to the ability to embed fonts, as part of the `PostScript
108-
# <https://en.wikipedia.org/wiki/PostScript_fonts#Core_Font_Set>`_ and `PDF
109-
# specification
110-
# <https://docs.oracle.com/cd/E96927_01/TSG/FAQ/What%20are%20the%2014%20base%20fonts%20distributed%20with%20Acroba.html>`_
111-
# there are 14 Core Fonts that compliant viewers must ensure are available. If
112-
# you restrict your document to only these fonts you do not have to embed any
113-
# font information in the document but still get vector text.
114-
#
115-
# This is especially helpful to generate *really lightweight* documents::
116-
#
117-
# # trigger core fonts for PDF backend
118-
# plt.rcParams["pdf.use14corefonts"] = True
119-
# # trigger core fonts for PS backend
120-
# plt.rcParams["ps.useafm"] = True
121-
#
122-
# chars = "AFM ftw!"
123-
# fig, ax = plt.subplots()
124-
# ax.text(0.5, 0.5, chars)
125-
#
126-
# fig.savefig("AFM_PDF.pdf", format="pdf")
127-
# fig.savefig("AFM_PS.ps", format="ps)
128-
#
129-
# Fonts in SVG
130-
# ------------
131-
#
132-
# Text can output to SVG in two ways controlled by :rc:`svg.fonttype`:
133-
#
134-
# - as a path (``'path'``) in the SVG
135-
# - as string in the SVG with font styling on the element (``'none'``)
136-
#
137-
# When saving via ``'path'`` Matplotlib will compute the path of the glyphs used
138-
# as vector paths and write those to the output. The advantage of doing so is
139-
# that the SVG will look the same on all computers independent of what fonts are
140-
# installed. However the text will not be editable after the fact.
141-
# In contrast, saving with ``'none'`` will result in smaller files and the
142-
# text will appear directly in the markup. However, the appearance may vary
143-
# based on the SVG viewer and what fonts are available.
144-
#
145-
# Fonts in Agg
146-
# ------------
147-
#
148-
# To output text to raster formats via Agg, Matplotlib relies on `FreeType
149-
# <https://www.freetype.org/>`_. Because the exact rendering of the glyphs
150-
# changes between FreeType versions we pin to a specific version for our image
151-
# comparison tests.
152-
#
153-
# How Matplotlib selects fonts
154-
# ----------------------------
155-
#
156-
# Internally, using a font in Matplotlib is a three step process:
157-
#
158-
# 1. a `.FontProperties` object is created (explicitly or implicitly)
159-
# 2. based on the `.FontProperties` object the methods on `.FontManager` are used
160-
# to select the closest "best" font Matplotlib is aware of (except for
161-
# ``'none'`` mode of SVG).
162-
# 3. the Python proxy for the font object is used by the backend code to render
163-
# the text -- the exact details depend on the backend via `.font_manager.get_font`.
164-
#
165-
# The algorithm to select the "best" font is a modified version of the algorithm
166-
# specified by the `CSS1 Specifications
167-
# <http://www.w3.org/TR/1998/REC-CSS2-19980512/>`_ which is used by web browsers.
168-
# This algorithm takes into account the font family name (e.g. "Arial", "Noto
169-
# Sans CJK", "Hack", ...), the size, style, and weight. In addition to family
170-
# names that map directly to fonts there are five "generic font family names"
171-
# (serif, monospace, fantasy, cursive, and sans-serif) that will internally be
172-
# mapped to any one of a set of fonts.
173-
#
174-
# Currently the public API for doing step 2 is `.FontManager.findfont` (and that
175-
# method on the global `.FontManager` instance is aliased at the module level as
176-
# `.font_manager.findfont`), which will only find a single font and return the absolute
177-
# path to the font on the filesystem.
178-
#
179-
# Font fallback
180-
# -------------
181-
#
182-
# There is no font that covers the entire Unicode space thus it is possible for the
183-
# users to require a mix of glyphs that can not be satisfied from a single font.
184-
# While it has been possible to use multiple fonts within a Figure, on distinct
185-
# `.Text` instances, it was not previous possible to use multiple fonts in the
186-
# same `.Text` instance (as a web browser does). As of Matplotlib 3.6 the Agg,
187-
# SVG, PDF, and PS backends will "fallback" through multiple fonts in a single
188-
# `.Text` instance:
189-
#
19+
(``usetex=True``), see :ref:`Text rendering with LaTeX
20+
<usetex>`.
19021
22+
Fonts in PDF and PostScript
23+
---------------------------
24+
25+
Fonts have a long (and sometimes incompatible) history in computing, leading to
26+
different platforms supporting different types of fonts. In practice,
27+
Matplotlib supports three font specifications (in addition to pdf 'core fonts',
28+
which are explained later in the guide):
29+
30+
.. list-table:: Type of Fonts
31+
:header-rows: 1
32+
33+
* - Type 1 (PDF)
34+
- Type 3 (PDF/PS)
35+
- TrueType (PDF)
36+
* - One of the oldest types, introduced by Adobe
37+
- Similar to Type 1 in terms of introduction
38+
- Newer than previous types, used commonly today, introduced by Apple
39+
* - Restricted subset of PostScript, charstrings are in bytecode
40+
- Full PostScript language, allows embedding arbitrary code
41+
(in theory, even render fractals when rasterizing!)
42+
- Include a virtual machine that can execute code!
43+
* - These fonts support font hinting
44+
- Do not support font hinting
45+
- Hinting supported (virtual machine processes the "hints")
46+
* - Non-subsetted through Matplotlib
47+
- Subsetted via external module ttconv
48+
- Subsetted via external module `fontTools <https://github.com/fonttools/fonttools>`__
49+
50+
.. note::
51+
52+
Adobe disabled__ support for authoring with Type 1 fonts in January 2023.
53+
54+
__ https://helpx.adobe.com/fonts/kb/postscript-type-1-fonts-end-of-support.html
55+
56+
Other font specifications which Matplotlib supports:
57+
58+
- Type 42 fonts (PS):
59+
60+
- PostScript wrapper around TrueType fonts
61+
- 42 is the `Answer to Life, the Universe, and Everything! <https://en.wikipedia.org/wiki/Answer_to_Life,_the_Universe,_and_Everything>`_
62+
- Matplotlib uses the external library `fontTools <https://github.com/fonttools/fonttools>`__
63+
to subset these types of fonts
64+
65+
- OpenType fonts:
66+
67+
- OpenType is a new standard for digital type fonts, developed jointly by
68+
Adobe and Microsoft
69+
- Generally contain a much larger character set!
70+
- Limited support with Matplotlib
71+
72+
Font subsetting
73+
~~~~~~~~~~~~~~~
74+
75+
The PDF and PostScript formats support embedding fonts in files, allowing the
76+
display program to correctly render the text, independent of what fonts are
77+
installed on the viewer's computer and without the need to pre-rasterize the text.
78+
This ensures that if the output is zoomed or resized the text does not become
79+
pixelated. However, embedding full fonts in the file can lead to large output
80+
files, particularly with fonts with many glyphs such as those that support CJK
81+
(Chinese/Japanese/Korean).
82+
83+
The solution to this problem is to subset the fonts used in the document and
84+
only embed the glyphs actually used. This gets both vector text and small
85+
files sizes. Computing the subset of the font required and writing the new
86+
(reduced) font are both complex problem and thus Matplotlib relies on
87+
`fontTools <https://fonttools.readthedocs.io/en/latest/>`__ and a vendored fork
88+
of ttconv.
89+
90+
Currently Type 3, Type 42, and TrueType fonts are subsetted. Type 1 fonts are not.
91+
92+
Core Fonts
93+
~~~~~~~~~~
94+
95+
In addition to the ability to embed fonts, as part of the `PostScript
96+
<https://en.wikipedia.org/wiki/PostScript_fonts#Core_Font_Set>`_ and `PDF
97+
specification
98+
<https://docs.oracle.com/cd/E96927_01/TSG/FAQ/What%20are%20the%2014%20base%20fonts%20distributed%20with%20Acroba.html>`_
99+
there are 14 Core Fonts that compliant viewers must ensure are available. If
100+
you restrict your document to only these fonts you do not have to embed any
101+
font information in the document but still get vector text.
102+
103+
This is especially helpful to generate *really lightweight* documents::
104+
105+
# trigger core fonts for PDF backend
106+
plt.rcParams["pdf.use14corefonts"] = True
107+
# trigger core fonts for PS backend
108+
plt.rcParams["ps.useafm"] = True
109+
110+
chars = "AFM ftw!"
191111
fig, ax = plt.subplots()
192-
ax.text(
193-
.5, .5, "There are 几个汉字 in between!",
194-
family=['DejaVu Sans', 'WenQuanYi Zen Hei'],
195-
ha='center'
196-
)
197-
198-
# %%
199-
# Internally this is implemented by setting The "font family" on
200-
# `.FontProperties` objects to a list of font families. A (currently)
201-
# private API extracts a list of paths to all of the fonts found and then
202-
# constructs a single `.ft2font.FT2Font` object that is aware of all of the fonts.
203-
# Each glyph of the string is rendered using the first font in the list that
204-
# contains that glyph.
205-
#
206-
# A majority of this work was done by Aitik Gupta supported by Google Summer of
207-
# Code 2021.
112+
ax.text(0.5, 0.5, chars)
113+
114+
fig.savefig("AFM_PDF.pdf", format="pdf")
115+
fig.savefig("AFM_PS.ps", format="ps)
116+
117+
Fonts in SVG
118+
------------
119+
120+
Text can output to SVG in two ways controlled by :rc:`svg.fonttype`:
121+
122+
- as a path (``'path'``) in the SVG
123+
- as string in the SVG with font styling on the element (``'none'``)
124+
125+
When saving via ``'path'`` Matplotlib will compute the path of the glyphs used
126+
as vector paths and write those to the output. The advantage of doing so is
127+
that the SVG will look the same on all computers independent of what fonts are
128+
installed. However the text will not be editable after the fact.
129+
In contrast, saving with ``'none'`` will result in smaller files and the
130+
text will appear directly in the markup. However, the appearance may vary
131+
based on the SVG viewer and what fonts are available.
132+
133+
Fonts in Agg
134+
------------
135+
136+
To output text to raster formats via Agg, Matplotlib relies on `FreeType
137+
<https://www.freetype.org/>`_. Because the exact rendering of the glyphs
138+
changes between FreeType versions we pin to a specific version for our image
139+
comparison tests.
140+
141+
How Matplotlib selects fonts
142+
----------------------------
143+
144+
Internally, using a font in Matplotlib is a three step process:
145+
146+
1. a `.FontProperties` object is created (explicitly or implicitly)
147+
2. based on the `.FontProperties` object the methods on `.FontManager` are used
148+
to select the closest "best" font Matplotlib is aware of (except for
149+
``'none'`` mode of SVG).
150+
3. the Python proxy for the font object is used by the backend code to render
151+
the text -- the exact details depend on the backend via `.font_manager.get_font`.
152+
153+
The algorithm to select the "best" font is a modified version of the algorithm
154+
specified by the `CSS1 Specifications
155+
<http://www.w3.org/TR/1998/REC-CSS2-19980512/>`_ which is used by web browsers.
156+
This algorithm takes into account the font family name (e.g. "Arial", "Noto
157+
Sans CJK", "Hack", ...), the size, style, and weight. In addition to family
158+
names that map directly to fonts there are five "generic font family names"
159+
(serif, monospace, fantasy, cursive, and sans-serif) that will internally be
160+
mapped to any one of a set of fonts.
161+
162+
Currently the public API for doing step 2 is `.FontManager.findfont` (and that
163+
method on the global `.FontManager` instance is aliased at the module level as
164+
`.font_manager.findfont`), which will only find a single font and return the absolute
165+
path to the font on the filesystem.
166+
167+
Font fallback
168+
-------------
169+
170+
There is no font that covers the entire Unicode space thus it is possible for the
171+
users to require a mix of glyphs that can not be satisfied from a single font.
172+
While it has been possible to use multiple fonts within a Figure, on distinct
173+
`.Text` instances, it was not previous possible to use multiple fonts in the
174+
same `.Text` instance (as a web browser does). As of Matplotlib 3.6 the Agg,
175+
SVG, PDF, and PS backends will "fallback" through multiple fonts in a single
176+
`.Text` instance:
177+
178+
.. plot::
179+
:include-source:
180+
:caption: The string "There are 几个汉字 in between!" rendered with 2 fonts.
181+
182+
fig, ax = plt.subplots()
183+
ax.text(
184+
.5, .5, "There are 几个汉字 in between!",
185+
family=['DejaVu Sans', 'WenQuanYi Zen Hei'],
186+
ha='center'
187+
)
188+
189+
Internally this is implemented by setting The "font family" on
190+
`.FontProperties` objects to a list of font families. A (currently)
191+
private API extracts a list of paths to all of the fonts found and then
192+
constructs a single `.ft2font.FT2Font` object that is aware of all of the fonts.
193+
Each glyph of the string is rendered using the first font in the list that
194+
contains that glyph.
195+
196+
A majority of this work was done by Aitik Gupta supported by Google Summer of
197+
Code 2021.
198+
"""

0 commit comments

Comments
 (0)