python-pillow / python-pillow/Pillow

Kerning woes

Open
#9,898 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Font Rendering
Dominant language
Python
Stars
13.8k
Forks
2.5k
Avg merge
2d 8h
Merged PRs (30d)
89

Description

I am trying to draw some text with Pillow, but the result has some jarring kerning issues. See the image:

Image

At bigger sizes the distance between the letter P and the letter o in the word "Power" is as big as half a space, give or take. At lower sizes, the distance between the letter o and the letters lt in the word bolt is also pretty huge (particularly in the line that is 15px or 16px in size).

This is with Noto Sans, but I also tried Droid Sans, Adwaita Sans and Open Sans and they all had this problem, usually with the same letter clusters, although the problem was less prominent in Open Sans.

I do not have this problem with apps on my system that use these fonts. I attached image showing how Kate, Geany and Libre Office Writer display that string and the kerning there looks ok:

Image

The sizes in the apps are standard 12pts, so are the equivalent of the 16px string in Pillow.

I am on Linux (kernel version: 7.1.9-354.current). This is what python3 -m PIL.report says:

--------------------------------------------------------------------
Pillow 12.3.0
Python 3.14.0 (main, Oct 25 2025, 05:06:07) [GCC 15.1.1 20250508]
--------------------------------------------------------------------
...
--------------------------------------------------------------------
--- PIL CORE support ok, compiled for 12.3.0
--- TKINTER support ok, loaded 8.6
--- FREETYPE2 support ok, loaded 2.14.3
--- LITTLECMS2 support ok, loaded 2.19
--- WEBP support ok, loaded 1.6.0
--- AVIF support ok, loaded 1.4.2
--- JPEG support ok, compiled for libjpeg-turbo 3.1.4.1
--- OPENJPEG (JPEG2000) support ok, loaded 2.5.4
--- ZLIB (PNG/ZIP) support ok, loaded 1.3.1.zlib-ng, compiled for zlib-ng 2.3.3
--- LIBTIFF support ok, loaded 4.7.1
--- RAQM (Bidirectional Text) support ok, loaded 0.10.5, fribidi 1.0.15, harfbuzz 14.2.1
*** LIBIMAGEQUANT (Quantization method) support not installed
--- XCB (X protocol) support ok
--------------------------------------------------------------------

This is the code I used to generate the example image:

from PIL import Image, ImageDraw, ImageFont, ImageText

image = Image.new("RGBA", (220, 140), "#fff")
increments = [0, 1, 2, 3, 4, 8, 12]
y = 5
for i in increments:
    font_size = 12 + i
    font = ImageFont.truetype(
        "/usr/share/fonts/truetype/noto-sans-ttf/NotoSans-Regular.ttf",
        font_size,
        layout_engine=ImageFont.Layout.RAQM,
    )
    text_draw = ImageDraw.Draw(image)
    im_text = ImageText.Text(f"Power bolt ({12 + i}px)", font)
    text_draw.text((5, y), im_text, anchor="la", font=font, fill="#000")
    y += font_size
image.save("power_bolt_pillow_raqm.png")

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided Pillow script with ImageFont.Layout.RAQM and inspect the output alongside python3 -m PIL.report. Trace the ImageText.Text and ImageDraw.text entry points, focusing on how RAQM and the reported FreeType support handle the shown letter pairs. Done means identifying and correcting the kerning discrepancy, with the reproduction case demonstrating consistent spacing across the listed font sizes.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.