8000 Allow font manager to parse all families · matplotlib/matplotlib@b715ddb · GitHub
[go: up one dir, main page]

Skip to content

Commit b715ddb

Browse files
committed
Allow font manager to parse all families
1 parent 2a3037f commit b715ddb

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

lib/matplotlib/font_manager.py

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
# - setWeights function needs improvement
2424
# - 'light' is an invalid weight value, remove it.
2525

26+
from collections import OrderedDict
2627
import dataclasses
2728
from functools import lru_cache
2829
import json
@@ -1019,6 +1020,19 @@ def json_load(filename):
10191020
return json.load(fh, object_hook=_json_decode)
10201021

10211022

1023+
class FontsPath:
1024+
"""Class to hold the result of findfont"""
1025+
def __init__(self, file_paths):
1026+
self._filepaths = None
1027+
self.set_filepaths(file_paths)
1028+
1029+
def set_filepaths(self, file_paths):
1030+
self._filepaths = file_paths
1031+
1032+
def get_filepaths(self):
1033+
return self._filepaths
1034+
1035+
10221036
def _normalize_font_family(family):
10231037
if isinstance(family, str):
10241038
family = [family]
@@ -1304,16 +1318,39 @@ def findfont(self, prop, fontext='ttf', directory=None,
13041318
rc_params = tuple(tuple(rcParams[key]) for key in [
13051319
"font.serif", "font.sans-serif", "font.cursive", "font.fantasy",
13061320
"font.monospace"])
1307-
return self._findfont_cached(
1308-
prop, fontext, directory, fallback_to_default, rebuild_if_missing,
1309-
rc_params)
1321+
1322+
prop = FontProperties._from_any(prop)
1323+
ffamily = prop.get_family()
1324+
1325+
# maintain two dicts, one for available paths,
1326+
# the other for fallback paths
1327+
fpaths, fbpaths = OrderedDict(), OrderedDict()
1328+
for fidx in range(len(ffamily)):
1329+
prop = prop.copy()
1330+
1331+
# set current prop's family
1332+
prop.set_family(ffamily[fidx])
1333+
1334+
fpath = self._findfont_cached(
1335+
FontProperties._from_any(prop), fontext, directory,
1336+
fallback_to_default, rebuild_if_missing, rc_params)
1337+
1338+
# if fontfile isn't found, fpath will be a FontsPath object
1339+
if isinstance(fpath, FontsPath):
1340+
fbpaths.update(fpath.get_filepaths())
1341+
else:
1342+
fpaths[ffamily[fidx]] = fpath
1343+
1344+
# append fallback font(s) to the very end
1345+
fpaths.update(fbpaths)
1346+
1347+
return FontsPath(fpaths)
1348+
13101349

13111350
@lru_cache()
13121351
def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
13131352
rebuild_if_missing, rc_params):
13141353

1315-
prop = FontProperties._from_any(prop)
1316-
13171354
fname = prop.get_file()
13181355
if fname is not None:
13191356
return fname
@@ -1401,7 +1438,10 @@ def is_opentype_cff_font(filename):
14011438

14021439

14031440
@lru_cache(64)
1404-
def _get_font(filename, hinting_factor, *, _kerning_factor, thread_id):
1441+
def _get_font(filenames, hinting_factor, *, _kerning_factor, thread_id):
1442+
# TODO: allow multiple files (future PR)
1443+
# for now just pass the first element
1444+
filename = filenames[0]
14051445
return ft2font.FT2Font(
14061446
filename, hinting_factor, _kerning_factor=_kerning_factor)
14071447

@@ -1417,11 +1457,20 @@ def _get_font(filename, hinting_factor, *, _kerning_factor, thread_id):
14171457
def get_font(filename, hinting_factor=None):
14181458
# Resolving the path avoids embedding the font twice in pdf/ps output if a
14191459
# single font is selected using two different relative paths.
1420-
filename = _cached_realpath(filename)
1460+
if isinstance(filename, FontsPath):
1461+
filenames = []
1462+
for fname in filename.get_filepaths().values():
1463+
filenames.append(_cached_realpath(fname))
1464+
else:
1465+
filenames = [_cached_realpath(filename)]
14211466
if hinting_factor is None:
14221467
hinting_factor = rcParams['text.hinting_factor']
1468+
1469+
# convert to tuple so its hashable
1470+
filenames = tuple(filenames)
1471+
14231472
# also key on the thread ID to prevent segfaults with multi-threading
1424-
return _get_font(filename, hinting_factor,
1473+
return _get_font(filenames, hinting_factor,
14251474
_kerning_factor=rcParams['text.kerning_factor'],
14261475
thread_id=threading.get_ident())
14271476

0 commit comments

Comments
 (0)
0