How to get all installed font path in python on Windows?
I would like to use GDI or DirectWrite.
Dependencies:
The solution contains 2 methods since the one for Windows 10 is much faster then the one for Windows 7 or more.
import comtypes
import sys
import time
from ctypes import byref, create_unicode_buffer, POINTER, windll, wintypes
from enum import IntEnum
from typing import Set
DWriteCreateFactory = windll.dwrite.DWriteCreateFactory
DWriteCreateFactory.restype = comtypes.HRESULT
DWriteCreateFactory.argtypes = [wintypes.UINT, comtypes.GUID, POINTER(POINTER(comtypes.IUnknown))]
class DWRITE_FACTORY_TYPE(IntEnum):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_factory_type
DWRITE_FACTORY_TYPE_SHARED = 0
DWRITE_FACTORY_TYPE_ISOLATED = 1
class IDWriteFontFileLoader(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontfileloader
_iid_ = comtypes.GUID("{727cad4e-d6af-4c9e-8a08-d695b11caa49}")
_methods_ = [
comtypes.STDMETHOD(None, "CreateStreamFromKey"), # Need to be implemented
]
class IDWriteLocalFontFileLoader(IDWriteFontFileLoader):
# https://learn.microsoft.com/en-us/windows/win32/directwrite/idwritelocalfontfileloader
_iid_ = comtypes.GUID("{b2d9f3ec-c9fe-4a11-a2ec-d86208f7c0a2}")
_methods_ = [
comtypes.STDMETHOD(None, "GetFilePathLengthFromKey", [wintypes.LPCVOID, wintypes.UINT, POINTER(wintypes.UINT)]),
comtypes.STDMETHOD(None, "GetFilePathFromKey", [wintypes.LPCVOID, wintypes.UINT, POINTER(wintypes.WCHAR), wintypes.UINT]),
comtypes.STDMETHOD(None, "GetLastWriteTimeFromKey"), # Need to be implemented
]
class IDWriteFontFile(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontfile
_iid_ = comtypes.GUID("{739d886a-cef5-47dc-8769-1a8b41bebbb0}")
_methods_ = [
comtypes.STDMETHOD(comtypes.HRESULT, "GetReferenceKey", [POINTER(wintypes.LPCVOID), POINTER(wintypes.UINT)]),
comtypes.STDMETHOD(comtypes.HRESULT, "GetLoader", [POINTER(POINTER(IDWriteFontFileLoader))]),
comtypes.STDMETHOD(None, "Analyze"), # Need to be implemented
]
class IDWriteFontFaceReference(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nn-dwrite_3-idwritefontfacereference
_iid_ = comtypes.GUID("{5E7FA7CA-DDE3-424C-89F0-9FCD6FED58CD}")
_methods_ = [
comtypes.STDMETHOD(None, "CreateFontFace"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFaceWithSimulations"), # Need to be implemented
comtypes.STDMETHOD(None, "Equals"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFontFaceIndex"), # Need to be implemented
comtypes.STDMETHOD(None, "GetSimulations"), # Need to be implemented
comtypes.STDMETHOD(comtypes.HRESULT, "GetFontFile", [POINTER(POINTER(IDWriteFontFile))]),
comtypes.STDMETHOD(None, "GetLocalFileSize"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFileSize"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFileTime"), # Need to be implemented
comtypes.STDMETHOD(None, "GetLocality"), # Need to be implemented
comtypes.STDMETHOD(None, "EnqueueFontDownloadRequest"), # Need to be implemented
comtypes.STDMETHOD(None, "EnqueueCharacterDownloadRequest"), # Need to be implemented
comtypes.STDMETHOD(None, "EnqueueGlyphDownloadRequest"), # Need to be implemented
comtypes.STDMETHOD(None, "EnqueueFileFragmentDownloadRequest"), # Need to be implemented
]
class IDWriteFontSet(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nn-dwrite_3-idwritefontset
_iid_ = comtypes.GUID("{53585141-D9F8-4095-8321-D73CF6BD116B}")
_methods_ = [
comtypes.STDMETHOD(wintypes.UINT, "GetFontCount"),
comtypes.STDMETHOD(comtypes.HRESULT, "GetFontFaceReference", [wintypes.UINT, POINTER(POINTER(IDWriteFontFaceReference))]),
comtypes.STDMETHOD(None, "FindFontFaceReference"), # Need to be implemented
comtypes.STDMETHOD(None, "FindFontFace"), # Need to be implemented
comtypes.STDMETHOD(None, "GetPropertyValues"), # Need to be implemented
comtypes.STDMETHOD(None, "GetPropertyValues"), # Need to be implemented
comtypes.STDMETHOD(None, "GetPropertyValues"), # Need to be implemented
comtypes.STDMETHOD(None, "GetPropertyOccurrenceCount"), # Need to be implemented
comtypes.STDMETHOD(None, "GetMatchingFonts"), # Need to be implemented
comtypes.STDMETHOD(None, "GetMatchingFonts"), # Need to be implemented
]
class IDWriteFontFace(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontface
_iid_ = comtypes.GUID("{5f49804d-7024-4d43-bfa9-d25984f53849}")
_methods_ = [
comtypes.STDMETHOD(None, "GetType"), # Need to be implemented
comtypes.STDMETHOD(comtypes.HRESULT, "GetFiles", [POINTER(wintypes.UINT), POINTER(POINTER(IDWriteFontFile))]),
comtypes.STDMETHOD(None, "GetIndex"), # Need to be implemented
comtypes.STDMETHOD(None, "GetSimulations"), # Need to be implemented
comtypes.STDMETHOD(None, "IsSymbolFont"), # Need to be implemented
comtypes.STDMETHOD(None, "GetMetrics"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGlyphCount"), # Need to be implemented
comtypes.STDMETHOD(None, "GetDesignGlyphMetrics"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGlyphIndices"), # Need to be implemented
comtypes.STDMETHOD(None, "TryGetFontTable"), # Need to be implemented
comtypes.STDMETHOD(None, "ReleaseFontTable"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGlyphRunOutline"), # Need to be implemented
comtypes.STDMETHOD(None, "GetRecommendedRenderingMode"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGdiCompatibleMetrics"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGdiCompatibleGlyphMetrics"), # Need to be implemented
]
class IDWriteFont(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefont
_iid_ = comtypes.GUID("{acd16696-8c14-4f5d-877e-fe3fc1d32737}")
_methods_ = [
comtypes.STDMETHOD(None, "GetFontFamily"), # Need to be implemented
comtypes.STDMETHOD(None, "GetWeight"), # Need to be implemented
comtypes.STDMETHOD(None, "GetStretch"), # Need to be implemented
comtypes.STDMETHOD(None, "GetStyle"), # Need to be implemented
comtypes.STDMETHOD(None, "IsSymbolFont"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFaceNames"), # Need to be implemented
comtypes.STDMETHOD(None, "GetInformationalStrings"), # Need to be implemented
comtypes.STDMETHOD(None, "GetSimulations"), # Need to be implemented
comtypes.STDMETHOD(None, "GetMetrics"), # Need to be implemented
comtypes.STDMETHOD(None, "HasCharacter"), # Need to be implemented
comtypes.STDMETHOD(comtypes.HRESULT, "CreateFontFace", [POINTER(POINTER(IDWriteFontFace))]),
]
class IDWriteFontList(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontlist
_iid_ = comtypes.GUID("{1a0d8438-1d97-4ec1-aef9-a2fb86ed6acb}")
_methods_ = [
comtypes.STDMETHOD(None, "GetFontCollection"), # Need to be implemented
comtypes.STDMETHOD(wintypes.UINT, "GetFontCount"),
comtypes.STDMETHOD(comtypes.HRESULT, "GetFont", [wintypes.UINT, POINTER(POINTER(IDWriteFont))]),
]
class IDWriteFontFamily(IDWriteFontList):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontfamily
_iid_ = comtypes.GUID("{da20d8ef-812a-4c43-9802-62ec4abd7add}")
_methods_ = [
comtypes.STDMETHOD(None, "GetFamilyNames"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFirstMatchingFont"), # Need to be implemented
comtypes.STDMETHOD(None, "GetMatchingFonts"), # Need to be implemented
]
class IDWriteFontCollection(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefontcollection
_iid_ = comtypes.GUID("{a84cee02-3eea-4eee-a827-87c1a02a0fcc}")
_methods_ = [
comtypes.STDMETHOD(wintypes.UINT, "GetFontFamilyCount"),
comtypes.STDMETHOD(comtypes.HRESULT, "GetFontFamily", [wintypes.UINT, POINTER(POINTER(IDWriteFontFamily))]),
comtypes.STDMETHOD(None, "FindFamilyName"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFontFromFontFace"), # Need to be implemented
]
class IDWriteFactory(comtypes.IUnknown):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nn-dwrite-idwritefactory
_iid_ = comtypes.GUID("{b859ee5a-d838-4b5b-a2e8-1adc7d93db48}")
_methods_ = [
comtypes.STDMETHOD(comtypes.HRESULT, "GetSystemFontCollection", [POINTER(POINTER(IDWriteFontCollection)), wintypes.BOOLEAN]),
comtypes.STDMETHOD(None, "CreateCustomFontCollection"), # Need to be implemented
comtypes.STDMETHOD(None, "RegisterFontCollectionLoader"), # Need to be implemented
comtypes.STDMETHOD(None, "UnregisterFontCollectionLoader"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFileReference"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateCustomFontFileReference"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFace"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateRenderingParams"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateMonitorRenderingParams"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateCustomRenderingParams"), # Need to be implemented
comtypes.STDMETHOD(None, "RegisterFontFileLoader"), # Need to be implemented
comtypes.STDMETHOD(None, "UnregisterFontFileLoader"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateTextFormat"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateTypography"), # Need to be implemented
comtypes.STDMETHOD(None, "GetGdiInterop"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateTextLayout"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateGdiCompatibleTextLayout"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateEllipsisTrimmingSign"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateTextAnalyzer"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateNumberSubstitution"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateGlyphRunAnalysis"), # Need to be implemented
]
class IDWriteFactory1(IDWriteFactory):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite_1/nn-dwrite_1-idwritefactory1
_iid_ = comtypes.GUID("{30572f99-dac6-41db-a16e-0486307e606a}")
_methods_ = [
comtypes.STDMETHOD(None, "GetEudcFontCollection"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateCustomRenderingParams1"), # Need to be implemented
]
class IDWriteFactory2(IDWriteFactory1):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite_2/nn-dwrite_2-idwritefactory2
_iid_ = comtypes.GUID("{0439fc60-ca44-4994-8dee-3a9af7b732ec}")
_methods_ = [
comtypes.STDMETHOD(None, "GetSystemFontFallback"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFallbackBuilder"), # Need to be implemented
comtypes.STDMETHOD(None, "TranslateColorGlyphRun"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateCustomRenderingParams2"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateGlyphRunAnalysis"), # Need to be implemented
]
class IDWriteFactory3(IDWriteFactory2):
# https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nn-dwrite_3-idwritefactory3
_iid_ = comtypes.GUID("{9A1B41C3-D3BB-466A-87FC-FE67556A3B65}")
_methods_ = [
comtypes.STDMETHOD(None, "CreateGlyphRunAnalysis"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateCustomRenderingParams3"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFaceReference"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontFaceReference"), # Need to be implemented
comtypes.STDMETHOD(comtypes.HRESULT, "GetSystemFontSet", [POINTER(POINTER(IDWriteFontSet))]),
comtypes.STDMETHOD(None, "CreateFontSetBuilder"), # Need to be implemented
comtypes.STDMETHOD(None, "CreateFontCollectionFromFontSet"), # Need to be implemented
comtypes.STDMETHOD(None, "GetSystemFontCollection3"), # Need to be implemented
comtypes.STDMETHOD(None, "GetFontDownloadQueue"), # Need to be implemented
]
def get_fonts_filepath_windows_10_or_more() -> Set[str]:
"""
Return an list of all the font installed.
"""
fonts_path = set()
dwrite_factory = POINTER(IDWriteFactory3)()
DWriteCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_ISOLATED, IDWriteFactory3._iid_, byref(dwrite_factory))
font_set = POINTER(IDWriteFontSet)()
dwrite_factory.GetSystemFontSet(byref(font_set))
for i in range(font_set.GetFontCount()):
font_face_reference = POINTER(IDWriteFontFaceReference)()
font_set.GetFontFaceReference(i, byref(font_face_reference))
font_file = POINTER(IDWriteFontFile)()
font_face_reference.GetFontFile(byref(font_file))
loader = POINTER(IDWriteFontFileLoader)()
font_file.GetLoader(byref(loader))
font_file_reference_key = wintypes.LPCVOID()
font_file_reference_key_size = wintypes.UINT()
font_file.GetReferenceKey(byref(font_file_reference_key), byref(font_file_reference_key_size))
try:
local_loader = loader.QueryInterface(IDWriteLocalFontFileLoader)
except comtypes.COMError:
continue
path_len = wintypes.UINT()
local_loader.GetFilePathLengthFromKey(font_file_reference_key, font_file_reference_key_size, byref(path_len))
buffer = create_unicode_buffer(path_len.value + 1)
local_loader.GetFilePathFromKey(font_file_reference_key, font_file_reference_key_size, buffer, len(buffer))
fonts_path.add(buffer.value)
return fonts_path
def get_fonts_filepath_windows_7_or_more() -> Set[str]:
"""
Return an list of all the font installed.
"""
fonts_path = set()
dwrite_factory = POINTER(IDWriteFactory)()
DWriteCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_ISOLATED, IDWriteFactory._iid_, byref(dwrite_factory))
sys_collection = POINTER(IDWriteFontCollection)()
dwrite_factory.GetSystemFontCollection(byref(sys_collection), False)
for i in range(sys_collection.GetFontFamilyCount()):
family = POINTER(IDWriteFontFamily)()
sys_collection.GetFontFamily(i, byref(family))
for j in range(family.GetFontCount()):
font = POINTER(IDWriteFont)()
family.GetFont(j, byref(font))
font_face = POINTER(IDWriteFontFace)()
font.CreateFontFace(byref(font_face))
file_count = wintypes.UINT()
font_face.GetFiles(byref(file_count), None)
font_files = (POINTER(IDWriteFontFile)* file_count.value)()
font_face.GetFiles(byref(file_count), font_files)
for font_file in font_files:
font_file_reference_key = wintypes.LPCVOID()
font_file_reference_key_size = wintypes.UINT()
font_file.GetReferenceKey(byref(font_file_reference_key), byref(font_file_reference_key_size))
loader = POINTER(IDWriteFontFileLoader)()
font_file.GetLoader(byref(loader))
try:
local_loader = loader.QueryInterface(IDWriteLocalFontFileLoader)
except comtypes.COMError:
continue
path_len = wintypes.UINT()
local_loader.GetFilePathLengthFromKey(font_file_reference_key, font_file_reference_key_size, byref(path_len))
buffer = create_unicode_buffer(path_len.value + 1)
local_loader.GetFilePathFromKey(font_file_reference_key, font_file_reference_key_size, buffer, len(buffer))
fonts_path.add(buffer.value)
return fonts_path
def is_windows_version_or_greater(windows_version, major: int, minor: int, service_pack_major: int) -> bool:
"""
Parameters:
windows_version: An object from sys.getwindowsversion.
major (int): The minimum major OS version number.
minor (int): The minimum minor OS version number.
service_pack_major (int): The minimum major Service Pack version number.
Returns:
True if the specified version matches or if it is greater than the version of the current Windows OS. Otherwise, False.
"""
if windows_version.major > major:
return True
elif windows_version.major == major and windows_version.minor > minor:
return True
else:
return windows_version.major == major and windows_version.minor == minor and windows_version.service_pack_major >= service_pack_major
def is_windows_vista_sp2_or_greater(windows_version) -> bool:
return is_windows_version_or_greater(windows_version, 6, 0, 2)
def is_windows_10_or_greater(windows_version) -> bool:
return is_windows_version_or_greater(windows_version, 10, 0, 0)
def main():
start = time.time()
if sys.platform == "win32":
windows_version = sys.getwindowsversion()
if is_windows_10_or_greater(windows_version):
fonts_path_dwrite = get_fonts_filepath_windows_10_or_more()
elif is_windows_vista_sp2_or_greater(windows_version):
fonts_path_dwrite = get_fonts_filepath_windows_7_or_more()
else:
raise Exception("This script only works on Windows 7 or more")
else:
raise Exception("This script only works on Windows.")
print(fonts_path_dwrite)
print(f"Time elapsed: {time.time() - start}")
if __name__ == "__main__":
sys.exit(main())
Dependencies:
import os
import sys
import time
import winreg
from win32com.shell import shell, shellcon
def get_win32_system_font():
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") as key:
paths = []
info = winreg.QueryInfoKey(key)
fonts_root = shell.SHGetKnownFolderPath(shellcon.FOLDERID_Fonts)
for index in range(info[1]):
value = winreg.EnumValue(key, index)
path = value[1] if os.path.isabs(value[1]) else os.path.join(fonts_root, value[1])
paths.append(path)
return paths
def get_win32_user_font():
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") as key:
paths = []
info = winreg.QueryInfoKey(key)
for index in range(info[1]):
value = winreg.EnumValue(key, index)
paths.append(value[1])
return paths
def main():
start = time.time()
system_font = get_win32_system_font()
user_font = get_win32_user_font()
print(time.time() - start)
if __name__ == "__main__":
sys.exit(main())
Dependencies:
import sys
import time
from matplotlib import font_manager
def main():
start = time.time()
fonts_paths = set(font_manager.findSystemFonts())
print(time.time() - start)
if __name__ == "__main__":
sys.exit(main())
Dependencies:
from find_system_fonts_filename import get_system_fonts_filename, FontConfigNotFound, OSNotSupported
try:
fonts_filename = get_system_fonts_filename()
except (FontConfigNotFound, OSNotSupported):
# Deal with the exception
# OSNotSupported can only happen in Windows and macOS
# - Windows Vista SP2 and more are supported
# - macOS 10.6 and more are supported
# FontConfigNotFound can only happen on Linux when Fontconfig could't be found.
pass