Skip to content

Commit 8672cf9

Browse files
authored
Merge pull request matplotlib#31461 from QuLogic/default-features
Support font features/language in default RendererBase.draw_text
2 parents ba56e3d + 4461ad7 commit 8672cf9

3 files changed

Lines changed: 61 additions & 32 deletions

File tree

lib/matplotlib/backend_bases.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,19 +540,25 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
540540
rendering backends, and indeed many builtin backends do not support
541541
this. Rather, TeX rendering is provided by `~.RendererBase.draw_tex`.
542542
"""
543-
self._draw_text_as_path(gc, x, y, s, prop, angle, ismath)
543+
self._draw_text_as_path(gc, x, y, s, prop, angle, ismath, mtext)
544544

545-
def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath):
545+
def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext):
546546
"""
547547
Draw the text by converting them to paths using `.TextToPath`.
548548
549549
This private helper supports the same parameters as
550550
`~.RendererBase.draw_text`; setting *ismath* to "TeX" triggers TeX
551551
rendering.
552552
"""
553+
if mtext is not None:
554+
features = mtext.get_fontfeatures()
555+
language = mtext.get_language()
556+
else:
557+
features = language = None
553558
text2path = self._text2path
554559
fontsize = self.points_to_pixels(prop.get_size_in_points())
555-
verts, codes = text2path.get_text_path(prop, s, ismath=ismath)
560+
verts, codes = text2path.get_text_path(prop, s, ismath=ismath,
561+
features=features, language=language)
556562
path = Path(verts, codes)
557563
if self.flipy():
558564
width, height = self.get_canvas_width_height()
66 KB
Loading

lib/matplotlib/tests/test_text.py

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -115,26 +115,6 @@ def find_matplotlib_font(**kw):
115115
ax.set_yticks([])
116116

117117

118-
@image_comparison(['complex'], extensions=['png', 'pdf', 'svg', 'eps'], style='mpl20')
119-
def test_complex_shaping():
120-
# Raqm is Arabic for writing; note that because Arabic is RTL, the characters here
121-
# may seem to be in a different order than expected, but libraqm will order them
122-
# correctly for us.
123-
text = (
124-
'Arabic: \N{Arabic Letter REH}\N{Arabic FATHA}\N{Arabic Letter QAF}'
125-
'\N{Arabic SUKUN}\N{Arabic Letter MEEM}')
126-
math_signs = '\N{N-ary Product}\N{N-ary Coproduct}\N{N-ary summation}\N{Integral}'
127-
text = math_signs + text + math_signs
128-
fig = plt.figure(figsize=(6, 2))
129-
fig.text(0.5, 0.75, text, size=32, ha='center', va='center')
130-
# Also check fallback behaviour:
131-
# - English should use cmr10
132-
# - Math signs should use DejaVu Sans Display (and thus be larger than the rest)
133-
# - Arabic should use DejaVu Sans
134-
fig.text(0.5, 0.25, text, size=32, ha='center', va='center',
135-
family=['cmr10', 'DejaVu Sans Display', 'DejaVu Sans'])
136-
137-
138118
@image_comparison(['multiline'], style='mpl20')
139119
def test_multiline():
140120
plt.figure()
@@ -1235,10 +1215,31 @@ def test_text_tightbbox_outside_scale_domain():
12351215
assert not np.isfinite(invalid_bbox.width)
12361216

12371217

1238-
@image_comparison(['features'], remove_text=False, style='mpl20',
1239-
extensions=['png', 'pdf', 'svg', 'eps'])
1240-
def test_text_features():
1241-
fig = plt.figure(figsize=(5, 1.5))
1218+
def _test_complex_shaping(fig):
1219+
# Raqm is Arabic for writing; note that because Arabic is RTL, the characters here
1220+
# may seem to be in a different order than expected, but libraqm will order them
1221+
# correctly for us.
1222+
text = (
1223+
'Arabic: \N{Arabic Letter REH}\N{Arabic FATHA}\N{Arabic Letter QAF}'
1224+
'\N{Arabic SUKUN}\N{Arabic Letter MEEM}')
1225+
math_signs = '\N{N-ary Product}\N{N-ary Coproduct}\N{N-ary summation}\N{Integral}'
1226+
text = math_signs + text + math_signs
1227+
fig.text(0.5, 0.75, text, size=32, ha='center', va='center')
1228+
# Also check fallback behaviour:
1229+
# - English should use cmr10
1230+
# - Math signs should use DejaVu Sans Display (and thus be larger than the rest)
1231+
# - Arabic should use DejaVu Sans
1232+
fig.text(0.5, 0.25, text, size=32, ha='center', va='center',
1233+
family=['cmr10', 'DejaVu Sans Display', 'DejaVu Sans'])
1234+
1235+
1236+
@image_comparison(['complex'], extensions=['png', 'pdf', 'svg', 'eps'], style='mpl20')
1237+
def test_complex_shaping():
1238+
fig = plt.figure(figsize=(6, 2))
1239+
_test_complex_shaping(fig)
1240+
1241+
1242+
def _test_text_features(fig):
12421243
t = fig.text(1, 0.7, 'Default: fi ffi fl st',
12431244
fontsize=32, horizontalalignment='right')
12441245
assert t.get_fontfeatures() is None
@@ -1252,6 +1253,13 @@ def test_text_features():
12521253
assert t.get_fontfeatures() == ('dlig', )
12531254

12541255

1256+
@image_comparison(['features'], remove_text=False, style='mpl20',
1257+
extensions=['png', 'pdf', 'svg', 'eps'])
1258+
def test_text_features():
1259+
fig = plt.figure(figsize=(5, 1.5))
1260+
_test_text_features(fig)
1261+
1262+
12551263
@pytest.mark.parametrize(
12561264
'input, match',
12571265
[
@@ -1266,11 +1274,7 @@ def test_text_language_invalid(input, match):
12661274
Text(0, 0, 'foo', language=input)
12671275

12681276

1269-
@image_comparison(['language'], remove_text=False, style='mpl20',
1270-
extensions=['png', 'pdf', 'svg', 'eps'])
1271-
def test_text_language():
1272-
fig = plt.figure(figsize=(5, 3))
1273-
1277+
def _test_text_language(fig):
12741278
t = fig.text(0, 0.8, 'Default', fontsize=32)
12751279
assert t.get_language() is None
12761280
t = fig.text(0, 0.55, 'Lang A', fontsize=32)
@@ -1308,3 +1312,22 @@ def test_text_language():
13081312
t.set_language((('en', 0, 1), ('smn', 1, 2), ('en', 2, 3), ('smn', 3, 4)))
13091313
assert t.get_language() == (
13101314
('en', 0, 1), ('smn', 1, 2), ('en', 2, 3), ('smn', 3, 4))
1315+
1316+
1317+
@image_comparison(['language'], remove_text=False, style='mpl20',
1318+
extensions=['png', 'pdf', 'svg', 'eps'])
1319+
def test_text_language():
1320+
fig = plt.figure(figsize=(5, 3))
1321+
_test_text_language(fig)
1322+
1323+
1324+
@image_comparison(['draw_text_fallback.png'], style='mpl20')
1325+
def test_draw_text_as_path_fallback(monkeypatch):
1326+
# Delete RendererAgg.draw_text so that we use the RendererBase.draw_text fallback.
1327+
monkeypatch.delattr('matplotlib.backends.backend_agg.RendererAgg.draw_text')
1328+
heights = [2, 1.5, 3]
1329+
fig = plt.figure(figsize=(6, sum(heights)))
1330+
subfig = fig.subfigures(3, 1, height_ratios=heights)
1331+
_test_complex_shaping(subfig[0])
1332+
_test_text_features(subfig[1])
1333+
_test_text_language(subfig[2])

0 commit comments

Comments
 (0)