|
2 | 2 | """ |
3 | 3 | # std imports |
4 | 4 | from os import PathLike |
| 5 | +from pathlib import Path |
5 | 6 | from typing import List, Optional, Union |
| 7 | +import warnings |
6 | 8 |
|
7 | 9 | # tpl imports |
8 | 10 | from matplotlib.font_manager import FontProperties, fontManager |
@@ -50,12 +52,8 @@ def __init__( |
50 | 52 | """ |
51 | 53 | if interactive and backend is not None: |
52 | 54 | raise ValueError("interactive and backend cannot both be specified.") |
53 | | - |
54 | | - if font_name is not None and font_path is not None: |
55 | | - raise ValueError("Only one of font_name and font_path may be specified.") |
56 | 55 |
|
57 | | - if font_path is not None: |
58 | | - font_name = self._load_font(font_path) |
| 56 | + font_name = self._resolve_font(font_name, font_path) |
59 | 57 |
|
60 | 58 | if font_scale <= 0: |
61 | 59 | raise ValueError("font_scale must be positive.") |
@@ -104,3 +102,39 @@ def _load_font(self, font_path: PathLike) -> str: |
104 | 102 | """ load a font into matplotlib and return its name """ |
105 | 103 | fontManager.addfont(font_path) |
106 | 104 | return FontProperties(fname=font_path).get_name() |
| 105 | + |
| 106 | + def _resolve_font(self, font_name: Optional[str], font_path: Optional[str]) -> str: |
| 107 | + """ Resolves the font to use for plotting. |
| 108 | + If neither font_name nor font_path is specified, look for the Gill Sans MT or Gill Sans font packaged with this library. |
| 109 | + If it is not found, look for a systems Gill Sans or Gill Sans MT font. If it is still not found, print a warning and use the default font. |
| 110 | + If font_name is specified, use it. |
| 111 | + If font_path is specified, load the font from the path and use it. |
| 112 | + If both are specified, raise an error. |
| 113 | + """ |
| 114 | + if font_name is not None and font_path is not None: |
| 115 | + raise ValueError("Only one of font_name and font_path may be specified.") |
| 116 | + |
| 117 | + if font_path is not None: |
| 118 | + return self._load_font(font_path) |
| 119 | + |
| 120 | + if font_name is not None: |
| 121 | + return font_name |
| 122 | + |
| 123 | + # Use bundled Gill Sans font if available |
| 124 | + bundled_font_path = Path(__file__).parent.parent / "fonts" / "gillsans.ttf" |
| 125 | + if bundled_font_path.exists(): |
| 126 | + return self._load_font(bundled_font_path) |
| 127 | + |
| 128 | + # Look for system Gill Sans or Gill Sans MT fonts |
| 129 | + available_fonts = [f.name for f in fontManager.ttflist] |
| 130 | + for font_candidate in ['Gill Sans MT', 'Gill Sans', 'GillSans']: |
| 131 | + if font_candidate in available_fonts: |
| 132 | + return font_candidate |
| 133 | + |
| 134 | + # Fall back to default font with warning |
| 135 | + warnings.warn( |
| 136 | + "Gill Sans font not found. Using default sans-serif font. " |
| 137 | + "For best results, install Gill Sans or specify a custom font.", |
| 138 | + UserWarning |
| 139 | + ) |
| 140 | + return "sans-serif" |
0 commit comments