0

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)

Edit

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?

Edit 2

I found out that the function doesn't work even without that constant.

1
  • Look in the Windows headers for the value of the FR_PRIVATE constant. Make sure to read the ctypes documentation, esp. about specifying .argtypes and .restype to specify the argument types. If you let ctypes guess how to convert Python arguments to C it can guess wrong and then "the function doesn't work". Show exactly how you are trying to call the function. Make a minimal reproducible example. Commented Jan 21, 2022 at 0:27

1 Answer 1

2

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)
Sign up to request clarification or add additional context in comments.

1 Comment

If they consider my question to be a duplicate, I have no problem closing it for that reason.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.