Skip to content

Commit 46feb6e

Browse files
authored
Merge pull request #16368 from anntzer/warnscript
Improve warning for unsupported scripts.
2 parents 93d1434 + b135cbf commit 46feb6e

File tree

6 files changed

+56
-16
lines changed

6 files changed

+56
-16
lines changed

lib/matplotlib/_text_layout.py renamed to lib/matplotlib/_text_helpers.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
11
"""
2-
Text layouting utilities.
2+
Low-level text helper utilities.
33
"""
44

55
import dataclasses
66

7+
from . import _api
78
from .ft2font import KERNING_DEFAULT, LOAD_NO_HINTING
89

910

1011
LayoutItem = dataclasses.make_dataclass(
1112
"LayoutItem", ["char", "glyph_idx", "x", "prev_kern"])
1213

1314

15+
def warn_on_missing_glyph(codepoint):
16+
_api.warn_external(
17+
"Glyph {} ({}) missing from current font.".format(
18+
codepoint,
19+
chr(codepoint).encode("ascii", "namereplace").decode("ascii")))
20+
block = ("Hebrew" if 0x0590 <= codepoint <= 0x05ff else
21+
"Arabic" if 0x0600 <= codepoint <= 0x06ff else
22+
"Devanagari" if 0x0900 <= codepoint <= 0x097f else
23+
"Bengali" if 0x0980 <= codepoint <= 0x09ff else
24+
"Gurmukhi" if 0x0a00 <= codepoint <= 0x0a7f else
25+
"Gujarati" if 0x0a80 <= codepoint <= 0x0aff else
26+
"Oriya" if 0x0b00 <= codepoint <= 0x0b7f else
27+
"Tamil" if 0x0b80 <= codepoint <= 0x0bff else
28+
"Telugu" if 0x0c00 <= codepoint <= 0x0c7f else
29+
"Kannada" if 0x0c80 <= codepoint <= 0x0cff else
30+
"Malayalam" if 0x0d00 <= codepoint <= 0x0d7f else
31+
"Sinhala" if 0x0d80 <= codepoint <= 0x0dff else
32+
None)
33+
if block:
34+
_api.warn_external(
35+
f"Matplotlib currently does not support {block} natively.")
36+
37+
1438
def layout(string, font, *, kern_mode=KERNING_DEFAULT):
1539
"""
1640
Render *string* with *font*. For each character in *string*, yield a

lib/matplotlib/backends/backend_pdf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from PIL import Image
2525

2626
import matplotlib as mpl
27-
from matplotlib import _api, _text_layout, cbook
27+
from matplotlib import _api, _text_helpers, cbook
2828
from matplotlib._pylab_helpers import Gcf
2929
from matplotlib.backend_bases import (
3030
_Backend, _check_savefig_extra_args, FigureCanvasBase, FigureManagerBase,
@@ -2296,7 +2296,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
22962296
# List of (start_x, glyph_index).
22972297
multibyte_glyphs = []
22982298
prev_was_multibyte = True
2299-
for item in _text_layout.layout(
2299+
for item in _text_helpers.layout(
23002300
s, font, kern_mode=KERNING_UNFITTED):
23012301
if ord(item.char) <= 255:
23022302
if prev_was_multibyte:

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
import numpy as np
1919

2020
import matplotlib as mpl
21-
from matplotlib import _api, cbook, _path
22-
from matplotlib import _text_layout
21+
from matplotlib import _api, cbook, _path, _text_helpers
2322
from matplotlib.afm import AFM
2423
from matplotlib.backend_bases import (
2524
_Backend, _check_savefig_extra_args, FigureCanvasBase, FigureManagerBase,
@@ -613,7 +612,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
613612
font.set_text(s, 0, flags=LOAD_NO_HINTING)
614613
self._character_tracker.track(font, s)
615614
xs_names = [(item.x, font.get_glyph_name(item.glyph_idx))
616-
for item in _text_layout.layout(s, font)]
615+
for item in _text_helpers.layout(s, font)]
617616

618617
self.set_color(*gc.get_rgb())
619618
ps_name = (font.postscript_name

lib/matplotlib/tests/test_text.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,3 +720,14 @@ def test_invalid_color():
720720
def test_pdf_kerning():
721721
plt.figure()
722722
plt.figtext(0.1, 0.5, "ATATATATATATATATATA", size=30)
723+
724+
725+
def test_unsupported_script(recwarn):
726+
fig = plt.figure()
727+
fig.text(.5, .5, "\N{BENGALI DIGIT ZERO}")
728+
fig.canvas.draw()
729+
assert all(isinstance(warn.message, UserWarning) for warn in recwarn)
730+
assert (
731+
[warn.message.args for warn in recwarn] ==
732+
[(r"Glyph 2534 (\N{BENGALI DIGIT ZERO}) missing from current font.",),
733+
(r"Matplotlib currently does not support Bengali natively.",)])

lib/matplotlib/textpath.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import numpy as np
77

8-
from matplotlib import _text_layout, dviread, font_manager, rcParams
8+
from matplotlib import _text_helpers, dviread, font_manager, rcParams
99
from matplotlib.font_manager import FontProperties, get_font
1010
from matplotlib.ft2font import LOAD_NO_HINTING, LOAD_TARGET_LIGHT
1111
from matplotlib.mathtext import MathTextParser
@@ -149,7 +149,7 @@ def get_glyphs_with_font(self, font, s, glyph_map=None,
149149

150150
xpositions = []
151151
glyph_ids = []
152-
for item in _text_layout.layout(s, font):
152+
for item in _text_helpers.layout(s, font):
153153
char_id = self._get_char_id(font, ord(item.char))
154154
glyph_ids.append(char_id)
155155
xpositions.append(item.x)

src/ft2font.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,21 @@ FT2Image::draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1,
172172
static FT_UInt ft_get_char_index_or_warn(FT_Face face, FT_ULong charcode)
173173
{
174174
FT_UInt glyph_index = FT_Get_Char_Index(face, charcode);
175-
if (!glyph_index) {
176-
PyErr_WarnFormat(NULL, 1, "Glyph %lu missing from current font.", charcode);
177-
// Apparently PyErr_WarnFormat returns 0 even if the exception propagates
178-
// due to running with -Werror, so check the error flag directly instead.
179-
if (PyErr_Occurred()) {
180-
throw py::exception();
181-
}
175+
if (glyph_index) {
176+
return glyph_index;
177+
}
178+
PyObject *text_helpers = NULL, *tmp = NULL;
179+
if (!(text_helpers = PyImport_ImportModule("matplotlib._text_helpers")) ||
180+
!(tmp = PyObject_CallMethod(text_helpers, "warn_on_missing_glyph", "k", charcode))) {
181+
goto exit;
182182
}
183-
return glyph_index;
183+
exit:
184+
Py_XDECREF(text_helpers);
185+
Py_XDECREF(tmp);
186+
if (PyErr_Occurred()) {
187+
throw py::exception();
188+
}
189+
return 0;
184190
}
185191

186192

0 commit comments

Comments
 (0)