Home > front end >  Load font file with Windows api Python
Load font file with Windows api Python

Time:01-26

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.

CodePudding user response:

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)
  •  Tags:  
  • Related