When rendering mathematical equations, matplotlib currently only supports a hard-coded number of fonts (configured via mathtext.fontset). While it is possible to configure custom fonts (via mathtext.fontset: custom), this requires to set separate fonts for upright, italic, fraktur, double-struck, etc. variants -- which is fundamentally incompatible with the way modern OpenType mathematics fonts are designed.
The current approach has several shortcomings:
It is not generally possible to use consistent fonts for text and mathematics (except for special cases covered by the hard-coded options). Think of matching the fonts for a textbook (using STIX Two,Minion, ...) or in a slide show (Cambria)
The UX of configuring fonts is inconsistent and somewhat counter intuitive.
(The mathtext codebase and font selection logic is relatively complex and inaccessible, with all the hardcoded fonts, fixes for their quirks, and fallbacks for missing symbols).
Unicode defines mathematical alphanumeric symbols as unique codepoints (see https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols), in contrast to different fonts all defining different styles for the same ASCII characters/codepoints.
Mathematical formulas can be rendered with OpenType mathematics fonts such as STIX Two Math, Cambria Math, or Latin Modern Math, etc.. For modern LaTeX (LuaTeX and XeTeX), this is implemented in the unicode-math package.
Instead of using different fonts based on the style to render the same codepoints (as it is currently implemented in matplotlib), this maps alphanumeric characters to different codepoints based on the style, and render them from a single font.
Since there is a major overhaul of matplotlib's text rendering currently under way (#30161), I thought now is a good time to bring this up.
Proposed solution
I propose to add support for OpenType mathematics fonts. Basic support is introduced in PR #31064 . The implementation is inspired by the unicode-math package for LaTeX.
This enables to configure and use arbitrary OpenType mathematics fonts to
match text and math fonts with the surrounding document
makes the UX more consistent
What do you think of this idea in general?
There are some open design questions:
How should the fonts be configured?
How to do unit tests? This may require vendoring at least one OpenType mathematics font. Currently, I have added STIX Two Math to the test data.
The next logical steps would be (i) to make use of the font metrics from the MATH tables instead of using default values (ii) support scaled variants of symbols.
It's definitely something more future-looking and that we'd like to do.
* How should the fonts be configured?
What you have in your PR seems straightforward, but I'll let @timhoffm make any final judgement.
* How to do unit tests? This may require vendoring at least one OpenType mathematics font. Currently, I have added STIX Two Math to the test data.
It's a bit large and we may want to subset it, but on the other hand, if we add test images that match all our other mathtext, then that might dwarf the problem. I'm unsure what we want to do there given we haven't split out the test images yet.
Support for unicode math would be really nice to have.
Re: configuration: I'm not sure I really like having one rcparam (mathtext.fontset) which, when set to a specific value (unicodemath), effectively forwards to another rcparam (mathtext.customfont), with the latter being effectively useless when mathtext.fontset has any other value. Indeed, it's similar to what's happening right now with mathtext.{bf,it,...}, which are unused except specifically when mathtext.fontset = custom. Perhaps a slightly nicer interface would be to support e.g. rcParams["mathtext.fontset"] = "custom:STIX Two Math" where the "custom:" prefix means "strip the prefix and use the rest as math font specification" (remove the quotes for matplotlibrc syntax, as usual). OTOH this isn't really a big deal and I'm happy to defer to @timhoffm here.
OTOH one thing that may be nice to check is that the syntax is ultimately extensible to support TeX's unicode-math's font setup capabilities (even if they are not supported right now). e.g.
Support for unicode math would be really nice to have.
Re: configuration: I'm not sure I really like having one rcparam (mathtext.fontset) which, when set to a specific value (unicodemath), effectively forwards to another rcparam (mathtext.customfont), with the latter being effectively useless when mathtext.fontset has any other value. Indeed, it's similar to what's happening right now with mathtext.{bf,it,...}, which are unused except specifically when mathtext.fontset = custom. Perhaps a slightly nicer interface would be to support e.g. rcParams["mathtext.fontset"] = "custom:STIX Two Math" where the "custom:" prefix means "strip the prefix and use the rest as math font specification" (remove the quotes for matplotlibrc syntax, as usual). OTOH this isn't really a big deal and I'm happy to defer to @timhoffm here.
This would also work. Maybe the more general question is whether this is supposed to become an expert feature or something that could be made a default at some point. In the latter case, I would suggest
rcParams['font.math'] = ['TeX Gyre DejaVu Math', 'Latin Modern Math', 'STIX Two Math']
or similar. With mathtext.fontset as an option to switch to the other fonts.
OTOH one thing that may be nice to check is that the syntax is ultimately extensible to support TeX's unicode-math's font setup capabilities (even if they are not supported right now). e.g.
At least you can find quite a few posts on tex.stackexchange where people ask to use font A for some glyphs and font B for other glyphs. I'm not saying we need to support this feature now (in fact I'd rather keep things simple for the first PR getting the basics in), just that we shouldn't pick a syntax that makes that awkward to add later (and given that unicode-math already came up with a reasonably syntax, we may as well just keep it).
No strong opinion as to whether this will end up being an expert feature or not (but again, being able to point users to unicode-math's docs would be an advantage, I think).
Thank you for the explanation. Sounds good to me.
I guess we are waiting for feedback from @timhoffm then.
Allow me to add a bit of a bigger perspective here.
Having OpenType mathematics support may open the possibility to eventually replace the hardcoded fonts entirely, because OpenType MATH versions for all of them (Computer Modern, STIX, DejaVu) exist.
This would allow to unify non-math and math font configuration, but also substantially simplify the _mathtext codebase (*).
Not that I would assume the right to suggest anything like that. My current intention is about adding minimal support for OpenType mathematics fonts.
I believe that reaching feature parity with the existing solution would certainly require some work, but maybe not as much as it sounds. Similar to how XeTeX does it, one would not even have to touch the engine/parser. The two big missings parts (that I am aware of - please correct me) are
reading the MathConstants table to populate the FontConstants object used in mathtext. This could be done either via fontTools (could be slow) or harfbuzz (by extending ft2font, for example).
reading the MathVariants table to access scaled glyphs of big operators and the various brackets. Should also be possible with harfbuzz.
(*) The current implementation is super impressive: It simultaneously supports (i) legacy non-unicode LaTeX fonts (cm), (ii) a unicode mathematics font that predates the standardisation of OpenType MATH (stix 1), and (iii) a non-math unicode font (DejaVu).
Activity
QuLogic commented on Feb 7, 2026
It's definitely something more future-looking and that we'd like to do.
What you have in your PR seems straightforward, but I'll let @timhoffm make any final judgement.
It's a bit large and we may want to subset it, but on the other hand, if we add test images that match all our other mathtext, then that might dwarf the problem. I'm unsure what we want to do there given we haven't split out the test images yet.
anntzer commented on Feb 7, 2026
Support for unicode math would be really nice to have.
Re: configuration: I'm not sure I really like having one rcparam (mathtext.fontset) which, when set to a specific value (unicodemath), effectively forwards to another rcparam (mathtext.customfont), with the latter being effectively useless when mathtext.fontset has any other value. Indeed, it's similar to what's happening right now with mathtext.{bf,it,...}, which are unused except specifically when mathtext.fontset = custom. Perhaps a slightly nicer interface would be to support e.g. rcParams["mathtext.fontset"] = "custom:STIX Two Math" where the "custom:" prefix means "strip the prefix and use the rest as math font specification" (remove the quotes for matplotlibrc syntax, as usual). OTOH this isn't really a big deal and I'm happy to defer to @timhoffm here.
OTOH one thing that may be nice to check is that the syntax is ultimately extensible to support TeX's unicode-math's font setup capabilities (even if they are not supported right now). e.g.
(from unicode-math's docs section 4.1.1) could map to rcParams["mathtext.fontset"] = "custom: MinionMath-Regular; MinionMath-Bold[range={bfup->up,bfit->it}]"?
llohse commented on Feb 7, 2026
This would also work. Maybe the more general question is whether this is supposed to become an expert feature or something that could be made a default at some point. In the latter case, I would suggest
or similar. With mathtext.fontset as an option to switch to the other fonts.
Interesting idea. Do you think there is a use case for such range substitutions?
anntzer commented on Feb 7, 2026
At least you can find quite a few posts on tex.stackexchange where people ask to use font A for some glyphs and font B for other glyphs. I'm not saying we need to support this feature now (in fact I'd rather keep things simple for the first PR getting the basics in), just that we shouldn't pick a syntax that makes that awkward to add later (and given that unicode-math already came up with a reasonably syntax, we may as well just keep it).
No strong opinion as to whether this will end up being an expert feature or not (but again, being able to point users to unicode-math's docs would be an advantage, I think).
llohse commented on Feb 12, 2026
Thank you for the explanation. Sounds good to me.
I guess we are waiting for feedback from @timhoffm then.
Allow me to add a bit of a bigger perspective here.
Having OpenType mathematics support may open the possibility to eventually replace the hardcoded fonts entirely, because OpenType MATH versions for all of them (Computer Modern, STIX, DejaVu) exist.
This would allow to unify non-math and math font configuration, but also substantially simplify the _mathtext codebase (*).
Not that I would assume the right to suggest anything like that. My current intention is about adding minimal support for OpenType mathematics fonts.
I believe that reaching feature parity with the existing solution would certainly require some work, but maybe not as much as it sounds. Similar to how XeTeX does it, one would not even have to touch the engine/parser. The two big missings parts (that I am aware of - please correct me) are
(*) The current implementation is super impressive: It simultaneously supports (i) legacy non-unicode LaTeX fonts (cm), (ii) a unicode mathematics font that predates the standardisation of OpenType MATH (stix 1), and (iii) a non-math unicode font (DejaVu).