Skip to content

Commit 86983e4

Browse files
Colton LathropQuLogic
authored andcommitted
Log a warning if selected font weight differs from requested
1 parent 15f2f37 commit 86983e4

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
``font_manager.findfont`` logs if selected font weight does not match requested
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

lib/matplotlib/font_manager.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from io import BytesIO
3636
import json
3737
import logging
38-
from numbers import Number
38+
from numbers import Integral
3939
import os
4040
from pathlib import Path
4141
import plistlib
@@ -172,6 +172,10 @@
172172
]
173173

174174

175+
def _normalize_weight(weight):
176+
return weight if isinstance(weight, Integral) else weight_dict[weight]
177+
178+
175179
def get_fontext_synonyms(fontext):
176180
"""
177181
Return a list of file extensions that are synonyms for
@@ -1256,8 +1260,8 @@ def score_weight(self, weight1, weight2):
12561260
# exact match of the weight names, e.g. weight1 == weight2 == "regular"
12571261
if cbook._str_equal(weight1, weight2):
12581262
return 0.0
1259-
w1 = weight1 if isinstance(weight1, Number) else weight_dict[weight1]
1260-
w2 = weight2 if isinstance(weight2, Number) else weight_dict[weight2]
1263+
w1 = _normalize_weight(weight1)
1264+
w2 = _normalize_weight(weight2)
12611265
return 0.95 * (abs(w1 - w2) / 1000) + 0.05
12621266

12631267
def score_size(self, size1, size2):
@@ -1480,6 +1484,10 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
14801484
best_font = font
14811485
if score == 0:
14821486
break
1487+
if best_font is not None and (_normalize_weight(prop.get_weight()) !=
1488+
_normalize_weight(best_font.weight)):
1489+
_log.warning('findfont: Failed to find font weight %s, now using %s.',
1490+
prop.get_weight(), best_font.weight)
14831491

14841492
if best_font is None or best_score >= 10.0:
14851493
if fallback_to_default:

lib/matplotlib/font_manager.pyi

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1+
from collections.abc import Iterable
12
from dataclasses import dataclass
3+
from numbers import Integral
24
import os
5+
from pathlib import Path
6+
from typing import Any, Literal
37

48
from matplotlib._afm import AFM
59
from matplotlib import ft2font
610

7-
from pathlib import Path
8-
9-
from collections.abc import Iterable
10-
from typing import Any, Literal
11-
1211
font_scalings: dict[str | None, float]
1312
stretch_dict: dict[str, int]
1413
weight_dict: dict[str, int]
@@ -19,6 +18,7 @@ MSUserFontDirectories: list[str]
1918
X11FontDirectories: list[str]
2019
OSXFontDirectories: list[str]
2120

21+
def _normalize_weight(weight: str | Integral) -> Integral: ...
2222
def get_fontext_synonyms(fontext: str) -> list[str]: ...
2323
def list_fonts(directory: str, extensions: Iterable[str]) -> list[str]: ...
2424
def win32FontDirectory() -> str: ...

lib/matplotlib/tests/test_font_manager.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from matplotlib.font_manager import (
1616
findfont, findSystemFonts, FontEntry, FontProperties, fontManager,
1717
json_dump, json_load, get_font, is_opentype_cff_font,
18-
MSUserFontDirectories, _get_fontconfig_fonts, ttfFontProperty)
18+
MSUserFontDirectories, ttfFontProperty,
19+
_get_fontconfig_fonts, _normalize_weight)
1920
from matplotlib import cbook, ft2font, pyplot as plt, rc_context, figure as mfigure
2021
from matplotlib.testing import subprocess_run_helper, subprocess_run_for_testing
2122

@@ -407,3 +408,29 @@ def test_fontproperties_init_deprecation():
407408
# Since this case is not covered by docs, I've refrained from jumping
408409
# extra hoops to detect this possible API misuse.
409410
FontProperties(family="serif-24:style=oblique:weight=bold")
411+
412+
413+
def test_normalize_weights():
414+
assert _normalize_weight(300) == 300 # passthrough
415+
assert _normalize_weight('ultralight') == 100
416+
assert _normalize_weight('light') == 200
417+
assert _normalize_weight('normal') == 400
418+
assert _normalize_weight('regular') == 400
419+
assert _normalize_weight('book') == 400
420+
assert _normalize_weight('medium') == 500
421+
assert _normalize_weight('roman') == 500
422+
assert _normalize_weight('semibold') == 600
423+
assert _normalize_weight('demibold') == 600
424+
assert _normalize_weight('demi') == 600
425+
assert _normalize_weight('bold') == 700
426+
assert _normalize_weight('heavy') == 800
427+
assert _normalize_weight('extra bold') == 800
428+
assert _normalize_weight('black') == 900
429+
with pytest.raises(KeyError):
430+
_normalize_weight('invalid')
431+
432+
433+
def test_font_match_warning(caplog):
434+
findfont(FontProperties(family=["DejaVu Sans"], weight=750))
435+
logs = [rec.message for rec in caplog.records]
436+
assert 'findfont: Failed to find font weight 750, now using 700.' in logs

0 commit comments

Comments
 (0)