8000 Simplify family parsing, remove FontsInterface · matplotlib/matplotlib@9901df1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9901df1

Browse files
committed
Simplify family parsing, remove FontsInterface
1 parent 4f0b971 commit 9901df1

File tree

1 file changed

+81
-38
lines changed

1 file changed

+81
-38
lines changed

lib/matplotlib/font_manager.py

Lines changed: 81 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -948,24 +948,6 @@ def copy(self):
948948
return new
949949

950950

951-
class FontsInterface:
952-
def __init__(self, ordered_family):
953-
self.set_orderedfamily(ordered_family)
954-
955-
def set_orderedfamily(self, ordered_family):
956-
self.families = []
957-
self.filepaths = []
958-
for key, value in ordered_family.items():
959-
self.families.append(key)
960-
self.filepaths.append(value)
961-
962-
def get_families(self):
963-
return self.families
964-
965-
def get_filepaths(self):
966-
return self.filepaths
967-
968-
969951
class _JSONEncoder(json.JSONEncoder):
970952
def default(self, o):
971953
if isinstance(o, FontManager):
@@ -1333,36 +1315,97 @@ def findfont(self, prop, fontext='ttf', directory=None,
13331315

13341316
def find_fontsprop(self, prop, fontext='ttf', directory=None,
13351317
fallback_to_default=True, rebuild_if_missing=True):
1318+
"""
1319+
Find font families that most closely matches the given properties.
1320+
1321+
Parameters
1322+
----------
1323+
prop : str or `~matplotlib.font_manager.FontProperties`
1324+
The font properties to search for. This can be either a
1325+
`.FontProperties` object or a string defining a
1326+
`fontconfig patterns`_.
1327+
1328+
fontext : {'ttf', 'afm'}, default: 'ttf'
1329+
The extension of the font file:
1330+
1331+
- 'ttf': TrueType and OpenType fonts (.ttf, .ttc, .otf)
1332+
- 'afm': Adobe Font Metrics (.afm)
1333+
1334+
directory : str, optional
1335+
If given, only search this directory and its subdirectories.
1336+
1337+
fallback_to_default : bool
1338+
If True, will fallback to the default font family (usually
1339+
"DejaVu Sans" or "Helvetica") if none of the families were found.
1340+
1341+
rebuild_if_missing : bool
1342+
Whether to rebuild the font cache and search again if the first
1343+
match appears to point to a nonexisting font (i.e., the font cache
1344+
contains outdated entries).
1345+
1346+
Returns
1347+
-------
1348+
OrderedDict
1349+
key, value pair of families and their corresponding filepaths.
1350+
1351+
Notes
1352+
-----
1353+
This is a plugin to original findfont API, which only returns a
1354+
single font for given font properties. Instead, this API returns
1355+
an OrderedDict containing multiple fonts and their filepaths which
1356+
closely match the given font properties.
1357+
Since this internally uses original API, there's no change
1358+
to the logic of performing the nearest neighbor search.
1359+
See `findfont` for more details.
1360+
1361+
"""
1362+
1363+
rc_params = tuple(tuple(rcParams[key]) for key in [
1364+
"font.serif", "font.sans-serif", "font.cursive", "font.fantasy",
1365+
"font.monospace"])
13361366

13371367
prop = FontProperties._from_any(prop)
13381368
ffamily = prop.get_family()
13391369

1340-
# maintain two dicts, one for available paths,
1341-
# the other for fallback paths
1342-
fpaths, fbpaths = OrderedDict(), OrderedDict()
1370+
fpaths = OrderedDict()
13431371
for fidx in range(len(ffamily)):
13441372
cprop = prop.copy()
13451373

13461374
# set current prop's family
13471375
cprop.set_family(ffamily[fidx])
13481376

13491377
try:
1350-
fpath = self.findfont(cprop, fontext, directory,
1351-
False, rebuild_if_missing)
1378+
fpath = self._findfont_cached(
1379+
cprop, fontext, directory,
1380+
False, rebuild_if_missing, rc_params
1381+
)
13521382
fpaths[ffamily[fidx]] = fpath
1383+
except ValueError:
1384+
_log.warning(
1385+
'findfont: Font family [\'%s\'] not found.', ffamily[fidx]
1386+
)
1387+
if ffamily[fidx].lower() in font_family_aliases:
1388+
_log.warning(
1389+
"findfont: Generic family [%r] not found because "
1390+
"none of the following families were found: %s",
1391+
ffamily[fidx],
1392+
", ".join(self._expand_aliases(ffamily[fidx]))
1393+
)
1394+
1395+
if not fpaths:
1396+
if fallback_to_default:
1397+
dfamily = self.defaultFamily[fontext]
1398+
cprop = prop.copy().set_family(dfamily)
1399+
fpath = self._findfont_cached(
1400+
cprop, fontext, directory,
1401+
True, rebuild_if_missing, rc_params
1402+
)
1403+
fpaths[dfamily] = fpath
1404+
else:
1405+
raise ValueError("Failed to find any font, and fallback "
1406+
"to the default font was disabled.")
13531407

1354-
except ValueError as e:
1355-
if fallback_to_default:
1356-
fpath = self.findfont(cprop, fontext, directory,
1357-
True, rebuild_if_missing)
1358-
fbpaths.update({self.defaultFamily[fontext]: fpath})
1359-
else:
1360-
raise e
1361-
1362-
# append fallback font(s) to the very end
1363-
fpaths.update(fbpaths)
1364-
1365-
return FontsInterface(fpaths)
1408+
return fpaths
13661409

13671410
@lru_cache()
13681411
def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
@@ -1473,10 +1516,10 @@ def _get_font(fpaths, hinting_factor, *, _kerning_factor, thread_id):
14731516
def get_font(filename, hinting_factor=None):
14741517
# Resolving the path avoids embedding the font twice in pdf/ps output if a
14751518
# single font is selected using two different relative paths.
1476-
if isinstance(filename, FontsInterface):
1477-
paths = tuple([_cached_realpath(fname) for fname in filename.get_filepaths()])
1519+
if isinstance(filename, OrderedDict):
1520+
paths = tuple(_cached_realpath(fname) for fname in filename.values())
14781521
else:
1479-
paths = tuple([_cached_realpath(filename)])
1522+
paths = (_cached_realpath(filename),)
14801523
if hinting_factor is None:
14811524
hinting_factor = rcParams['text.hinting_factor']
14821525
# also key on the thread ID to prevent segfaults with multi-threading

0 commit comments

Comments
 (0)
0