I was looking for a way to load a ttf file and print text with that font. While looking for some information, I found this question: load a ttf font with the Windows API
In that question they recommend adding a private font with AddFontResourceEx. But I didn't find any way to access such function with pywin32 module and ctypes.windll. Is there any way to access this function? Or failing that, another way to print text with a ttf font without using Pillow???
Next, I will leave a code so you can do the tests:
import win32print
import win32gui
import win32ui
hprinter = win32print.OpenPrinter("Microsoft Print to Pdf")
devmode = win32print.GetPrinter(hprinter, 2)["pDevMode"]
hdc = win32gui.CreateDC("WINSPOOL", printer, devmode)
dc = win32ui.CreateDCFromHandle(Self.hdc)
I managed to access the function with
ctypes.windll.gdi32.AddFontResourceExA
But now I want to access the FR_PRIVATE
constant. How can I do it?
I found out that the function doesn't work even without that constant.
I adapted the code from this answer and got the answer!
I will put the code below:
def add_font_file(file):
FR_PRIVATE = 0x10
file = ctypes.byref(ctypes.create_unicode_buffer(file))
font_count = gdi32.AddFontResourceExW(file, FR_PRIVATE, 0)
if(font_count == 0):
raise RuntimeError("Error durante la carga de la fuente.")
In case the original link goes down, the original code was as follows:
from ctypes import windll, byref, create_unicode_buffer, create_string_buffer
FR_PRIVATE = 0x10
FR_NOT_ENUM = 0x20
def loadfont(fontpath, private=True, enumerable=False):
'''
Makes fonts located in file `fontpath` available to the font system.
`private` if True, other processes cannot see this font, and this
font will be unloaded when the process dies
`enumerable` if True, this font will appear when enumerating fonts
See https://msdn.microsoft.com/en-us/library/dd183327(VS.85).aspx
'''
# This function was taken from
# https://github.com/ifwe/digsby/blob/f5fe00244744aa131e07f09348d10563f3d8fa99/digsby/src/gui/native/win/winfonts.py#L15
# This function is written for Python 2.x. For 3.x, you
# have to convert the isinstance checks to bytes and str
if isinstance(fontpath, str):
pathbuf = create_string_buffer(fontpath)
AddFontResourceEx = windll.gdi32.AddFontResourceExA
elif isinstance(fontpath, unicode):
pathbuf = create_unicode_buffer(fontpath)
AddFontResourceEx = windll.gdi32.AddFontResourceExW
else:
raise TypeError('fontpath must be of type str or unicode')
flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0)
numFontsAdded = AddFontResourceEx(byref(pathbuf), flags, 0)
return bool(numFontsAdded)