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 b6cdb1fa6e8e..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 @@ -341,6 +342,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 +424,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 +435,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: @@ -474,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', @@ -497,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) @@ -551,6 +562,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): """ @@ -630,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 @@ -651,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' @@ -663,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], " @@ -741,6 +758,9 @@ class DejaVuSerifFonts(DejaVuFonts): 0: 'DejaVu Serif', } + def get_font_constants(self) -> type[FontConstantsBase]: + return DejaVuSerifFontConstants + class DejaVuSansFonts(DejaVuFonts): """ @@ -759,6 +779,9 @@ class DejaVuSansFonts(DejaVuFonts): 0: 'DejaVu Sans', } + def get_font_constants(self) -> type[FontConstantsBase]: + return DejaVuSansFontConstants + class StixFonts(UnicodeFonts): """ @@ -842,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 @@ -874,6 +897,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 +1107,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.""" @@ -1896,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 @@ -2068,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 @@ -2325,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] @@ -2344,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) @@ -2649,7 +2640,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 +2734,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): 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 000000000000..8311a98ac9e3 Binary files /dev/null and b/lib/matplotlib/mpl-data/fonts/ttf/cmti10.ttf differ 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.', 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}$",