My code is for my own use but if someone is having similar issues, I'm sure that it can easily be adapted for your own needs.
My key functions are:
def get_text_width(text_string, font):
return font.getmask(text_string).getbbox()[2]
def kern(name, draw_object, y, space, font, fill):
chars = [char for char in name]
total_width = 0
for char in chars:
width_text = get_text_width(char, font)
total_width += (width_text + int(space))
__, height_text = draw_object.textsize(name, font)
__, offset_y = font.getoffset(name)
height_text += offset_y
width_adjuster = 0
for char in chars:
width_text = get_text_width(char, font)
top_left_x = (473 / 2 - total_width / 2) + width_adjuster
top_left_y = (40 / 2 - height_text / 2) + y
xy = top_left_x, top_left_y
width_adjuster += width_text + int(space)
print(f"char:{char},width_text:{width_text},xy:{xy},width_adjuster:{width_adjuster}")
draw_object.text(xy, char, font=font, fill=fill)
It gives a nice output below. However, it's not entirely precise. The number of pixels between letters will vary slightly with different fonts. I have not found a way to standardize this, so I've just accepted the fact when I enter a value for kerning into my GUI, it is just a scalar relative to the font, not the number of pixels
