|
99 | 99 | r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts',
|
100 | 100 | r'SOFTWARE\Microsoft\Windows\CurrentVersion\Fonts']
|
101 | 101 |
|
| 102 | +MSUserFontDirectories = [ |
| 103 | + os.path.join(str(Path.home()), r'AppData\Local\Microsoft\Windows\Fonts'), |
| 104 | + os.path.join(str(Path.home()), r'AppData\Roaming\Microsoft\Windows\Fonts')] |
| 105 | + |
102 | 106 | X11FontDirectories = [
|
103 | 107 | # an old standard installation point
|
104 | 108 | "/usr/X11R6/lib/X11/fonts/TTF/",
|
@@ -167,41 +171,83 @@ def win32FontDirectory():
|
167 | 171 | return os.path.join(os.environ['WINDIR'], 'Fonts')
|
168 | 172 |
|
169 | 173 |
|
170 |
| -def win32InstalledFonts(directory=None, fontext='ttf'): |
171 |
| - """ |
172 |
| - Search for fonts in the specified font directory, or use the |
173 |
| - system directories if none given. A list of TrueType font |
174 |
| - filenames are returned by default, or AFM fonts if *fontext* == |
175 |
| - 'afm'. |
176 |
| - """ |
177 |
| - import winreg |
| 174 | +def _win32RegistryFonts(reg_domain, base_dir): |
| 175 | + r""" |
| 176 | + Searches for fonts in the Windows registry. |
178 | 177 |
|
179 |
| - if directory is None: |
180 |
| - directory = win32FontDirectory() |
| 178 | + Parameters |
| 179 | + ---------- |
| 180 | + reg_domain : int |
| 181 | + The top level registry domain (e.g. HKEY_LOCAL_MACHINE). |
181 | 182 |
|
182 |
| - fontext = ['.' + ext for ext in get_fontext_synonyms(fontext)] |
| 183 | + base_dir : str |
| 184 | + The path to the folder where the font files are usually located (e.g. |
| 185 | + C:\Windows\Fonts). If only the filename of the font is stored in the |
| 186 | + registry, the absolute path is built relative to this base directory. |
| 187 | +
|
| 188 | + Returns |
| 189 | + ------- |
| 190 | + `set` |
| 191 | + `pathlib.Path` objects with the absolute path to the font files found. |
183 | 192 |
|
| 193 | + """ |
| 194 | + import winreg |
184 | 195 | items = set()
|
185 |
| - for fontdir in MSFontDirectories: |
| 196 | + |
| 197 | + for reg_path in MSFontDirectories: |
186 | 198 | try:
|
187 |
| - with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, fontdir) as local: |
| 199 | + with winreg.OpenKey(reg_domain, reg_path) as local: |
188 | 200 | for j in range(winreg.QueryInfoKey(local)[1]):
|
189 |
| - key, direc, tp = winreg.EnumValue(local, j) |
190 |
| - if not isinstance(direc, str): |
| 201 | + # value may contain the filename of the font or its |
| 202 | + # absolute path. |
| 203 | + key, value, tp = winreg.EnumValue(local, j) |
| 204 | + if not isinstance(value, str): |
191 | 205 | continue
|
| 206 | + |
192 | 207 | # Work around for https://bugs.python.org/issue25778, which
|
193 | 208 | # is fixed in Py>=3.6.1.
|
194 |
| - direc = direc.split("\0", 1)[0] |
| 209 | + value = value.split("\0", 1)[0] |
| 210 | + |
195 | 211 | try:
|
196 |
| - path = Path(directory, direc).resolve() |
| 212 | + # If value contains already an absolute path, then it |
| 213 | + # is not changed further. |
| 214 | + path = Path(base_dir, value).resolve() |
197 | 215 | except RuntimeError:
|
198 | 216 | # Don't fail with invalid entries.
|
199 | 217 | continue
|
200 |
| - if path.suffix.lower() in fontext: |
201 |
| - items.add(str(path)) |
| 218 | + |
| 219 | + items.add(path) |
202 | 220 | except (OSError, MemoryError):
|
203 | 221 | continue
|
204 |
| - return list(items) |
| 222 | + |
| 223 | + return items |
| 224 | + |
| 225 | + |
| 226 | +def win32InstalledFonts(directory=None, fontext='ttf'): |
| 227 | + """ |
| 228 | + Search for fonts in the specified font directory, or use the |
| 229 | + system directories if none given. Additionally, it is searched for user |
| 230 | + fonts installed. A list of TrueType font filenames are returned by default, |
| 231 | + or AFM fonts if *fontext* == 'afm'. |
| 232 | + """ |
| 233 | + import winreg |
| 234 | + |
| 235 | + if directory is None: |
| 236 | + directory = win32FontDirectory() |
| 237 | + |
| 238 | + fontext = ['.' + ext for ext in get_fontext_synonyms(fontext)] |
| 239 | + |
| 240 | + items = set() |
| 241 | + |
| 242 | + # System fonts |
| 243 | + items.update(_win32RegistryFonts(winreg.HKEY_LOCAL_MACHINE, directory)) |
| 244 | + |
| 245 | + # User fonts |
| 246 | + for userdir in MSUserFontDirectories: |
| 247 | + items.update(_win32RegistryFonts(winreg.HKEY_CURRENT_USER, userdir)) |
| 248 | + |
| 249 | + # Keep only paths with matching file extension. |
| 250 | + return [str(path) for path in items if path.suffix.lower() in fontext] |
205 | 251 |
|
206 | 252 |
|
207 | 253 | @cbook.deprecated("3.1")
|
@@ -253,7 +299,7 @@ def findSystemFonts(fontpaths=None, fontext='ttf'):
|
253 | 299 |
|
254 | 300 | if fontpaths is None:
|
255 | 301 | if sys.platform == 'win32':
|
256 |
| - fontpaths = [win32FontDirectory()] |
| 302 | + fontpaths = MSUserFontDirectories + [win32FontDirectory()] |
257 | 303 | # now get all installed fonts directly...
|
258 | 304 | fontfiles.update(win32InstalledFonts(fontext=fontext))
|
259 | 305 | else:
|
|
0 commit comments