@@ -195,6 +195,7 @@ def list_fonts(directory, extensions):
195
195
if Path (filename ).suffix .lower () in extensions ]
196
196
197
197
198
+ @_api .deprecated ("3.5" )
198
199
def win32FontDirectory ():
199
200
r"""
200
201
Return the user-specified font directory for Win32. This is
@@ -212,6 +213,7 @@ def win32FontDirectory():
212
213
return os .path .join (os .environ ['WINDIR' ], 'Fonts' )
213
214
214
215
216
+ @_api .deprecated ("3.5" )
215
217
def _win32RegistryFonts (reg_domain , base_dir ):
216
218
r"""
217
219
Search for fonts in the Windows registry.
@@ -264,6 +266,7 @@ def _win32RegistryFonts(reg_domain, base_dir):
264
266
return items
265
267
266
268
269
+ @_api .deprecated ("3.5" )
267
270
def win32InstalledFonts (directory = None , fontext = 'ttf' ):
268
271
"""
269
272
Search for fonts in the specified font directory, or use the
@@ -291,9 +294,54 @@ def win32InstalledFonts(directory=None, fontext='ttf'):
291
294
return [str (path ) for path in items if path .suffix .lower () in fontext ]
292
295
293
296
297
+ def _get_win32_installed_fonts ():
298
+ """List the font paths known to the Windows registry."""
299
+ import winreg
300
+
301
+ # Compute the user-specified font directory for Win32, which is the
302
+ # registry entry for
303
+ # \\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Fonts
304
+ # if it exists, or %WINDIR%\Fonts.
305
+ try :
306
+ with winreg .OpenKey (winreg .HKEY_CURRENT_USER , MSFolders ) as user :
307
+ local_dir = winreg .QueryValueEx (user , 'Fonts' )[0 ]
308
+ except OSError :
309
+ local_dir = os .path .join (os .environ ['WINDIR' ], 'Fonts' )
310
+
311
+ items = set ()
312
+ # Search and resolve fonts listed in the registry.
313
+ for domain , base_dirs in [
314
+ # System fonts.
315
+ (winreg .HKEY_LOCAL_MACHINE , [local_dir ]),
316
+ # User fonts.
317
+ (winreg .HKEY_CURRENT_USER , MSUserFontDirectories ),
318
+ ]:
319
+ for base_dir in base_dirs :
320
+ for reg_path in MSFontDirectories :
321
+ try :
322
+ with winreg .OpenKey (domain , reg_path ) as local :
323
+ for j in range (winreg .QueryInfoKey (local )[1 ]):
324
+ # value may contain the filename of the font or its
325
+ # absolute path.
326
+ key , value , tp = winreg .EnumValue (local , j )
327
+ if not isinstance (value , str ):
328
+ continue
329
+ try :
330
+ # If value contains already an absolute path,
331
+ # then it is not changed further.
332
+ path = Path (base_dir , value ).resolve ()
333
+ except RuntimeError :
334
+ # Don't fail with invalid entries.
335
+ continue
336
+ items .add (path )
337
+ except (OSError , MemoryError ):
338
+ continue
339
+ return items
340
+
341
+
294
342
@lru_cache ()
295
- def _call_fc_list ():
296
- """Cache and list the font filenames known to `fc-list`."""
343
+ def _get_fontconfig_fonts ():
344
+ """Cache and list the font paths known to `fc-list`."""
297
345
try :
298
346
if b'--format' not in subprocess .check_output (['fc-list' , '--help' ]):
299
347
_log .warning ( # fontconfig 2.7 implemented --format.
@@ -302,14 +350,15 @@ def _call_fc_list():
302
350
out = subprocess .check_output (['fc-list' , '--format=%{file}\\ n' ])
303
351
except (OSError , subprocess .CalledProcessError ):
304
352
return []
305
- return [os .fsdecode (fname ) for fname in out .split (b'\n ' )]
353
+ return [Path ( os .fsdecode (fname ) ) for fname in out .split (b'\n ' )]
306
354
307
355
356
+ @_api .deprecated ("3.5" )
308
357
def get_fontconfig_fonts (fontext = 'ttf' ):
309
358
"""List font filenames known to `fc-list` having the given extension."""
310
359
fontext = ['.' + ext for ext in get_fontext_synonyms (fontext )]
311
- return [fname for fname in _call_fc_list ()
312
- if Path ( fname ) .suffix .lower () in fontext ]
360
+ return [str ( path ) for path in _get_fontconfig_fonts ()
361
+ if path .suffix .lower () in fontext ]
313
362
314
363
315
364
def findSystemFonts (fontpaths = None , fontext = 'ttf' ):
@@ -325,14 +374,16 @@ def findSystemFonts(fontpaths=None, fontext='ttf'):
325
374
326
375
if fontpaths is None :
327
376
if sys .platform == 'win32' :
377
+ installed_fonts = _get_win32_installed_fonts ()
328
378
fontpaths = MSUserFontDirectories + [win32FontDirectory ()]
329
- # now get all installed fonts directly...
330
- fontfiles .update (win32InstalledFonts (fontext = fontext ))
331
379
else :
332
- fontpaths = X11FontDirectories
380
+ installed_fonts = _get_fontconfig_fonts ()
333
381
if sys .platform == 'darwin' :
334
382
fontpaths = [* X11FontDirectories , * OSXFontDirectories ]
335
- fontfiles .update (get_fontconfig_fonts (fontext ))
383
+ else :
384
+ fontpaths = X11FontDirectories
385
+ fontfiles .update (str (path ) for path in installed_fonts
386
+ if path .suffix .lower ()[1 :] in fontexts )
336
387
337
388
elif isinstance (fontpaths , str ):
338
389
fontpaths = [fontpaths ]
0 commit comments