Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1623633

Browse files
authored
Merge pull request #16228 from anntzer/fontpath
Allow directly passing explicit font paths.
2 parents 119fcbd + 3b2894e commit 1623633

11 files changed

Lines changed: 49 additions & 42 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Simple syntax to select fonts by absolute path
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Fonts can now be selected by passing an absolute `pathlib.Path` to the *font*
5+
kwarg of `.Text`.

examples/text_labels_and_annotations/font_file.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
"""
1+
r"""
22
===================================
33
Using a ttf font file in Matplotlib
44
===================================
55
66
Although it is usually not a good idea to explicitly point to a single ttf file
7-
for a font instance, you can do so using the `.font_manager.FontProperties`
8-
*fname* argument.
7+
for a font instance, you can do so by passing a `pathlib.Path` instance as the
8+
*font* parameter. Note that passing paths as `str`\s is intentionally not
9+
supported, but you can simply wrap `str`\s in `pathlib.Path`\s as needed.
910
1011
Here, we use the Computer Modern roman font (``cmr10``) shipped with
1112
Matplotlib.
@@ -18,14 +19,12 @@
1819
from pathlib import Path
1920

2021
import matplotlib as mpl
21-
from matplotlib import font_manager as fm
2222
import matplotlib.pyplot as plt
2323

2424
fig, ax = plt.subplots()
2525

2626
fpath = Path(mpl.get_data_path(), "fonts/ttf/cmr10.ttf")
27-
prop = fm.FontProperties(fname=fpath)
28-
ax.set_title(f'This is a special font: {fpath.name}', fontproperties=prop)
27+
ax.set_title(f'This is a special font: {fpath.name}', font=fpath)
2928
ax.set_xlabel('This is the default font')
3029

3130
plt.show()
@@ -42,5 +41,4 @@
4241
# in this example:
4342

4443
import matplotlib
45-
matplotlib.font_manager.FontProperties
4644
matplotlib.axes.Axes.set_title

examples/text_labels_and_annotations/font_table.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""
1616

1717
import os
18+
from pathlib import Path
1819
import unicodedata
1920

2021
import matplotlib.font_manager as fm
@@ -101,7 +102,7 @@ def draw_font_table(path):
101102
for key, cell in table.get_celld().items():
102103
row, col = key
103104
if row > 0 and col > -1: # Beware of table's idiosyncratic indexing...
104-
cell.set_text_props(fontproperties=fm.FontProperties(fname=path))
105+
cell.set_text_props(font=Path(path))
105106

106107
fig.tight_layout()
107108
plt.show()

lib/matplotlib/font_manager.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,10 @@ class FontProperties:
598598
599599
sans-serif, normal, normal, normal, normal, scalable.
600600
601-
Alternatively, a font may be specified using an absolute path to a
602-
.ttf file, by using the *fname* kwarg.
601+
Alternatively, a font may be specified using the absolute path to a font
602+
file, by using the *fname* kwarg. However, in this case, it is typically
603+
simpler to just pass the path (as a `pathlib.Path`, not a `str`) to the
604+
*font* kwarg of the `.Text` object.
603605
604606
The preferred usage of font sizes is to use the relative values,
605607
e.g., 'large', instead of absolute font sizes, e.g., 12. This
@@ -657,6 +659,17 @@ def __init__(self,
657659
self.set_file(fname)
658660
self.set_size(size)
659661

662+
@classmethod
663+
def _from_any(cls, arg):
664+
if isinstance(arg, cls):
665+
return arg
666+
elif isinstance(arg, os.PathLike):
667+
return cls(fname=arg)
668+
elif isinstance(arg, str):
669+
return cls(arg)
670+
else:
671+
return cls(**arg)
672+
660673
def __hash__(self):
661674
l = (tuple(self.get_family()),
662675
self.get_slant(),
@@ -1230,8 +1243,7 @@ def findfont(self, prop, fontext='ttf', directory=None,
12301243
def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
12311244
rebuild_if_missing, rc_params):
12321245

1233-
if not isinstance(prop, FontProperties):
1234-
prop = FontProperties(prop)
1246+
prop = FontProperties._from_any(prop)
12351247

12361248
fname = prop.get_file()
12371249
if fname is not None:

lib/matplotlib/legend.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,10 @@ def __init__(self, parent, handles, labels,
364364
self.prop = FontProperties(size=fontsize)
365365
else:
366366
self.prop = FontProperties(size=rcParams["legend.fontsize"])
367-
elif isinstance(prop, dict):
368-
self.prop = FontProperties(**prop)
369-
if "size" not in prop:
370-
self.prop.set_size(rcParams["legend.fontsize"])
371367
else:
372-
self.prop = prop
368+
self.prop = FontProperties._from_any(prop)
369+
if isinstance(prop, dict) and "size" not in prop:
370+
self.prop.set_size(rcParams["legend.fontsize"])
373371

374372
self._fontsize = self.prop.get_size_in_points()
375373

@@ -876,8 +874,6 @@ def set_title(self, title, prop=None):
876874
self._legend_title_box.set_visible(False)
877875

878876
if prop is not None:
879-
if isinstance(prop, dict):
880-
prop = FontProperties(**prop)
881877
self._legend_title_box._text.set_fontproperties(prop)
882878

883879
self.stale = True

lib/matplotlib/offsetbox.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,12 +1101,10 @@ def __init__(self, loc,
11011101

11021102
if prop is None:
11031103
self.prop = FontProperties(size=rcParams["legend.fontsize"])
1104-
elif isinstance(prop, dict):
1105-
self.prop = FontProperties(**prop)
1106-
if "size" not in prop:
1107-
self.prop.set_size(rcParams["legend.fontsize"])
11081104
else:
1109-
self.prop = prop
1105+
self.prop = FontProperties._from_any(prop)
1106+
if isinstance(prop, dict) and "size" not in prop:
1107+
self.prop.set_size(rcParams["legend.fontsize"])
11101108

11111109
self.patch = FancyBboxPatch(
11121110
xy=(0.0, 0.0), width=1., height=1.,

lib/matplotlib/quiver.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,10 @@ def on_dpi_change(fig):
282282
_fp = self.fontproperties
283283
# boxprops = dict(facecolor='red')
284284
self.text = mtext.Text(
285-
text=label, # bbox=boxprops,
286-
horizontalalignment=self.halign[self.labelpos],
287-
verticalalignment=self.valign[self.labelpos],
288-
fontproperties=font_manager.FontProperties(**_fp))
285+
text=label, # bbox=boxprops,
286+
horizontalalignment=self.halign[self.labelpos],
287+
verticalalignment=self.valign[self.labelpos],
288+
fontproperties=font_manager.FontProperties._from_any(_fp))
289289

290290
if self.labelcolor is not None:
291291
self.text.set_color(self.labelcolor)
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from pathlib import Path
22

33
import matplotlib
4-
from matplotlib.font_manager import FontProperties
54
from matplotlib.testing.decorators import image_comparison
65
import matplotlib.pyplot as plt
76

@@ -10,10 +9,9 @@
109
# mpltest.ttf does not have "l"/"p" glyphs so we get a warning when trying to
1110
# get the font extents.
1211
def test_truetype_conversion(recwarn):
13-
fontprop = FontProperties(
14-
fname=str(Path(__file__).with_name('mpltest.ttf').resolve()), size=80)
1512
matplotlib.rcParams['pdf.fonttype'] = 3
1613
fig, ax = plt.subplots()
17-
ax.text(0, 0, "ABCDE", fontproperties=fontprop)
14+
ax.text(0, 0, "ABCDE",
15+
font=Path(__file__).with_name("mpltest.ttf"), fontsize=80)
1816
ax.set_xticks([])
1917
ax.set_yticks([])

lib/matplotlib/text.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def _get_textbox(text, renderer):
105105
@cbook._define_aliases({
106106
"color": ["c"],
107107
"fontfamily": ["family"],
108-
"fontproperties": ["font_properties"],
108+
"fontproperties": ["font", "font_properties"],
109109
"horizontalalignment": ["ha"],
110110
"multialignment": ["ma"],
111111
"fontname": ["name"],
@@ -1221,11 +1221,12 @@ def set_fontproperties(self, fp):
12211221
12221222
Parameters
12231223
----------
1224-
fp : `.font_manager.FontProperties`
1224+
fp : `.font_manager.FontProperties` or `str` or `pathlib.Path`
1225+
If a `str`, it is interpreted as a fontconfig pattern parsed by
1226+
`.FontProperties`. If a `pathlib.Path`, it is interpreted as the
1227+
absolute path to a font file.
12251228
"""
1226-
if isinstance(fp, str):
1227-
fp = FontProperties(fp)
1228-
self._fontproperties = fp.copy()
1229+
self._fontproperties = FontProperties._from_any(fp).copy()
12291230
self.stale = True
12301231

12311232
def set_usetex(self, usetex):

lib/matplotlib/textpath.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ def __init__(self, xy, s, size=None, prop=None,
400400

401401
if prop is None:
402402
prop = FontProperties()
403+
else:
404+
prop = FontProperties._from_any(prop)
403405
if size is None:
404406
size = prop.get_size_in_points()
405407

0 commit comments

Comments
 (0)