(5) действительно выглядит сложно, если не считать вставки фиктивных узких мест в строку (что нарушит кернинг) или использования чего-то гораздо более высокого уровня, например, рендеринга SVG или HTML / CSS.
Однако, если вы не возражаете запачкать руки, довольно легко взломать рендерер freetype PIL и добавить горизонтальное пространство. См. _imagingft.c ; после следующего кода в font_getsize и font_render:
if (kerning && last_index && index) {
FT_Vector delta;
FT_Get_Kerning(self->face, last_index, index, ft_kerning_default,
&delta);
x += delta.x >> 6;
}
Добавить:
if (last_index && index) {
x += tracking;
}
Попробуйте сначала с простым целым числом для отслеживания (вероятно, довольно большим, судя по тому, что '>> 6'); скомпилируйте и посмотрите, работает ли он. Следующим шагом будет получение значения отслеживания в функцию C из Python, для чего вам придется изменить вызов ParseTuple в font_render на:
long tracking;
if (!PyArg_ParseTuple(args, "Ol|il:render", &string, &id, &mask, &tracking))
return NULL;
И в font_getsize:
long tracking;
if (!PyArg_ParseTuple(args, "O|l:getsize", &string, &tracking))
return NULL;
Тогда посмотрите, какой интерфейс Python вам нужен. Это тривиальный, но довольно утомительный случай добавления дополнительного аргумента 'tracking' через каждый уровень интерфейса, например:
def truetype(filename, size, index=0, encoding="", tracking= 0): # added optional tracking
"Load a truetype font file."
try:
return FreeTypeFont(filename, size, index, encoding, tracking) # added tracking
...
class FreeTypeFont:
"FreeType font wrapper (requires _imagingft service)"
def __init__(self, file, size, index=0, encoding="", tracking= 0): # added tracking
import _imagingft
self.font = _imagingft.getfont(file, size, index, encoding)
self.tracking= tracking # add this line
...
def getmask2(self, text, mode="", fill=Image.core.fill):
size, offset = self.font.getsize(text, self.tracking) # use tracking
im = fill("L", size, 0)
self.font.render(text, im.id, mode=="1", self.tracking) # use tracking
return im, offset
Я не проверял ничего из этого! Если это работает, возможно, стоит отправить его как патч.