@@ -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,52 @@ 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
+ (winreg .HKEY_LOCAL_MACHINE , [local_dir ]), # System fonts.
315
+ (winreg .HKEY_CURRENT_USER , MSUserFontDirectories ), # User fonts.
316
+ ]:
317
+ for base_dir in base_dirs :
318
+ for reg_path in MSFontDirectories :
319
+ try :
320
+ with winreg .OpenKey (domain , reg_path ) as local :
321
+ for j in range (winreg .QueryInfoKey (local )[1 ]):
322
+ # value may contain the filename of the font or its
323
+ # absolute path.
324
+ key , value , tp = winreg .EnumValue (local , j )
325
+ if not isinstance (value , str ):
326
+ continue
327
+ try :
328
+ # If value contains already an absolute path,
D7AE
329
+ # then it is not changed further.
330
+ path = Path (base_dir , value ).resolve ()
331
+ except RuntimeError :
332
+ # Don't fail with invalid entries.
333
+ continue
334
+ items .add (path )
335
+ except (OSError , MemoryError ):
336
+ continue
337
+ return items
338
+
339
+
294
340
@lru_cache ()
295
- def _call_fc_list ():
296
- """Cache and list the font filenames known to `fc-list`."""
341
+ def _get_fontconfig_fonts ():
342
+ """Cache and list the font paths known to `fc-list`."""
297
343
try :
298
344
if b'--format' not in subprocess .check_output (['fc-list' , '--help' ]):
299
345
_log .warning ( # fontconfig 2.7 implemented --format.
@@ -302,14 +348,15 @@ def _call_fc_list():
302
348
out = subprocess .check_output (['fc-list' , '--format=%{file}\\ n' ])
303
349
except (OSError , subprocess .CalledProcessError ):
304
350
return []
305
- return [os .fsdecode (fname ) for fname in out .split (b'\n ' )]
351
+ return [Path ( os .fsdecode (fname ) ) for fname in out .split (b'\n ' )]
306
352
307
353
354
+ @_api .deprecated ("3.5" )
308
355
def get_fontconfig_fonts (fontext = 'ttf' ):
309
356
"""List font filenames known to `fc-list` having the given extension."""
310
357
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 ]
358
+ return [str ( path ) for path in _get_fontconfig_fonts ()
359
+ if path .suffix .lower () in fontext ]
313
360
314
361
315
362
def findSystemFonts (fontpaths = None , fontext = 'ttf' ):
@@ -325,14 +372,16 @@ def findSystemFonts(fontpaths=None, fontext='ttf'):
325
372
326
373
if fontpaths is None :
327
374
if sys .platform == 'win32' :
375
+ installed_fonts = _get_win32_installed_fonts ()
328
376
fontpaths = MSUserFontDirectories + [win32FontDirectory ()]
329
- # now get all installed fonts directly...
330
- fontfiles .update (win32InstalledFonts (fontext = fontext ))
331
377
else :
332
- fontpaths = X11FontDirectories
378
+ installed_fonts = _get_fontconfig_fonts ()
333
379
if sys .platform == 'darwin' :
334
380
fontpaths = [* X11FontDirectories , * OSXFontDirectories ]
335
- fontfiles .update (get_fontconfig_fonts (fontext ))
381
+ else :
382
+ fontpaths = X11FontDirectories
383
+ fontfiles .update (str (path ) for path in installed_fonts
384
+ if path .suffix .lower ()[1 :] in fontexts )
336
385
337
386
elif isinstance (fontpaths , str ):
338
387
fontpaths = [fontpaths ]
0 commit comments