From 813709181fed75e1ca5599219f3783ae59d7b4ec Mon Sep 17 00:00:00 2001 From: Leon Merten Lohse Date: Mon, 9 Feb 2026 09:13:43 +0100 Subject: [PATCH 1/3] mathtext refactoring: replace FontConstants lookup Replace lookup table for font constants based on the family name by methods in their respective classes. Removes non-local call of private _get_font method in _get_font_constant_set. This simplifies implementing dynamically loaded font constants. --- lib/matplotlib/_mathtext.py | 65 +++++++++++++------------------------ 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index b6cdb1fa6e8e..3b36d6d4ea14 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -341,6 +341,9 @@ def get_sized_alternatives_for_symbol(self, fontname: str, """ return [(fontname, sym)] + def get_font_constants(self) -> type[FontConstantsBase]: + return FontConstantsBase + class TruetypeFonts(Fonts, metaclass=abc.ABCMeta): """ @@ -420,7 +423,7 @@ def _get_info(self, fontname: str, font_class: str, sym: str, fontsize: float, ) def get_axis_height(self, fontname: str, fontsize: float, dpi: float) -> float: - consts = _get_font_constants(self, fontname) + consts = self.get_font_constants() if consts.axis_height is not None: return consts.axis_height * fontsize * dpi / 72 else: @@ -431,7 +434,7 @@ def get_axis_height(self, fontname: str, fontsize: float, dpi: float) -> float: return (metrics.ymax + metrics.ymin) / 2 def get_quad(self, fontname: str, fontsize: float, dpi: float) -> float: - consts = _get_font_constants(self, fontname) + consts = self.get_font_constants() if consts.quad is not None: return consts.quad * fontsize * dpi / 72 else: @@ -551,6 +554,9 @@ def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> list[tuple[str, str]]: return self._size_alternatives.get(sym, [(fontname, sym)]) + def get_font_constants(self) -> type[FontConstantsBase]: + return ComputerModernFontConstants + class UnicodeFonts(TruetypeFonts): """ @@ -741,6 +747,9 @@ class DejaVuSerifFonts(DejaVuFonts): 0: 'DejaVu Serif', } + def get_font_constants(self) -> type[FontConstantsBase]: + return DejaVuSerifFontConstants + class DejaVuSansFonts(DejaVuFonts): """ @@ -759,6 +768,9 @@ class DejaVuSansFonts(DejaVuFonts): 0: 'DejaVu Sans', } + def get_font_constants(self) -> type[FontConstantsBase]: + return DejaVuSansFontConstants + class StixFonts(UnicodeFonts): """ @@ -874,6 +886,12 @@ def get_sized_alternatives_for_symbol( # type: ignore[override] alternatives = alternatives[:-1] return alternatives + def get_font_constants(self) -> type[FontConstantsBase]: + if self._sans: + return STIXSansFontConstants + else: + return STIXFontConstants + class StixSansFonts(StixFonts): """ @@ -1078,45 +1096,6 @@ class DejaVuSansFontConstants(FontConstantsBase): axis_height = 512 / 2048 -# Maps font family names to the FontConstantBase subclass to use -_font_constant_mapping = { - 'DejaVu Sans': DejaVuSansFontConstants, - 'DejaVu Sans Mono': DejaVuSansFontConstants, - 'DejaVu Serif': DejaVuSerifFontConstants, - 'cmb10': ComputerModernFontConstants, - 'cmex10': ComputerModernFontConstants, - 'cmmi10': ComputerModernFontConstants, - 'cmr10': ComputerModernFontConstants, - 'cmss10': ComputerModernFontConstants, - 'cmsy10': ComputerModernFontConstants, - 'cmtt10': ComputerModernFontConstants, - 'STIXGeneral': STIXFontConstants, - 'STIXNonUnicode': STIXFontConstants, - 'STIXSizeFiveSym': STIXFontConstants, - 'STIXSizeFourSym': STIXFontConstants, - 'STIXSizeThreeSym': STIXFontConstants, - 'STIXSizeTwoSym': STIXFontConstants, - 'STIXSizeOneSym': STIXFontConstants, - # Map the fonts we used to ship, just for good measure - 'Bitstream Vera Sans': DejaVuSansFontConstants, - 'Bitstream Vera': DejaVuSansFontConstants, - } - - -def _get_font_constants(fontset: Fonts, font: str) -> type[FontConstantsBase]: - constants = _font_constant_mapping.get(fontset._get_font(font).family_name, - FontConstantsBase) - # STIX sans isn't really its own fonts, just different code points - # in the STIX fonts, so we have to detect this one separately. - if constants is STIXFontConstants and isinstance(fontset, StixSansFonts): - return STIXSansFontConstants - return constants - - -def _get_font_constant_set(state: ParserState) -> type[FontConstantsBase]: - return _get_font_constants(state.fontset, state.font) - - class Node: """A node in the TeX box model.""" @@ -2649,7 +2628,7 @@ def subsuper(self, s: str, loc: int, toks: ParseResults) -> T.Any: nucleus = Hlist([nucleus]) # Handle regular sub/superscripts - consts = _get_font_constant_set(state) + consts = state.fontset.get_font_constants() lc_height = last_char.height lc_baseline = 0 if self.is_dropsub(last_char): @@ -2743,7 +2722,7 @@ def _genfrac(self, ldelim: str, rdelim: str, rule: float | None, style: _MathSty axis_height = state.fontset.get_axis_height( state.font, state.fontsize, state.dpi) - consts = _get_font_constant_set(state) + consts = state.fontset.get_font_constants() x_height = state.fontset.get_xheight(state.font, state.fontsize, state.dpi) for _ in range(style.value): From a6913f3b26d539846896d87b7729d1b1b74da2fa Mon Sep 17 00:00:00 2001 From: Leon Merten Lohse Date: Mon, 9 Feb 2026 10:30:07 +0100 Subject: [PATCH 2/3] mathtext: implement \mathnormal and distinguish between normal and it To replicate LaTeX behaviour, distinguish between "italic" and "normal" math. In particular, digits should be set italic in the \mathit env. For `cm`, use cmti font for "it" For general UnicodeFont (stix, DejaVu, ...), maps digits to roman or italic alphabet, depending on "normal" or "it" environment. --- doc/release/next_whats_new/mathnormal.rst | 10 + lib/matplotlib/_mathtext.py | 40 ++- lib/matplotlib/_mathtext_data.py | 15 +- lib/matplotlib/font_manager.py | 2 +- lib/matplotlib/mpl-data/fonts/afm/cmti10.afm | 333 ++++++++++++++++++ lib/matplotlib/mpl-data/fonts/ttf/cmti10.ttf | Bin 0 -> 32808 bytes lib/matplotlib/mpl-data/matplotlibrc | 8 +- .../mpl-data/stylelib/classic.mplstyle | 8 +- lib/matplotlib/rcsetup.py | 6 +- 9 files changed, 385 insertions(+), 37 deletions(-) create mode 100644 doc/release/next_whats_new/mathnormal.rst create mode 100644 lib/matplotlib/mpl-data/fonts/afm/cmti10.afm create mode 100644 lib/matplotlib/mpl-data/fonts/ttf/cmti10.ttf diff --git a/doc/release/next_whats_new/mathnormal.rst b/doc/release/next_whats_new/mathnormal.rst new file mode 100644 index 000000000000..7e4cd5d333fe --- /dev/null +++ b/doc/release/next_whats_new/mathnormal.rst @@ -0,0 +1,10 @@ +Mathtext distinguishes *italic* and *normal* font +------------------------------------------------- + +Matplotlib's lightweight TeX expression parser (``usetex=False``) now distinguishes between *italic* and *normal* math fonts to closer replicate the behaviour of LaTeX. +The normal math font is selected by default in math environment (unless the rcParam ``mathtext.default`` is overwritten) but can be explicitly set with the new ``\mathnormal`` command. Italic font is selected with ``\mathit``. +The main difference is that *italic* produces italic digits, whereas *normal* produces upright digits. Previously, it was not possible to typeset italic digits. +Note that ``normal`` now corresponds to what used to be ``it``, whereas ``it`` now renders all characters italic. +**Important**: In case the default mathematics font is overwritten by setting ``mathtext.default: it`` in ``matplotlibrc``, it must be either commented out or changed to ``mathtext.default: normal`` to preserve its behaviour. Otherwise, all alphanumeric characters, including digits, are rendered italic. + +One difference to traditional LaTeX is that LaTeX further distinguishes between *normal* (``\mathnormal``) and *default math*, where the default uses roman digits and normal uses oldstyle digits. This distinction is no longer present with modern LaTeX engines and unicode-math nor in Matplotlib. diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 3b36d6d4ea14..dc09dedcca2c 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -269,8 +269,9 @@ def get_metrics(self, font: str, font_class: str, sym: str, fontsize: float, ---------- font : str One of the TeX font names: "tt", "it", "rm", "cal", "sf", "bf", - "default", "regular", "bb", "frak", "scr". "default" and "regular" - are synonyms and use the non-math font. + "default", "regular", "normal", "bb", "frak", "scr". "default" + and "regular" are synonyms and use the non-math font. + "normal" denotes the normal math font. font_class : str One of the TeX font names (as for *font*), but **not** "bb", "frak", or "scr". This is used to combine two font classes. The @@ -477,10 +478,11 @@ class BakomaFonts(TruetypeFonts): its own proprietary 8-bit encoding. """ _fontmap = { + 'normal': 'cmmi10', 'cal': 'cmsy10', 'rm': 'cmr10', 'tt': 'cmtt10', - 'it': 'cmmi10', + 'it': 'cmti10', 'bf': 'cmb10', 'sf': 'cmss10', 'ex': 'cmex10', @@ -500,12 +502,18 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag def _get_glyph(self, fontname: str, font_class: str, sym: str) -> tuple[FT2Font, CharacterCodeType, bool]: font = None + if fontname in self.fontmap and sym in latex_to_bakoma: basename, num = latex_to_bakoma[sym] - slanted = (basename == "cmmi10") or sym in self._slanted_symbols + slanted = (basename in ("cmmi10", "cmti10")) or sym in self._slanted_symbols font = self._get_font(basename) elif len(sym) == 1: - slanted = (fontname == "it") + slanted = (fontname in ("it", "normal")) + if fontname == "normal" and sym.isdigit(): + # use digits from cmr (roman alphabet) instead of cmm (math alphabet), + # same as LaTeX does. + fontname = "rm" + slanted = False font = self._get_font(fontname) if font is not None: num = ord(sym) @@ -636,11 +644,14 @@ def _get_glyph(self, fontname: str, font_class: str, # Only characters in the "Letter" class should be italicized in 'it' # mode. Greek capital letters should be Roman. if found_symbol: - if fontname == 'it' and uniindex < 0x10000: + if fontname == 'normal' and uniindex < 0x10000: + # normal mathematics font char = chr(uniindex) if (unicodedata.category(char)[0] != "L" or unicodedata.name(char).startswith("GREEK CAPITAL")): new_fontname = 'rm' + else: + new_fontname = 'it' slanted = (new_fontname == 'it') or sym in self._slanted_symbols found_symbol = False @@ -657,7 +668,7 @@ def _get_glyph(self, fontname: str, font_class: str, if not found_symbol: if self._fallback_font: - if (fontname in ('it', 'regular') + if (fontname in ('it', 'regular', 'normal') and isinstance(self._fallback_font, StixFonts)): fontname = 'rm' @@ -669,7 +680,7 @@ def _get_glyph(self, fontname: str, font_class: str, return g else: - if (fontname in ('it', 'regular') + if (fontname in ('it', 'regular', 'normal') and isinstance(self, StixFonts)): return self._get_glyph('rm', font_class, sym) _log.warning("Font %r does not have a glyph for %a [U+%x], " @@ -854,7 +865,7 @@ def _map_virtual_font(self, fontname: str, font_class: str, fontname = mpl.rcParams['mathtext.default'] # Fix some incorrect glyphs. - if fontname in ('rm', 'it'): + if fontname in ('rm', 'it', 'normal'): uniindex = stix_glyph_fixes.get(uniindex, uniindex) # Handle private use area glyphs @@ -1875,7 +1886,7 @@ def font(self) -> str: @font.setter def font(self, name: str) -> None: - if name in ('rm', 'it', 'bf', 'bfit'): + if name in ('normal', 'rm', 'it', 'bf', 'bfit'): self.font_class = name self._font = name @@ -2047,7 +2058,7 @@ class _MathStyle(enum.Enum): _dropsub_symbols = set(r'\int \oint \iint \oiint \iiint \oiiint \iiiint'.split()) _fontnames = set("rm cal it tt sf bf bfit " - "default bb frak scr regular".split()) + "default bb frak scr regular normal".split()) _function_names = set(""" arccos csc ker min arcsin deg lg Pr arctan det lim sec arg dim @@ -2304,7 +2315,7 @@ def non_math(self, toks: ParseResults) -> T.Any: s = toks[0].replace(r'\$', '$') symbols = [Char(c, self.get_state()) for c in s] hlist = Hlist(symbols) - # We're going into math now, so set font to 'it' + # We're going into math now, so set font to 'normal' self.push_state() self.get_state().font = mpl.rcParams['mathtext.default'] return [hlist] @@ -2323,13 +2334,14 @@ def _make_space(self, percentage: float) -> Kern: # In TeX, an em (the unit usually used to measure horizontal lengths) # is not the width of the character 'm'; it is the same in different # font styles (e.g. roman or italic). Mathtext, however, uses 'm' in - # the italic style so that horizontal spaces don't depend on the + # the normal style so that horizontal spaces don't depend on the # current font style. + # TODO: this should be read from the font file state = self.get_state() key = (state.font, state.fontsize, state.dpi) width = self._em_width_cache.get(key) if width is None: - width = state.fontset.get_quad('it', state.fontsize, state.dpi) + width = state.fontset.get_quad('normal', state.fontsize, state.dpi) self._em_width_cache[key] = width return Kern(width * percentage) diff --git a/lib/matplotlib/_mathtext_data.py b/lib/matplotlib/_mathtext_data.py index f8b7c9ac2c33..6d0c20a1b2a2 100644 --- a/lib/matplotlib/_mathtext_data.py +++ b/lib/matplotlib/_mathtext_data.py @@ -161,16 +161,6 @@ '(' : ('cmr10', 0x28), ')' : ('cmr10', 0x29), '+' : ('cmr10', 0x2b), - '0' : ('cmr10', 0x30), - '1' : ('cmr10', 0x31), - '2' : ('cmr10', 0x32), - '3' : ('cmr10', 0x33), - '4' : ('cmr10', 0x34), - '5' : ('cmr10', 0x35), - '6' : ('cmr10', 0x36), - '7' : ('cmr10', 0x37), - '8' : ('cmr10', 0x38), - '9' : ('cmr10', 0x39), ':' : ('cmr10', 0x3a), ';' : ('cmr10', 0x3b), '=' : ('cmr10', 0x3d), @@ -1350,7 +1340,7 @@ "\N{DOUBLE-STRUCK CAPITAL PI}"), ("\N{GREEK CAPITAL LETTER SIGMA}", "\N{GREEK CAPITAL LETTER SIGMA}", - "it", + "rm", # not in STIX italic "\N{DOUBLE-STRUCK N-ARY SUMMATION}"), # \Sigma (not in beta STIX fonts) ("\N{GREEK SMALL LETTER GAMMA}", "\N{GREEK SMALL LETTER GAMMA}", @@ -1778,6 +1768,9 @@ ], } +_stix_virtual_fonts['bb']['normal'] = _stix_virtual_fonts['bb']['it'] # type:ignore[call-overload] +_stix_virtual_fonts['sf']['normal'] = _stix_virtual_fonts['sf']['it'] # type:ignore[call-overload] + @overload def _normalize_stix_fontcodes(d: _EntryTypeIn) -> _EntryTypeOut: ... diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index e7bef5f29f46..b4076e686561 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -1134,7 +1134,7 @@ class FontManager: # Increment this version number whenever the font cache data # format or behavior has changed and requires an existing font # cache files to be rebuilt. - __version__ = '3.11.0a2' + __version__ = '3.11.0a3' def __init__(self, size=None, weight='normal'): self._version = self.__version__ diff --git a/lib/matplotlib/mpl-data/fonts/afm/cmti10.afm b/lib/matplotlib/mpl-data/fonts/afm/cmti10.afm new file mode 100644 index 000000000000..ac9e89f676b8 --- /dev/null +++ b/lib/matplotlib/mpl-data/fonts/afm/cmti10.afm @@ -0,0 +1,333 @@ +StartFontMetrics 2.0 +FontName cmti10 +FullName cmti10 +FamilyName cmti10 +Weight Medium +ItalicAngle 0.000000 +IsFixedPitch false +UnderlinePosition -133 +UnderlineThickness 20 +Version 1.1/12-Nov-94 +FontBBox -35, -250, 1125, 750 +Notice Copyright \(C\) 1994, Basil K. Malyshev. All Rights Reserved.\nBaKoMa Fonts Collection, Level-B. +EncodingScheme FontSpecific +CapHeight 683 +XHeight 431 +Descender -194 +Ascender 694 +StartCharMetrics 129 +C 0 ; WX 627.22 ; N Gamma ; B 59 0 706 683 ; +C 1 ; WX 817.78 ; N Delta ; B 70 0 752 716 ; +C 2 ; WX 766.67 ; N Theta ; B 148 -22 788 705 ; +C 3 ; WX 692.22 ; N Lambda ; B 58 0 643 716 ; +C 4 ; WX 664.44 ; N Xi ; B 75 0 755 683 ; +C 5 ; WX 743.33 ; N Pi ; B 59 0 854 683 ; +C 6 ; WX 715.56 ; N Sigma ; B 80 0 782 683 ; +C 7 ; WX 766.67 ; N Upsilon ; B 213 0 833 705 ; +C 8 ; WX 715.56 ; N Phi ; B 158 0 729 683 ; +C 9 ; WX 766.67 ; N Psi ; B 211 0 825 683 ; +C 10 ; WX 715.56 ; N Omega ; B 100 0 759 705 ; +C 11 ; WX 613.33 ; N ff ; B -25 -205 758 705 ; L i ffi ; L l ffl ; +C 12 ; WX 562.22 ; N fi ; B -25 -205 597 705 ; +C 13 ; WX 587.78 ; N fl ; B -25 -205 639 705 ; +C 14 ; WX 881.67 ; N ffi ; B -25 -205 917 705 ; +C 15 ; WX 894.44 ; N ffl ; B -25 -205 945 705 ; +C 16 ; WX 306.67 ; N dotlessi ; B 81 -11 334 442 ; +C 17 ; WX 332.22 ; N dotlessj ; B -35 -205 322 442 ; +C 18 ; WX 511.11 ; N grave ; B 291 503 433 696 ; +C 19 ; WX 511.11 ; N acute ; B 339 503 551 696 ; +C 20 ; WX 511.11 ; N caron ; B 279 505 538 633 ; +C 21 ; WX 511.11 ; N breve ; B 280 521 567 694 ; +C 22 ; WX 511.11 ; N macron ; B 232 555 566 589 ; +C 23 ; WX 831.28 ; N ring ; B 476 541 670 716 ; +C 24 ; WX 460 ; N cedilla ; B 99 -194 338 0 ; +C 25 ; WX 536.67 ; N germandbls ; B -20 -205 578 705 ; +C 26 ; WX 715.56 ; N ae ; B 90 -11 721 442 ; +C 27 ; WX 715.56 ; N oe ; B 106 -15 721 446 ; +C 28 ; WX 511.11 ; N oslash ; B 66 -109 553 540 ; +C 29 ; WX 882.78 ; N AE ; B 59 0 949 683 ; +C 30 ; WX 985 ; N OE ; B 162 -22 1051 705 ; +C 31 ; WX 766.67 ; N Oslash ; B 120 -62 818 745 ; +C 32 ; WX 255.56 ; N polishlcross ; B 91 280 345 393 ; +C 33 ; WX 306.67 ; N exclam ; B 111 0 376 716 ; L quoteleft exclamdown ; +C 34 ; WX 514.44 ; N quotedblright ; B 176 390 520 694 ; +C 35 ; WX 817.78 ; N numbersign ; B 115 -194 828 694 ; +C 36 ; WX 769.11 ; N dollar ; B 88 -11 698 709 ; +C 37 ; WX 817.78 ; N percent ; B 145 -56 847 750 ; +C 38 ; WX 766.67 ; N ampersand ; B 127 -22 803 716 ; +C 39 ; WX 306.67 ; N quoteright ; B 218 390 375 694 ; L quoteright quotedblright ; +C 40 ; WX 408.89 ; N parenleft ; B 150 -250 517 750 ; +C 41 ; WX 408.89 ; N parenright ; B 17 -250 384 750 ; +C 42 ; WX 511.11 ; N asterisk ; B 195 319 584 750 ; +C 43 ; WX 766.67 ; N plus ; B 140 -57 753 557 ; +C 44 ; WX 306.67 ; N comma ; B 72 -194 226 110 ; +C 45 ; WX 357.78 ; N hyphen ; B 85 185 340 245 ; L hyphen endash ; +C 46 ; WX 306.67 ; N period ; B 111 0 224 110 ; +C 47 ; WX 511.11 ; N slash ; B 20 -250 617 750 ; +C 48 ; WX 511.11 ; N zero ; B 115 -22 556 666 ; +C 49 ; WX 511.11 ; N one ; B 115 0 463 666 ; +C 50 ; WX 511.11 ; N two ; B 82 -22 551 666 ; +C 51 ; WX 511.11 ; N three ; B 95 -22 562 666 ; +C 52 ; WX 511.11 ; N four ; B 44 -194 475 666 ; +C 53 ; WX 511.11 ; N five ; B 107 -22 567 666 ; +C 54 ; WX 511.11 ; N six ; B 120 -22 567 666 ; +C 55 ; WX 511.11 ; N seven ; B 142 -22 628 666 ; +C 56 ; WX 511.11 ; N eight ; B 97 -22 554 666 ; +C 57 ; WX 511.11 ; N nine ; B 105 -22 553 666 ; +C 58 ; WX 306.67 ; N colon ; B 111 0 305 431 ; +C 59 ; WX 306.67 ; N semicolon ; B 72 -194 305 431 ; +C 60 ; WX 306.67 ; N exclamdown ; B 57 -216 322 500 ; +C 61 ; WX 766.67 ; N equal ; B 115 133 776 367 ; +C 62 ; WX 511.11 ; N questiondown ; B 85 -216 442 500 ; +C 63 ; WX 511.11 ; N question ; B 194 0 551 716 ; L quoteleft questiondown ; +C 64 ; WX 766.67 ; N at ; B 151 -11 789 705 ; +C 65 ; WX 743.33 ; N A ; B 58 0 693 716 ; +C 66 ; WX 703.89 ; N B ; B 62 0 734 683 ; +C 67 ; WX 715.56 ; N C ; B 150 -22 813 705 ; +C 68 ; WX 755 ; N D ; B 60 0 775 683 ; +C 69 ; WX 678.33 ; N E ; B 59 0 744 683 ; +C 70 ; WX 652.78 ; N F ; B 59 0 732 683 ; +C 71 ; WX 773.61 ; N G ; B 150 -22 813 705 ; +C 72 ; WX 743.33 ; N H ; B 59 0 854 683 ; +C 73 ; WX 385.56 ; N I ; B 55 0 503 683 ; +C 74 ; WX 525 ; N J ; B 90 -22 622 683 ; +C 75 ; WX 768.89 ; N K ; B 59 0 860 683 ; +C 76 ; WX 627.22 ; N L ; B 59 0 626 683 ; +C 77 ; WX 896.67 ; N M ; B 63 0 1004 683 ; +C 78 ; WX 743.33 ; N N ; B 59 0 854 683 ; +C 79 ; WX 766.67 ; N O ; B 148 -22 788 705 ; +C 80 ; WX 678.33 ; N P ; B 60 0 730 683 ; +C 81 ; WX 766.67 ; N Q ; B 148 -194 788 705 ; +C 82 ; WX 729.44 ; N R ; B 60 -22 723 683 ; +C 83 ; WX 562.22 ; N S ; B 74 -22 633 705 ; +C 84 ; WX 715.56 ; N T ; B 175 0 808 683 ; +C 85 ; WX 743.33 ; N U ; B 200 -22 854 683 ; +C 86 ; WX 743.33 ; N V ; B 208 -22 868 683 ; +C 87 ; WX 998.89 ; N W ; B 207 -22 1125 683 ; +C 88 ; WX 743.33 ; N X ; B 50 0 825 683 ; +C 89 ; WX 743.33 ; N Y ; B 201 0 875 683 ; +C 90 ; WX 613.33 ; N Z ; B 79 0 704 683 ; +C 91 ; WX 306.67 ; N bracketleft ; B 73 -250 446 750 ; +C 92 ; WX 514.44 ; N quotedblleft ; B 265 390 609 694 ; +C 93 ; WX 306.67 ; N bracketright ; B -14 -250 359 750 ; +C 94 ; WX 511.11 ; N circumflex ; B 264 533 524 694 ; +C 95 ; WX 306.67 ; N dotaccent ; B 251 559 364 669 ; +C 96 ; WX 306.67 ; N quoteleft ; B 204 390 361 694 ; L quoteleft quotedblleft ; +C 97 ; WX 511.11 ; N a ; B 107 -11 538 442 ; +C 98 ; WX 460 ; N b ; B 113 -11 461 694 ; +C 99 ; WX 460 ; N c ; B 108 -11 470 442 ; +C 100 ; WX 511.11 ; N d ; B 107 -11 562 694 ; +C 101 ; WX 460 ; N e ; B 112 -11 468 442 ; +C 102 ; WX 306.67 ; N f ; B -25 -205 452 705 ; L i fi ; L f ff ; L l fl ; +C 103 ; WX 460 ; N g ; B 51 -205 489 442 ; +C 104 ; WX 511.11 ; N h ; B 74 -11 538 694 ; +C 105 ; WX 306.67 ; N i ; B 81 -11 334 656 ; +C 106 ; WX 306.67 ; N j ; B -35 -205 359 656 ; +C 107 ; WX 460 ; N k ; B 74 -11 501 694 ; +C 108 ; WX 255.56 ; N l ; B 92 -11 308 694 ; +C 109 ; WX 817.78 ; N m ; B 81 -11 845 442 ; +C 110 ; WX 562.22 ; N n ; B 81 -11 589 442 ; +C 111 ; WX 511.11 ; N o ; B 108 -11 511 442 ; +C 112 ; WX 511.11 ; N p ; B 12 -194 512 442 ; +C 113 ; WX 460 ; N q ; B 107 -194 499 442 ; +C 114 ; WX 421.67 ; N r ; B 81 -11 488 442 ; +C 115 ; WX 408.89 ; N s ; B 76 -11 419 442 ; +C 116 ; WX 332.22 ; N t ; B 90 -11 373 626 ; +C 117 ; WX 536.67 ; N u ; B 81 -11 564 442 ; +C 118 ; WX 460 ; N v ; B 81 -11 492 443 ; +C 119 ; WX 664.44 ; N w ; B 81 -11 696 443 ; +C 120 ; WX 463.89 ; N x ; B 55 -11 517 442 ; +C 121 ; WX 485.56 ; N y ; B 81 -205 517 442 ; +C 122 ; WX 408.89 ; N z ; B 60 -11 465 442 ; +C 123 ; WX 511.11 ; N endash ; B 92 253 552 279 ; L hyphen emdash ; +C 124 ; WX 1022.22 ; N emdash ; B 118 253 1037 279 ; +C 125 ; WX 511.11 ; N hungarumlaut ; B 267 505 576 697 ; +C 126 ; WX 511.11 ; N tilde ; B 248 565 572 668 ; +C 127 ; WX 511.11 ; N dieresis ; B 268 565 552 669 ; +C -1 ; WX 357.78 ; N space ; B 357 0 358 0 ; +EndCharMetrics +StartKernData +StartKernPairs 180 +KPX A C -25.56 +KPX A G -25.56 +KPX A O -25.56 +KPX A Q -25.56 +KPX A T -76.67 +KPX A U -25.56 +KPX A V -102.22 +KPX A W -102.22 +KPX A Y -76.67 +KPX A a -51.11 +KPX A b -25.56 +KPX A c -51.11 +KPX A d -51.11 +KPX A e -51.11 +KPX A g -51.11 +KPX A h -25.56 +KPX A i -25.56 +KPX A k -25.56 +KPX A l -25.56 +KPX A m -25.56 +KPX A n -25.56 +KPX A o -51.11 +KPX A q -51.11 +KPX A r -25.56 +KPX A t -25.56 +KPX A u -25.56 +KPX A v -25.56 +KPX A w -25.56 +KPX D A -25.56 +KPX D V -25.56 +KPX D W -25.56 +KPX D X -25.56 +KPX D Y -25.56 +KPX F A -102.22 +KPX F C -25.56 +KPX F G -25.56 +KPX F O -25.56 +KPX F Q -25.56 +KPX F a -76.67 +KPX F e -76.67 +KPX F o -76.67 +KPX F r -76.67 +KPX F u -76.67 +KPX K C -25.56 +KPX K G -25.56 +KPX K O -25.56 +KPX K Q -25.56 +KPX L T -76.67 +KPX L V -102.22 +KPX L W -102.22 +KPX L Y -76.67 +KPX L a -51.11 +KPX L c -51.11 +KPX L d -51.11 +KPX L e -51.11 +KPX L g -51.11 +KPX L o -51.11 +KPX L q -51.11 +KPX O A -25.56 +KPX O V -25.56 +KPX O W -25.56 +KPX O X -25.56 +KPX O Y -25.56 +KPX P A -76.67 +KPX R C -25.56 +KPX R G -25.56 +KPX R O -25.56 +KPX R Q -25.56 +KPX R T -76.67 +KPX R U -25.56 +KPX R V -102.22 +KPX R W -102.22 +KPX R Y -76.67 +KPX R a -51.11 +KPX R b -25.56 +KPX R c -51.11 +KPX R d -51.11 +KPX R e -51.11 +KPX R g -51.11 +KPX R h -25.56 +KPX R i -25.56 +KPX R k -25.56 +KPX R l -25.56 +KPX R m -25.56 +KPX R n -25.56 +KPX R o -51.11 +KPX R q -51.11 +KPX R r -25.56 +KPX R t -25.56 +KPX R u -25.56 +KPX R v -25.56 +KPX R w -25.56 +KPX T A -76.67 +KPX T a -76.67 +KPX T e -76.67 +KPX T o -76.67 +KPX T r -76.67 +KPX T u -76.67 +KPX T y -76.67 +KPX V A -102.22 +KPX V C -25.56 +KPX V G -25.56 +KPX V O -25.56 +KPX V Q -25.56 +KPX V a -76.67 +KPX V e -76.67 +KPX V o -76.67 +KPX V r -76.67 +KPX V u -76.67 +KPX W A -76.67 +KPX X C -25.56 +KPX X G -25.56 +KPX X O -25.56 +KPX X Q -25.56 +KPX Y A -76.67 +KPX Y a -76.67 +KPX Y e -76.67 +KPX Y o -76.67 +KPX Y r -76.67 +KPX Y u -76.67 +KPX b a -51.11 +KPX b c -51.11 +KPX b d -51.11 +KPX b e -51.11 +KPX b g -51.11 +KPX b o -51.11 +KPX b q -51.11 +KPX c a -51.11 +KPX c c -51.11 +KPX c d -51.11 +KPX c e -51.11 +KPX c g -51.11 +KPX c o -51.11 +KPX c q -51.11 +KPX d l 51.11 +KPX e a -51.11 +KPX e c -51.11 +KPX e d -51.11 +KPX e e -51.11 +KPX e g -51.11 +KPX e o -51.11 +KPX e q -51.11 +KPX f bracketright 104.31 +KPX f exclam 104.31 +KPX f parenright 104.31 +KPX f question 104.31 +KPX f quoteright 104.31 +KPX ff bracketright 104.31 +KPX ff exclam 104.31 +KPX ff parenright 104.31 +KPX ff question 104.31 +KPX ff quoteright 104.31 +KPX l l 51.11 +KPX n quoteright -102.22 +KPX o a -51.11 +KPX o c -51.11 +KPX o d -51.11 +KPX o e -51.11 +KPX o g -51.11 +KPX o o -51.11 +KPX o q -51.11 +KPX p a -51.11 +KPX p c -51.11 +KPX p d -51.11 +KPX p e -51.11 +KPX p g -51.11 +KPX p o -51.11 +KPX p q -51.11 +KPX polishlcross L -320.55 +KPX polishlcross l -255.55 +KPX quoteright exclam 102.22 +KPX quoteright question 102.22 +KPX r a -51.11 +KPX r c -51.11 +KPX r d -51.11 +KPX r e -51.11 +KPX r g -51.11 +KPX r o -51.11 +KPX r q -51.11 +KPX w l 51.11 +EndKernPairs +EndKernData +EndFontMetrics diff --git a/lib/matplotlib/mpl-data/fonts/ttf/cmti10.ttf b/lib/matplotlib/mpl-data/fonts/ttf/cmti10.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8311a98ac9e307d0f6657c27da01906c5a35ea51 GIT binary patch literal 32808 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 V(AWQ@1b_LHxCW&1Y1w8$_&?N+Z$1D3 literal 0 HcmV?d00001 diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index 4fd08aa60578..01a2f37bfd9d 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -375,10 +375,10 @@ # 'stixsans'] when a symbol cannot be found in one of the # custom math fonts. Select 'None' to not perform fallback # and replace the missing character by a dummy symbol. -#mathtext.default: it # The default font to use for math. - # Can be any of the LaTeX font names, including - # the special name "regular" for the same font - # used in regular text. +#mathtext.default: normal # The default font to use for math. + # Can be any of the LaTeX font names (normal, it, bf, + # etc.), including the special name "regular" for the + # same font used in regular text. ## *************************************************************************** diff --git a/lib/matplotlib/mpl-data/stylelib/classic.mplstyle b/lib/matplotlib/mpl-data/stylelib/classic.mplstyle index cd636d65c7c8..302a25ca29a9 100644 --- a/lib/matplotlib/mpl-data/stylelib/classic.mplstyle +++ b/lib/matplotlib/mpl-data/stylelib/classic.mplstyle @@ -162,10 +162,10 @@ mathtext.fallback: cm # Select fallback font from ['cm' (Computer Modern), 'sti # custom math fonts. Select 'None' to not perform fallback # and replace the missing character by a dummy. -mathtext.default : it # The default font to use for math. - # Can be any of the LaTeX font names, including - # the special name "regular" for the same font - # used in regular text. +mathtext.default: normal # The default font to use for math. + # Can be any of the LaTeX font names (normal, it, bf, + # etc.), including the special name "regular" for the + # same font used in regular text. ### AXES # default face and edge color, default tick sizes, diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index f70697fdab45..4d0d2ccf89be 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -1093,7 +1093,7 @@ def _convert_validator_spec(key, conv): "mathtext.fontset": ["dejavusans", "dejavuserif", "cm", "stix", "stixsans", "custom"], "mathtext.default": ["rm", "cal", "bfit", "it", "tt", "sf", "bf", "default", - "bb", "frak", "scr", "regular"], + "bb", "frak", "scr", "regular", "normal"], "mathtext.fallback": _validate_mathtext_fallback, "image.aspect": validate_aspect, # equal, auto, a number @@ -1886,9 +1886,9 @@ class _Param: "math fonts. Select 'None' to not perform fallback and replace the " "missing character by a dummy symbol." ), - _Param("mathtext.default", "it", + _Param("mathtext.default", "normal", ["rm", "cal", "bfit", "it", "tt", "sf", "bf", "default", "bb", "frak", "scr", - "regular", ], + "regular", "normal"], description='The default font to use for math. Can be any of the LaTeX font ' 'names, including the special name "regular" for the same font ' 'used in regular text.', From 77d4e52f5b96f257903405e17a7ae22ba2ef552b Mon Sep 17 00:00:00 2001 From: Leon Merten Lohse Date: Thu, 26 Feb 2026 13:57:50 +0100 Subject: [PATCH 3/3] Add test case for mathnormal Ensure that \mathnormal is parsed and sets digits upright. --- lib/matplotlib/tests/test_mathtext.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py index 46cc253ad945..51963bd590cc 100644 --- a/lib/matplotlib/tests/test_mathtext.py +++ b/lib/matplotlib/tests/test_mathtext.py @@ -571,6 +571,13 @@ def test_boldsymbol(fig_test, fig_ref): fig_ref.text(0.1, 0.2, r"$\mathrm{abc0123\alpha}$") +@check_figures_equal() +def test_mathnormal(fig_test, fig_ref): + # ensure that \mathnormal is parsed and sets digits upright + fig_test.text(0.1, 0.2, r"$\mathnormal{0123456789}$") + fig_ref.text(0.1, 0.2, r"$\mathrm{0123456789}$") + + def test_box_repr(): s = repr(_mathtext.Parser().parse( r"$\frac{1}{2}$",