1
- """
1
+ r """
2
2
.. redirect-from:: /users/fonts
3
3
.. redirect-from:: /users/explain/fonts
4
4
16
16
DejaVu Sans.
17
17
18
18
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>`.
190
21
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!"
191
111
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