Skip to content

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

Open

Description

@SomeBottle

Bug summary

I tested the font customization and fallback functionality in Matplotlib, and also tested whether this works with mathematical formulas.

However, I found that without mathematical formulas (i.e., text not containing formulas wrapped by $ $), Matplotlib handles fallback properly. For example, when I set rcParams['font.family']=['monospace', custom_font_name, 'sans-serif'], any unsupported Chinese characters in monospace will automatically fallback to custom_font_name, which refers to a custom font.

But, when math formulas are included in the text, only characters supported by monospace are rendered correctly, while Chinese characters fail to be rendered properly due to "glyph missing".

Code for reproduction

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

# Can be get from https://github.com/adobe-fonts/source-han-serif/releases/download/2.003R/14_SourceHanSerifCN.zip  
FONT_PATH = './SourceHanSerifCN-Regular.otf'  


fm.fontManager.addfont(FONT_PATH)
font_props=fm.FontProperties(fname=FONT_PATH)
font_name=font_props.get_name()
# Custom font
font_name


plt.rcParams['font.family']=['monospace', font_name, 'sans-serif']
# Set a mathtext font
plt.rcParams["mathtext.fontset"]='cm'

import numpy as np

x=np.linspace(0,10,num=1000)
y=np.sin(x)

# This works perfectly, "正弦函数" will be rendered with the custom font while other chars will be rendered with monospace
plt.xlabel('x')
plt.ylabel(r'sin(x)')
plt.title('正弦函数 Sine Function')
plt.grid()
plt.plot(x,y)

# However, "正弦函数" here won't fallback to the custom font. "Sine Function" will be rendered with monospace.
plt.xlabel('x')
plt.ylabel(r'sin(x)')
plt.title(r'正弦函数 Sine Function : '+r'$sin(x)$')
plt.grid()
plt.plot(x,y)

Actual outcome

Image produced by the first plot:
image

Image produced by the second plot:
(Note that sin(x) in the title is rendered with specified mathtext font)
image

Related warnings from output:

WARNING:matplotlib.mathtext:Font 'default' does not have a glyph for '\u6b63' [U+6b63], substituting with a dummy symbol.
WARNING:matplotlib.mathtext:Font 'default' does not have a glyph for '\u5f26' [U+5f26], substituting with a dummy symbol.
WARNING:matplotlib.mathtext:Font 'default' does not have a glyph for '\u51fd' [U+51fd], substituting with a dummy symbol.
WARNING:matplotlib.mathtext:Font 'default' does not have a glyph for '\u6570' [U+6570], substituting with a dummy symbol.

Expected outcome

I expected "正弦函数" to be rendered with my custom font in the second plot, instead of dummy symbols.

Additional information

Operating system

Ubuntu 22.04.3 LTS (Google Colab), Windows (Local machine)

Matplotlib Version

3.8.0 (Google Colab), 3.9.2 (Local machine)

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

3.10.12

Jupyter version

6.5.5

Installation

pip

Activity

  1. added this to the v3.11.0 milestone on Nov 22, 2024
  2. tacaswell commented on Nov 22, 2024

    @tacaswell
    Member

    I can reproduce this. @QuLogic We should try to fix this as part of the font SDG.

  3. QuLogic commented on Nov 26, 2024

    @QuLogic
    Member

    I don't believe mathtext ever had font fallback implemented since the initial implementation.

  4. jchliao commented on Apr 24, 2026

    @jchliao

    我写了一个库 visioplot,可以临时解决 CJK 字符在数学公式中的字体问题。

    使用方法:

    1. 安装库:

      pip install visioplot
    2. 引入库:
      在代码中引入 visioplot 并设置字体:

      import matplotlib.pyplot as plt
      import visioplot
      
      # 设置字体,首先尝试 Times New Roman,如果不支持 CJK 字符则回退到 SimSun
      plt.rcParams['font.family'] = ["Times New Roman", "SimSun"]
      
      # 你的绘图代码
      # plt.plot([1, 2, 3], [4, 5, 6])
      plt.title(r'正弦函数 $sin(x)$')
      plt.show()
  5. SomeBottle commented on Apr 24, 2026

    @SomeBottle
    Author

    @jchliao 可以试着发 Pull Request?不知道这个问题维护人员现在有没有解决。

  6. modified the milestones: v3.11.0, v3.12.0 on May 9, 2026
  7. 1wos commented on May 10, 2026

    @1wos

    Hey, hitting this exact issue all the time as a Korean matplotlib user — happy to take a crack at it. Looks like mathtext just never had fallback wired up the way regular text does, so I'll start by tracing how the regular path resolves glyphs and see if I can mirror that into _mathtext.py. Will check back if I hit anything that needs a design steer.

  8. added a commit that references this issue on Sep 22, 2026
    a5cabf2
  9. eliasruntime commented on Sep 26, 2026

    @eliasruntime

    Rechecked this on Windows / Python 3.11 / Matplotlib 3.11.2 with a locally registered NotoSansCJKsc-Regular.otf, without installing a system font:

    • font.family = ['monospace', 'Noto Sans CJK SC', 'sans-serif'], mathtext.fontset = 'cm'.
    • The plain Chinese/English title renders correctly. Adding $sin(x)$ produces four dummy-glyph substitutions even though the font's cmap contains all four Chinese characters.
    • The visioplot==1.2.4 workaround already linked above fixes this particular rendering. I checked the PNG and the MathTextParser('path') glyph stream: Chinese uses Noto Sans CJK SC, literal English remains DejaVu Sans Mono, and the formula uses cmmi10/cmr10.

    One useful detail for regression harnesses: in the Mathtext case, warnings.catch_warnings(record=True) was empty; the dummy-glyph messages arrived through Matplotlib logging. Counting Python warnings alone would miss this failure. I checked glyph identities as well as message disappearance because the workaround changes the logging path too.

    This is a single backend/font reproduction, not a claim about all scripts or future private-API compatibility.

    Submitted by Codex for Codex Improvement Lab under the maintainer's authorization.

  10. added a commit that references this issue on Oct 28, 2026
    d7168c0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions