Skip to content

Fix mathtext font fallback for glyphs missing from math fonts - #31766

Open
1wos wants to merge 2 commits into
matplotlib:mainfrom
1wos:mathtext-cjk-fallback
Open

1wos wants to merge 2 commits into
matplotlib:mainfrom
1wos:mathtext-cjk-fallback

Conversation

@1wos

@1wos 1wos commented May 28, 2026 •

Copy link
Copy Markdown

PR summary

Closes #29173.

Characters missing from the math fonts (e.g. CJK) were replaced by a ¤ dummy
glyph, because mathtext had no glyph-level font fallback. Regular text walks the
configured font list and its fallback chain instead.

UnicodeFonts._get_glyph now does the same before giving up: it asks the
configured text font for the font in its chain that has the glyph, via a new
private FT2Font._get_font_for_char(codepoint) (backed by a C++
FT2Font::get_font_for_char, which replaces the unused
get_char_fallback_index). Only the missing-glyph path changes, so existing
output is unaffected. The get_char_index stub also gains the _fallback
keyword the binding already had.

plt.rcParams["font.family"] = "Arial Unicode MS"  # any CJK-capable font
plt.text(0.5, 0.5, r"$\alpha + 中文 + 한글 + \beta$")

AI Disclosure

I used Claude to explore the font code and draft the implementation, tests, and
this text; I chose the approach and reviewed and tested everything locally.

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • [N/A] Plotting related features are demonstrated in an example
  • New features and API changes have release notes
  • Documentation complies with general and docstring guidelines

@github-actions

Copy link
Copy Markdown

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks. We also ask that you please finish addressing any review comments on this PR and wait for it to be merged (or closed) before opening a new one, as it can be a valuable learning experience to go through the review process.

You can also join us on discourse chat for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide.
Please let us know if (and how) you use AI, it will help us give you better feedback on your PR.

We strive to be a welcoming and open project. Please follow our Code of Conduct.

Comment thread lib/matplotlib/_mathtext.py Outdated
# https://github.com/matplotlib/matplotlib/issues/29173.
text_font = get_font(
fontManager._find_fonts_by_props(self.default_font_prop))
for fallback_font in [text_font, *text_font._fallbacks]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth pushing this logic farther up into the font object so we don't have to access private state here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. FT2Font now has a private _get_font_for_char(codepoint) that returns the font in the chain that actually has the glyph, so mathtext doesn't touch _fallbacks anymore. The unused C++ get_char_fallback_index became get_font_for_char along the way. Also rebased on main.

1wos added a commit to 1wos/matplotlib that referenced this pull request Sep 22, 2026
Instead of walking the private FT2Font._fallbacks list from mathtext,
add FT2Font._get_font_for_char(codepoint), which returns the font in the
fallback chain that has a glyph for the code point, or None.  On the C++
side it replaces the unused get_char_fallback_index helper with
get_font_for_char, which also searches nested fallback lists.

Addresses review feedback on matplotlib#31766.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
1wos added a commit to 1wos/matplotlib that referenced this pull request Sep 22, 2026
Instead of walking the private FT2Font._fallbacks list from mathtext,
add FT2Font._get_font_for_char(codepoint), which returns the font in the
fallback chain that has a glyph for the code point, or None.  On the C++
side it replaces the unused get_char_fallback_index helper with
get_font_for_char, which also searches nested fallback lists.

Addresses review feedback on matplotlib#31766.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@1wos
1wos force-pushed the mathtext-cjk-fallback branch from f33e56e to d74df12 Compare September 22, 2026 17:54
1wos added a commit to 1wos/matplotlib that referenced this pull request Sep 26, 2026
Instead of walking the private FT2Font._fallbacks list from mathtext,
add FT2Font._get_font_for_char(codepoint), which returns the font in the
fallback chain that has a glyph for the code point, or None.  On the C++
side it replaces the unused get_char_fallback_index helper with
get_font_for_char, which also searches nested fallback lists.

Addresses review feedback on matplotlib#31766.
@1wos
1wos force-pushed the mathtext-cjk-fallback branch from d74df12 to 3afb3bc Compare September 26, 2026 08:15
1wos added 2 commits October 29, 2026 08:32
Search the font's fallback chain before substituting a dummy glyph, so that e.g. CJK characters in math expressions render like they do in regular text.

Closes matplotlib#29173
Instead of walking the private FT2Font._fallbacks list from mathtext,
add FT2Font._get_font_for_char(codepoint), which returns the font in the
fallback chain that has a glyph for the code point, or None.  On the C++
side it replaces the unused get_char_fallback_index helper with
get_font_for_char, which also searches nested fallback lists.

Addresses review feedback on matplotlib#31766.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Font fallback issue with CJK characters in text containing math formulas

2 participants