GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — mathtext: add support for unicode mathematics fonts by llohse · Pull Request #31048 · matplotlib/matplotlib

Conversation

@llohse

@llohse llohse commented Jan 29, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Add basic support for generic unicode OpenType/TrueType mathematics fonts such as STIX Two Math, Cambria Math, DejaVu Math, etc.

Currently, mathematics text rendering through mathtext in matplotlib supports a hard-coded number of fonts (configured via mathtext.fontset). Its design presumably predates the specification of mathematics alphabets in the unicode standard. While it is possible to configure custom fonts (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 mathematics fonts are designed.

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.
One relatively modern way to render mathematical formulas uses mathematics fonts such as STIX Two Math or Cambria Math, Asana Math, etc.. For LaTeX, this is implemented in the unicode-math package.
Instead of choosing a font based on the style (as it is currently done in matplotlib) to render the same codepoints, this maps alphanumeric characters to different codepoints based on the style, and render them from a single font.

Shortcomings of the status quo:

  • It is not currently possible to use modern mathematics fonts when using mathtext for rendering of mathematical equations in matplotlib. Consequently, it is difficult to configure fonts that are visually consistent and may require the use of latex rendering.
  • Font configuration may be perceived as somewhat complicated
  • The mathtext codebase and font selection logic is relatively complex and inaccessible, with all the hardcoded fonts, fixes for their quirks, and fallbacks

This change implements functionality to use any installed unicode Opentype/Truetype mathematics fonts for use in mathtext in a portable way. Currently, this can be enabled by setting the rcparams

mathtext.fontset: unicodemath
mathtext.mathfont: STIX Two Math # or any other font name that can be loaded by fontmanager

I could think of different ways to configure this, though.

Internally, I have implemented a separate class UnicodeMathFonts(TruetypeFonts) to no interfere with the existing fontsets.

Running the test currently requires STIX Two Math to be installed on the system. For that reason, I have added it to the test data. One may think about vendoring STIX Two Math or DejaVu Math via mpl-data instead.

Examples

import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.rcParams['mathtext.fontset'] = 'unicodemath'

font_names = ['STIX Two Math', 'TeX Gyre Pagella Math', 'TeX Gyre Schola Math', 'Noto Sans Math', 'Latin Modern Math', 'TeX Gyre DejaVu Math']

for font in font_names:
    with mpl.rc_context({'mathtext.mathfont' : font}):
        fig = plt.figure(figsize=(3, 1.5), dpi=150)
        fig.suptitle(f'{font}')
        fig.text(.1, .2, r'$\frac{1}{2 \pi \mathrm{i}} \int_{\partial G} f(z) \mathrm{d}z = \sum_{\nu = 1}^n \left(\mathrm{res} f\right)(z_\nu)$')
        fig.text(.1, .45, r'$\bigcup_{i \in I} A_i := \left\{ x \mid \bigvee_i\left( i \in I \wedge x \in A_i\right)\right\}$')
        fig.text(.1, .7, r'$\mathbb{Q} = \left. \left(\mathbb{Z} \times \mathbb{Z} \setminus \{ 0\} \right) \right/ \sim $')
        fig.tight_layout()
        fig.savefig(f'{font}.png')
Latin Modern Math Noto Sans Math STIX Two Math TeX Gyre DejaVu Math TeX Gyre Schola Math

PR checklist

  • "closes #0000" is in the body of the PR description to link the related issue
  • new and changed code is tested
  • Plotting related features are demonstrated in an example
  • New Features and API Changes are noted with a directive and release note
  • Documentation complies with general and docstring guidelines

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

anntzer reacted with hooray emoji
All reactions
  • 🎉 1 reaction
@github-actions github-actions Bot added topic: rcparams topic: text/mathtext labels Jan 29, 2026
@llohse
llohse marked this pull request as draft January 29, 2026 12:29
@llohse
llohse marked this pull request as ready for review January 29, 2026 12:57
@llohse
llohse force-pushed the mathtext-unicode branch from c465e4c to 66dffff Compare January 29, 2026 13:02
anntzer
anntzer reviewed Jan 29, 2026
View reviewed changes
Comment thread lib/matplotlib/_mathtext.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@llohse
llohse force-pushed the mathtext-unicode branch from e942825 to 3bccb55 Compare January 29, 2026 16:46
@QuLogic

QuLogic commented Jan 29, 2026

Copy link
Copy Markdown
Member

This is very interesting, though I have not looked into the implementation details. Do these Unicode math fonts cover symbols like integrals, etc.? The test images so far don't cover those, so I would guess not?

Also, these test images should either wait for #30161 or base the PR on it, as they all exhibit the wobbly baseline problem from the old text layout algorithm.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@llohse

llohse commented Jan 30, 2026

Copy link
Copy Markdown
Contributor Author

This is very interesting, though I have not looked into the implementation details. Do these Unicode math fonts cover symbols like integrals, etc.? The test images so far don't cover those, so I would guess not?

Thanks. Absolutely. They include all glyphs that are relevant for mathematics typesetting. "Modern" LaTeX typestting with unicode-math exclusively uses glyphs and metadata from the otf font files. In the future, one may consider to read the MATH table instead of using hard-coded FontConstant values.
Please take a look at the example images that I provided in the PR description.
I would welcome any advice on how to lay out the tests. In particular, they require at least one mathematics font to be present. Does it make sense to vendor STIX Two Math, either in mpl-data or in the test data? Alternatively, DejaVu Math (since DejaVu seems to be the default in matplotlib).

Also, these test images should either wait for #30161 or base the PR on it, as they all exhibit the wobbly baseline problem from the old text layout algorithm.

Makes sense. I'll try to rebase to it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@llohse

llohse commented Jan 30, 2026

Copy link
Copy Markdown
Contributor Author

@QuLogic I merged the changes into a new branch based on #30161 here: https://github.com/llohse/matplotlib/tree/mathtext-unicode-textoverhaul

Should I update this PR somehow?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@llohse llohse mentioned this pull request Feb 2, 2026
ft2font: Extend OS/2 table with new fields #31050
Merged
1 task done
@llohse
llohse changed the base branch from main to text-overhaul February 3, 2026 08:20
@llohse
llohse force-pushed the mathtext-unicode branch from 3bccb55 to e123ef0 Compare February 3, 2026 08:20
@github-actions github-actions Bot added topic: text topic: widgets/UI GUI: tk topic: pyplot API topic: toolbar topic: styles Documentation: build building the docs CI: Run cygwin Run cygwin tests on a PR Documentation: examples files in galleries/examples Documentation: devdocs files in doc/devel Documentation: user guide files in galleries/users_explain or doc/users labels Feb 3, 2026
dependabot Bot and others added 6 commits February 3, 2026 09:22
@dependabot @llohse
Bump the actions group across 1 directory with 2 updates
9b725bd
Bumps the actions group with 2 updates in the / directory: [github/codeql-action](https://github.com/github/codeql-action) and [actions/cache](https://github.com/actions/cache).


Updates `github/codeql-action` from 4.31.9 to 4.31.10
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@5d4e8d1...cdefb33)

Updates `actions/cache` from 5.0.1 to 5.0.2
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@9255dc7...8b402f5)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/cache
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <[email protected]>
@anntzer @llohse
Remove outdated notion of property alias priority from docs.
b9a5ae5
The concept of alias priority was deprecated in 71d725f and has been
removed since then (making normalize_kwargs maintain kwarg order).
@bodhisilberling @llohse
Fix grammar: 'it would better' -> 'it would be better' in comment
5953dd1
@story645 @llohse
reorg docs to remove misc section, consolidate and cleanup file struc…
ec04898
…ture info
@doronbehar @llohse
widgets.pyi: Add missing RadioButtons.index_selected type hint
ed0f0f6
@doronbehar @llohse
CheckButtons: rename _checks to _buttons
e42b312
For more consistency and similarity with RadioButtons
doronbehar and others added 19 commits February 3, 2026 09:22
@doronbehar @llohse
*Buttons: use a shared _Buttons class
37aa7f8
Share all the trivial functions which are identical without any further
modifications.
@doronbehar @llohse
*Buttons: use a semi-public self._buttons_ys variable
cdc231f
@doronbehar @llohse
*Buttons: share more __init__ functionality
81b2196
@bodhisilberling @llohse
Fix formatting: add space after # in TODO comment
9aae0a8
@story645 @llohse
move doc build options into tables and tabs
0be344d
@QuLogic @llohse
Remove mutable defaults from tool manager functions
fce26f5
This is generally frowned upon (though we don't actually change it, so
it's safe), but more importantly, Sphinx tries to put all the values
into the docstring, which just looks bad.
@QuLogic @llohse
DOC: Use the old class-based autodoc with Sphinx 9
e721843
The new version appears to be causing some issues for our missing
reference checks, so reverting back to the old implementation should buy
us some time to fix things.
@QuLogic @llohse
DOC: Fix cross-references to new _Buttons class
71b6bf2
@larrybradley @timhoffm @llohse
FIX: Handle AxesWidget cleanup after failed init (matplotlib#30935)
deec641
* FIX: Handle AxesWidget cleanup after failed init

* Apply code review suggestions

* Update lib/matplotlib/tests/test_widgets.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Remove __del__ method

* Remove AxesWidget.__del__ from widgets.pyi

---------

Co-authored-by: Tim Hoffmann <[email protected]>
@QuLogic @llohse
TST: Fix warnings from Pillow for unavailable features
f17ca37
If Pillow is old enough to not support a feature _at all_, then it will
warn about it. If you're running the whole test suite, then something
else seems to cause pytest to treat it as benign. But if you run only
`test_agg.py`, then our `-Werror` setting will cause it to fail test
collection.
@anntzer @llohse
Speedup normalize_kwargs by storing aliases in a more practical format.
9387f36
Directly store property alias information in `{"alias": "propety", ...}`
format, which greatly speeds up normalize_kwargs.

In order to not worry about two different dict formats (the new one, and
the old one, which was `{"property": ["alias", ...], ...}`) in
normalize_kwargs, deprecate support for directly passing an alias map --
callers should always pass an artist (or artist type) directly, which
hides the detail of the format of the alias map.  Also deprecate passing
`alias_mapping=None`, which doesn't really seem needed (unlike
`kw=None`, which is regularly used).

Whether the format of aliases passed to `_api.define_aliases` should
also be changed to match the new format is a separate question that
doesn't have to be addressed here (it can be changed later, being fully
private anyways).
@hasanrashid
@timhoffm @rcomer @llohse
Improving error message for width and position type mismatch in viol…
6361f6f
…inplot (matplotlib#30752)

* Improving error message for width and position type mismatch in violinplot

* Improving error message for width and position type mismatch in violinplot

* Fix violin plot statistics in test data

* Trigger CI pipeline

* Trigger CI pipeline

* Update lib/matplotlib/axes/_axes.py

Co-authored-by: Copilot <[email protected]>

* Update lib/matplotlib/axes/_axes.py

Co-authored-by: Copilot <[email protected]>

* Update lib/matplotlib/tests/test_axes.py

Co-authored-by: Copilot <[email protected]>

* Store original widths parameter before conversion for accurate type validation
- Improve pytest match strings with proper line continuation formatting
- Enhanced error messages provide clear examples for correct usage

* Update lib/matplotlib/axes/_axes.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Update lib/matplotlib/axes/_axes.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Remove low-information comment

Co-authored-by: Tim Hoffmann <[email protected]>

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Tim Hoffmann <[email protected]>
Co-authored-by: Ruth Comer <[email protected]>
@star1327p @llohse
DOC: Make grammatical corrections [ci doc]
6bea6f6
@vujadinovic @llohse
DOCS: Fix typo in time array step size comment
442b53a
The code uses dt=0.01 as time step but the comment said 0.02
@rcomer @llohse
DOC: bring the credits page a little more up-to-date [ci doc]
4460ed3
This page has not been updated since June 2020.  Getting it up to
date would require a lot of manual intervention in the mailmap, so
I propose to do it in batches.  This change adds new contributors
up to 0b61e32.
@sanrishi @llohse
Add type hint for fig_kw in subplots (matplotlib#31033)
90dd742
Fixes matplotlib#31003
@llohse
mathtext: add support for unicode mathematics fonts
6b499a4
Adds support for generic unicode OpenType/TrueType mathematics fonts such as STIX Two Math, Cambria Math,
@llohse
bundle STIX Two Math in tests
3d98533
@llohse
inline _is_digit, etc.
d8bf6d2
@llohse
llohse force-pushed the mathtext-unicode branch from e123ef0 to d8bf6d2 Compare February 3, 2026 08:22
@llohse

llohse commented Feb 3, 2026

Copy link
Copy Markdown
Contributor Author

... I messed up by changing the target branch. Apologies.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@llohse
llohse marked this pull request as draft February 3, 2026 08:24
@llohse llohse closed this Feb 3, 2026
@llohse llohse mentioned this pull request Feb 3, 2026
mathtext: add support for unicode mathematics fonts #31064
Open
5 tasks
@QuLogic QuLogic added the status: duplicate label Feb 3, 2026
@QuLogic QuLogic mentioned this pull request Feb 3, 2026
Implement TeX's fraction and script alignment #31046
Merged
2 of 5 tasks
@scottshambaugh scottshambaugh added the status: superseded label Feb 3, 2026
@QuLogic QuLogic mentioned this pull request Mar 12, 2026
text: Use font metrics to determine line heights #31291
Merged
1 of 5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@anntzer anntzer anntzer left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

CI: Run cygwin Run cygwin tests on a PR Documentation: build building the docs Documentation: devdocs files in doc/devel Documentation: examples files in galleries/examples Documentation: user guide files in galleries/users_explain or doc/users GUI: tk status: duplicate status: superseded topic: pyplot API topic: rcparams topic: styles topic: text/mathtext topic: text topic: toolbar topic: widgets/UI

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

13 participants

@llohse @QuLogic @anntzer @scottshambaugh @bodhisilberling @story645 @doronbehar @larrybradley @hasanrashid @star1327p @vujadinovic @rcomer @sanrishi
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.