Skip to content

Commit 58f38a7

Browse files
committed
Merge commit '56308afb3b0cfc0952148ade8fa918846a3f2419' into text-overhaul-figures-per-commit
2 parents cb66eba + 56308af commit 58f38a7

File tree

19 files changed

+144
-96
lines changed

19 files changed

+144
-96
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FT2Font no longer sets a default size
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
In the interest of handling non-scalable fonts and reducing font initialization, the
5+
`.FT2Font` constructor no longer sets a default size. Non-scalable fonts are sometimes
6+
used for bitmap-backed emoji fonts.
7+
8+
If metrics are important (i.e., if you are loading character glyphs, or setting a text
9+
string), then explicitly call `.FT2Font.set_size` beforehand.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Font kerning factor is deprecated
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Due to internal changes to support complex text rendering, the kerning factor on fonts is
5+
no longer used. Setting the ``text.kerning_factor`` rcParam (which existed only for
6+
backwards-compatibility) to any value other than None is deprecated, and the rcParam will
7+
be removed in the future.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``font_manager.is_opentype_cff_font`` is deprecated
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
There is no replacement.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Glyph indices now typed distinctly from character codes
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Previously, character codes and glyph indices were both typed as `int`, which means you
5+
could mix and match them erroneously. While the character code can't be made a distinct
6+
type (because it's used for `chr`/`ord`), typing glyph indices as a distinct type means
7+
these can't be fully swapped.

doc/users/prev_whats_new/whats_new_3.2.0.rst

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,15 @@ triangle meshes.
5252

5353
Kerning adjustments now use correct values
5454
------------------------------------------
55-
Due to an error in how kerning adjustments were applied, previous versions of
56-
Matplotlib would under-correct kerning. This version will now correctly apply
57-
kerning (for fonts supported by FreeType). To restore the old behavior (e.g.,
58-
for test images), you may set :rc:`text.kerning_factor` to 6 (instead of 0).
59-
Other values have undefined behavior.
60-
61-
.. plot::
62-
63-
import matplotlib.pyplot as plt
64-
65-
# Use old kerning values:
66-
plt.rcParams['text.kerning_factor'] = 6
67-
fig, ax = plt.subplots()
68-
ax.text(0.0, 0.05, 'BRAVO\nAWKWARD\nVAT\nW.Test', fontsize=56)
69-
ax.set_title('Before (text.kerning_factor = 6)')
70-
71-
Note how the spacing between characters is uniform between their bounding boxes
72-
(above). With corrected kerning (below), slanted characters (e.g., AV or VA)
73-
will be spaced closer together, as well as various other character pairs,
74-
depending on font support (e.g., T and e, or the period after the W).
55+
Due to an error in how kerning adjustments were applied, previous versions of Matplotlib
56+
would under-correct kerning. This version will now correctly apply kerning (for fonts
57+
supported by FreeType). To restore the old behavior (e.g., for test images), you may set
58+
the ``text.kerning_factor`` rcParam to 6 (instead of 0). Other values have undefined
59+
behavior.
60+
61+
With corrected kerning (below), slanted characters (e.g., AV or VA) will be spaced closer
62+
together, as well as various other character pairs, depending on font support (e.g., T
63+
and e, or the period after the W).
7564

7665
.. plot::
7766

lib/matplotlib/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ def __setitem__(self, key, val):
751751
f"a list of valid parameters)") from err
752752
except ValueError as ve:
753753
raise ValueError(f"Key {key}: {ve}") from None
754+
if key == "text.kerning_factor" and cval is not None:
755+
_api.warn_deprecated("3.11", name="text.kerning_factor", obj_type="rcParam")
754756
self._set(key, cval)
755757

756758
def __getitem__(self, key):

lib/matplotlib/_afm.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030
import inspect
3131
import logging
3232
import re
33-
from typing import BinaryIO, NamedTuple, TypedDict
33+
from typing import BinaryIO, NamedTuple, TypedDict, cast
3434

3535
from ._mathtext_data import uni2type1
36+
from .ft2font import CharacterCodeType, GlyphIndexType
3637

3738

3839
_log = logging.getLogger(__name__)
@@ -197,7 +198,7 @@ class CharMetrics(NamedTuple):
197198
The bbox of the character (B) as a tuple (*llx*, *lly*, *urx*, *ury*)."""
198199

199200

200-
def _parse_char_metrics(fh: BinaryIO) -> tuple[dict[int, CharMetrics],
201+
def _parse_char_metrics(fh: BinaryIO) -> tuple[dict[CharacterCodeType, CharMetrics],
201202
dict[str, CharMetrics]]:
202203
"""
203204
Parse the given filehandle for character metrics information.
@@ -218,7 +219,7 @@ def _parse_char_metrics(fh: BinaryIO) -> tuple[dict[int, CharMetrics],
218219
"""
219220
required_keys = {'C', 'WX', 'N', 'B'}
220221

221-
ascii_d: dict[int, CharMetrics] = {}
222+
ascii_d: dict[CharacterCodeType, CharMetrics] = {}
222223
name_d: dict[str, CharMetrics] = {}
223224
for bline in fh:
224225
# We are defensively letting values be utf8. The spec requires
@@ -409,19 +410,21 @@ def get_str_bbox_and_descent(self, s: str) -> tuple[int, int, float, int, int]:
409410

410411
return left, miny, total_width, maxy - miny, -miny
411412

412-
def get_glyph_name(self, glyph_ind: int) -> str: # For consistency with FT2Font.
413+
def get_glyph_name(self, # For consistency with FT2Font.
414+
glyph_ind: GlyphIndexType) -> str:
413415
"""Get the name of the glyph, i.e., ord(';') is 'semicolon'."""
414-
return self._metrics[glyph_ind].name
416+
return self._metrics[cast(CharacterCodeType, glyph_ind)].name
415417

416-
def get_char_index(self, c: int) -> int: # For consistency with FT2Font.
418+
def get_char_index(self, # For consistency with FT2Font.
419+
c: CharacterCodeType) -> GlyphIndexType:
417420
"""
418421
Return the glyph index corresponding to a character code point.
419422
420423
Note, for AFM fonts, we treat the glyph index the same as the codepoint.
421424
"""
422-
return c
425+
return cast(GlyphIndexType, c)
423426

424-
def get_width_char(self, c: int) -> float:
427+
def get_width_char(self, c: CharacterCodeType) -> float:
425428
"""Get the width of the character code from the character metric WX field."""
426429
return self._metrics[c].width
427430

lib/matplotlib/_mathtext.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737

3838
if T.TYPE_CHECKING:
3939
from collections.abc import Iterable
40-
from .ft2font import Glyph
40+
from .ft2font import CharacterCodeType, Glyph
41+
4142

4243
ParserElement.enable_packrat()
4344
_log = logging.getLogger("matplotlib.mathtext")
@@ -47,7 +48,7 @@
4748
# FONTS
4849

4950

50-
def get_unicode_index(symbol: str) -> int: # Publicly exported.
51+
def get_unicode_index(symbol: str) -> CharacterCodeType: # Publicly exported.
5152
r"""
5253
Return the integer index (from the Unicode table) of *symbol*.
5354
@@ -85,7 +86,7 @@ class VectorParse(NamedTuple):
8586
width: float
8687
height: float
8788
depth: float
88-
glyphs: list[tuple[FT2Font, float, int, float, float]]
89+
glyphs: list[tuple[FT2Font, float, CharacterCodeType, float, float]]
8990
rects: list[tuple[float, float, float, float]]
9091

9192
VectorParse.__module__ = "matplotlib.mathtext"
@@ -212,7 +213,7 @@ class FontInfo(NamedTuple):
212213
fontsize: float
213214
postscript_name: str
214215
metrics: FontMetrics
215-
num: int
216+
num: CharacterCodeType
216217
glyph: Glyph
217218
offset: float
218219

@@ -365,7 +366,7 @@ def _get_offset(self, font: FT2Font, glyph: Glyph, fontsize: float,
365366
return 0.
366367

367368
def _get_glyph(self, fontname: str, font_class: str,
368-
sym: str) -> tuple[FT2Font, int, bool]:
369+
sym: str) -> tuple[FT2Font, CharacterCodeType, bool]:
369370
raise NotImplementedError
370371

371372
# The return value of _get_info is cached per-instance.
@@ -425,7 +426,9 @@ def get_kern(self, font1: str, fontclass1: str, sym1: str, fontsize1: float,
425426
info1 = self._get_info(font1, fontclass1, sym1, fontsize1, dpi)
426427
info2 = self._get_info(font2, fontclass2, sym2, fontsize2, dpi)
427428
font = info1.font
428-
return font.get_kerning(info1.num, info2.num, Kerning.DEFAULT) / 64
429+
return font.get_kerning(font.get_char_index(info1.num),
430+
font.get_char_index(info2.num),
431+
Kerning.DEFAULT) / 64
429432
return super().get_kern(font1, fontclass1, sym1, fontsize1,
430433
font2, fontclass2, sym2, fontsize2, dpi)
431434

@@ -459,7 +462,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
459462
_slanted_symbols = set(r"\int \oint".split())
460463

461464
def _get_glyph(self, fontname: str, font_class: str,
462-
sym: str) -> tuple[FT2Font, int, bool]:
465+
sym: str) -> tuple[FT2Font, CharacterCodeType, bool]:
463466
font = None
464467
if fontname in self.fontmap and sym in latex_to_bakoma:
465468
basename, num = latex_to_bakoma[sym]
@@ -551,7 +554,7 @@ class UnicodeFonts(TruetypeFonts):
551554
# Some glyphs are not present in the `cmr10` font, and must be brought in
552555
# from `cmsy10`. Map the Unicode indices of those glyphs to the indices at
553556
# which they are found in `cmsy10`.
554-
_cmr10_substitutions = {
557+
_cmr10_substitutions: dict[CharacterCodeType, CharacterCodeType] = {
555558
0x00D7: 0x00A3, # Multiplication sign.
556559
0x2212: 0x00A1, # Minus sign.
557560
}
@@ -594,11 +597,11 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
594597
_slanted_symbols = set(r"\int \oint".split())
595598

596599
def _map_virtual_font(self, fontname: str, font_class: str,
597-
uniindex: int) -> tuple[str, int]:
600+
uniindex: CharacterCodeType) -> tuple[str, CharacterCodeType]:
598601
return fontname, uniindex
599602

600603
def _get_glyph(self, fontname: str, font_class: str,
601-
sym: str) -> tuple[FT2Font, int, bool]:
604+
sym: str) -> tuple[FT2Font, CharacterCodeType, bool]:
602605
try:
603606
uniindex = get_unicode_index(sym)
604607
found_symbol = True
@@ -607,8 +610,7 @@ def _get_glyph(self, fontname: str, font_class: str,
607610
found_symbol = False
608611
_log.warning("No TeX to Unicode mapping for %a.", sym)
609612

610-
fontname, uniindex = self._map_virtual_font(
611-
fontname, font_class, uniindex)
613+
fontname, uniindex = self._map_virtual_font(fontname, font_class, uniindex)
612614

613615
new_fontname = fontname
614616

@@ -693,7 +695,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
693695
self.fontmap[name] = fullpath
694696

695697
def _get_glyph(self, fontname: str, font_class: str,
696-
sym: str) -> tuple[FT2Font, int, bool]:
698+
sym: str) -> tuple[FT2Font, CharacterCodeType, bool]:
697699
# Override prime symbol to use Bakoma.
698700
if sym == r'\prime':
699701
return self.bakoma._get_glyph(fontname, font_class, sym)
@@ -783,7 +785,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
783785
self.fontmap[name] = fullpath
784786

785787
def _map_virtual_font(self, fontname: str, font_class: str,
786-
uniindex: int) -> tuple[str, int]:
788+
uniindex: CharacterCodeType) -> tuple[str, CharacterCodeType]:
787789
# Handle these "fonts" that are actually embedded in
788790
# other fonts.
789791
font_mapping = stix_virtual_fonts.get(fontname)
@@ -1170,7 +1172,7 @@ def __init__(self, elements: T.Sequence[Node]):
11701172
self.glue_sign = 0 # 0: normal, -1: shrinking, 1: stretching
11711173
self.glue_order = 0 # The order of infinity (0 - 3) for the glue
11721174

1173-
def __repr__(self):
1175+
def __repr__(self) -> str:
11741176
return "{}<w={:.02f} h={:.02f} d={:.02f} s={:.02f}>[{}]".format(
11751177
super().__repr__(),
11761178
self.width, self.height,

lib/matplotlib/_mathtext_data.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
"""
44

55
from __future__ import annotations
6-
from typing import overload
6+
from typing import TypeAlias, overload
77

8-
latex_to_bakoma = {
8+
from .ft2font import CharacterCodeType
9+
10+
11+
latex_to_bakoma: dict[str, tuple[str, CharacterCodeType]] = {
912
'\\__sqrt__' : ('cmex10', 0x70),
1013
'\\bigcap' : ('cmex10', 0x5c),
1114
'\\bigcup' : ('cmex10', 0x5b),
@@ -241,7 +244,7 @@
241244

242245
# Automatically generated.
243246

244-
type12uni = {
247+
type12uni: dict[str, CharacterCodeType] = {
245248
'aring' : 229,
246249
'quotedblright' : 8221,
247250
'V' : 86,
@@ -475,7 +478,7 @@
475478
# for key in sd:
476479
# print("{0:24} : {1: <s},".format("'" + key + "'", sd[key]))
477480

478-
tex2uni = {
481+
tex2uni: dict[str, CharacterCodeType] = {
479482
'#' : 0x23,
480483
'$' : 0x24,
481484
'%' : 0x25,
@@ -1113,8 +1116,9 @@
11131116
# Each element is a 4-tuple of the form:
11141117
# src_start, src_end, dst_font, dst_start
11151118

1116-
_EntryTypeIn = tuple[str, str, str, str | int]
1117-
_EntryTypeOut = tuple[int, int, str, int]
1119+
_EntryTypeIn: TypeAlias = tuple[str, str, str, str | CharacterCodeType]
1120+
_EntryTypeOut: TypeAlias = tuple[CharacterCodeType, CharacterCodeType, str,
1121+
CharacterCodeType]
11181122

11191123
_stix_virtual_fonts: dict[str, dict[str, list[_EntryTypeIn]] | list[_EntryTypeIn]] = {
11201124
'bb': {
@@ -1735,7 +1739,7 @@ def _normalize_stix_fontcodes(d):
17351739
del _stix_virtual_fonts
17361740

17371741
# Fix some incorrect glyphs.
1738-
stix_glyph_fixes = {
1742+
stix_glyph_fixes: dict[CharacterCodeType, CharacterCodeType] = {
17391743
# Cap and Cup glyphs are swapped.
17401744
0x22d2: 0x22d3,
17411745
0x22d3: 0x22d2,

lib/matplotlib/_text_helpers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import dataclasses
88

99
from . import _api
10-
from .ft2font import FT2Font, Kerning, LoadFlags
10+
from .ft2font import FT2Font, GlyphIndexType, Kerning, LoadFlags
1111

1212

1313
@dataclasses.dataclass(frozen=True)
1414
class LayoutItem:
1515
ft_object: FT2Font
1616
char: str
17-
glyph_idx: int
17+
glyph_idx: GlyphIndexType
1818
x: float
1919
prev_kern: float
2020

0 commit comments

Comments
 (0)