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

Skip to content

Commit 83feec5

Browse files
committed
Use more specific patterns for bundled mathtext fonts
Because we previously only asked for a font family (and sometimes a weight/style), mathtext fonts were at the whim of rcParams for all other settings. This could mean that we would look for an non-existent weight, or even set the normal font to italic unintentionally. The fonts that are available for mathtext are (for now) fixed and bundled, and we only intend for them to work with the exact fonts we have. So use more specific fontconfig patterns that should always match the fonts that we have. While it could be possible to simply hard-code these paths relative to our data path, it seems that way back in 157a059, that implementation was changed to `findfont` intentionally to avoid duplicate embeddings.
1 parent 87edae5 commit 83feec5

2 files changed

Lines changed: 45 additions & 11 deletions

File tree

lib/matplotlib/_mathtext.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
364364
self._fonts['default'] = default_font
365365
self._fonts['regular'] = default_font
366366

367+
def _normalize_font_pattern(self, pattern: str) -> str:
368+
for option in ['stretch', 'style', 'variant', 'weight']:
369+
if f':{option}' not in pattern:
370+
pattern = f'{pattern}:{option}=normal'
371+
return pattern
372+
367373
def _get_font(self, font: str) -> FT2Font:
368374
basename = self.fontmap.get(font, font)
369375
cached_font = self._fonts.get(basename)
@@ -492,7 +498,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
492498

493499
super().__init__(default_font_prop, load_glyph_flags)
494500
for key, val in self._fontmap.items():
495-
fullpath = findfont(val)
501+
fullpath = findfont(self._normalize_font_pattern(val))
496502
self.fontmap[key] = fullpath
497503
self.fontmap[val] = fullpath
498504

@@ -617,7 +623,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
617623
}
618624

619625
for size, name in stixsizedaltfonts.items():
620-
fullpath = findfont(name)
626+
fullpath = findfont(self._normalize_font_pattern(name))
621627
self.fontmap[size] = fullpath
622628
self.fontmap[name] = fullpath
623629

@@ -719,7 +725,7 @@ def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlag
719725
'5': 'STIXSizeFiveSym',
720726
})
721727
for key, name in self._fontmap.items():
722-
fullpath = findfont(name)
728+
fullpath = findfont(self._normalize_font_pattern(name))
723729
self.fontmap[key] = fullpath
724730
self.fontmap[name] = fullpath
725731

@@ -748,9 +754,9 @@ class DejaVuSerifFonts(DejaVuFonts):
748754
"""
749755
_fontmap = {
750756
'rm': 'DejaVu Serif',
751-
'it': 'DejaVu Serif:italic',
757+
'it': 'DejaVu Serif:style=italic',
752758
'bf': 'DejaVu Serif:weight=bold',
753-
'bfit': 'DejaVu Serif:italic:bold',
759+
'bfit': 'DejaVu Serif:style=italic:weight=bold',
754760
'sf': 'DejaVu Sans',
755761
'tt': 'DejaVu Sans Mono',
756762
'ex': 'DejaVu Serif Display',
@@ -769,9 +775,9 @@ class DejaVuSansFonts(DejaVuFonts):
769775
"""
770776
_fontmap = {
771777
'rm': 'DejaVu Sans',
772-
'it': 'DejaVu Sans:italic',
778+
'it': 'DejaVu Sans:style=italic',
773779
'bf': 'DejaVu Sans:weight=bold',
774-
'bfit': 'DejaVu Sans:italic:bold',
780+
'bfit': 'DejaVu Sans:style=italic:weight=bold',
775781
'sf': 'DejaVu Sans',
776782
'tt': 'DejaVu Sans Mono',
777783
'ex': 'DejaVu Sans Display',
@@ -796,11 +802,11 @@ class StixFonts(UnicodeFonts):
796802
"""
797803
_fontmap = {
798804
'rm': 'STIXGeneral',
799-
'it': 'STIXGeneral:italic',
805+
'it': 'STIXGeneral:style=italic',
800806
'bf': 'STIXGeneral:weight=bold',
801-
'bfit': 'STIXGeneral:italic:bold',
807+
'bfit': 'STIXGeneral:style=italic:weight=bold',
802808
'nonunirm': 'STIXNonUnicode',
803-
'nonuniit': 'STIXNonUnicode:italic',
809+
'nonuniit': 'STIXNonUnicode:style=italic',
804810
'nonunibf': 'STIXNonUnicode:weight=bold',
805811
'0': 'STIXGeneral',
806812
'1': 'STIXSizeOneSym',
@@ -815,7 +821,7 @@ class StixFonts(UnicodeFonts):
815821
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
816822
TruetypeFonts.__init__(self, default_font_prop, load_glyph_flags)
817823
for key, name in self._fontmap.items():
818-
fullpath = findfont(name)
824+
fullpath = findfont(self._normalize_font_pattern(name))
819825
self.fontmap[key] = fullpath
820826
self.fontmap[name] = fullpath
821827

lib/matplotlib/tests/test_mathtext.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,34 @@ def test_mathtext_exceptions(math, msg):
371371
parser.parse(math)
372372

373373

374+
def test_mathtext_fonts(caplog):
375+
# Changing these `font.*` rcParams should not affect mathtext, as that uses bundled
376+
# fonts with a specific mapping to style/weight. TODO: font.stretch and font.variant
377+
# are difficult to test as we don't have anything that might accidentally be
378+
# substituted there.
379+
mpl.rcParams['font.style'] = 'italic'
380+
mpl.rcParams['font.weight'] = 100
381+
# Use explicitly available default so that it doesn't warn.
382+
default_font = fm.FontProperties('DejaVu Sans:style=normal:weight=normal')
383+
384+
_mathtext.BakomaFonts(default_font, LoadFlags.DEFAULT)
385+
dejavusans = _mathtext.DejaVuSansFonts(default_font, LoadFlags.DEFAULT)
386+
dejavuserif = _mathtext.DejaVuSerifFonts(default_font, LoadFlags.DEFAULT)
387+
stix = _mathtext.StixFonts(default_font, LoadFlags.DEFAULT)
388+
stixsans = _mathtext.StixSansFonts(default_font, LoadFlags.DEFAULT)
389+
390+
# Setting font.style should not have accidentally changed any roman font to italic.
391+
assert dejavusans.fontmap['rm'].endswith('DejaVuSans.ttf')
392+
assert dejavuserif.fontmap['rm'].endswith('DejaVuSerif.ttf')
393+
assert stix.fontmap['rm'].endswith('STIXGeneral.ttf')
394+
assert stixsans.fontmap['rm'].endswith('STIXGeneral.ttf')
395+
# No bakoma font is actually italic, so that setting won't affect it.
396+
397+
# If `font.weight` leaked into the mathtext setup, then it should cause a warning to
398+
# be logged from the font manager for a missing font weight.
399+
assert caplog.records == []
400+
401+
374402
def test_get_unicode_index_exception():
375403
with pytest.raises(ValueError):
376404
_mathtext.get_unicode_index(r'\foo')

0 commit comments

Comments
 (0)