Description
Bug report
Bug summary
The document page Configuring the font family said that:
You can explicitly set which font family is picked up for a given font style (e.g., 'serif', 'sans-serif', or 'monospace').
In the example below, we only allow one font family (Tahoma) for the sans-serif font style. You the default family with the font.family rc param, e.g.,:rcParams['font.family'] = 'sans-serif'and for the font.family you set a list of font styles to try to find in order:
rcParams['font.sans-serif'] = ['Tahoma', 'DejaVu Sans', 'Lucida Grande', 'Verdana']
But the mechanism behind the strings rendering with the font-family is not as same as what most users think.
- The
matplotlib
just finds the font in the font list and apply the first valid one (can be found in the given path) to all characters in the given string. - We can use a list of fonts to the font-family settings in Visual Studio Code, Sublime Text, and websites. They have their own algorithm to deal with the problem of fonts fallback so that we can apply each font in the list in order to draw the correct character. Refer to How do web browsers implement font fallback?
Would matplotlib
have any plan to implement this feature? There were so many users got into the trouble of missing fonts when we want to show the string mixed with CJK characters and Latin characters.
Code for reproduction
Just take a look at this Colab Notebook.
use ['DejaVu Sans', 'SimHei', 'sans-serif']
# Setup the fonts
matplotlib.rcParams['font.sans-serif'] = ['DejaVu Sans', 'SimHei', 'sans-serif']
def model(x, p):
return x ** (2 * p + 1) / (1 + x ** (2 * p))
x = np.linspace(0.75, 1.25, 201)
fig, ax = plt.subplots()
for p in [10, 15, 20, 30, 50, 100]:
ax.plot(x, model(x, p), label=p)
ax.legend(title='Order')
ax.set(xlabel='電壓 Voltage (mV)')
ax.set(ylabel='電流 Current (A)')
ax.autoscale(tight=True)
電壓
and電流
can't be correctly rendered with the current fontDejaVu Sans
.
use ['SimHei', 'DejaVu Sans', 'sans-serif']
# Setup the fonts
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'sans-serif']
def model(x, p):
return x ** (2 * p + 1) / (1 + x ** (2 * p))
x = np.linspace(0.75, 1.25, 201)
fig, ax = plt.subplots()
for p in [10, 15, 20, 30, 50, 100]:
ax.plot(x, model(x, p), label=p)
ax.legend(title='Order')
ax.set(xlabel='電壓 Voltage (mV)')
ax.set(ylabel='電流 Current (A)')
ax.autoscale(tight=True)
電壓
and電流
can be correctly rendered with the current fontSimHei
.Voltage
andCurrent
are also be rendered with the current fontSimHei
.
Expected outcome
We would like to apply the Chinese font SimHei
to the Chinese characters and the English font DejaVu Sans
to the English characters. Just like what we use font-family
style in CSS: