From a90075a66803b30cd02c0607d47c0d912913b6aa Mon Sep 17 00:00:00 2001 From: Frank Henigman Date: Wed, 4 Feb 2026 20:52:52 -0500 Subject: [PATCH 1/2] Add FontFile.to_imagefont(). --- Tests/test_font_pcf.py | 10 ++++++++++ src/PIL/FontFile.py | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index 1be7a4d1e39..5b8832977db 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -76,6 +76,16 @@ def test_draw(request: pytest.FixtureRequest, tmp_path: Path) -> None: assert_image_similar_tofile(im, "Tests/images/test_draw_pbm_target.png", 0) +def test_to_imagefont(request: pytest.FixtureRequest, tmp_path: Path) -> None: + with open(fontname, "rb") as test_file: + pcffont = PcfFontFile.PcfFontFile(test_file) + imgfont = pcffont.to_imagefont() + im = Image.new("L", (130, 30), "white") + draw = ImageDraw.Draw(im) + draw.text((0, 0), message, "black", font=imgfont) + assert_image_similar_tofile(im, "Tests/images/test_draw_pbm_target.png", 0) + + def test_textsize(request: pytest.FixtureRequest, tmp_path: Path) -> None: tempname = save_font(request, tmp_path) font = ImageFont.load(tempname) diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py index 1e0c1c166b5..b50385daac6 100644 --- a/src/PIL/FontFile.py +++ b/src/PIL/FontFile.py @@ -15,10 +15,11 @@ # from __future__ import annotations +import io import os from typing import BinaryIO -from . import Image, _binary +from . import Image, ImageFont, _binary WIDTH = 800 @@ -123,12 +124,33 @@ def save(self, filename: str) -> None: # font metrics with open(os.path.splitext(filename)[0] + ".pil", "wb") as fp: - fp.write(b"PILfont\n") - fp.write(f";;;;;;{self.ysize};\n".encode("ascii")) # HACK!!! - fp.write(b"DATA\n") - for id in range(256): - m = self.metrics[id] - if not m: - puti16(fp, (0,) * 10) - else: - puti16(fp, m[0] + m[1] + m[2]) + self.save_metrics(fp) + + def save_metrics(self, fp: BinaryIO) -> None: + """Save font metrics to a file-like object""" + fp.write(b"PILfont\n") + fp.write(f";;;;;;{self.ysize};\n".encode("ascii")) # HACK!!! + fp.write(b"DATA\n") + for id in range(256): + m = self.metrics[id] + if not m: + puti16(fp, (0,) * 10) + else: + puti16(fp, m[0] + m[1] + m[2]) + + def to_imagefont(self) -> ImageFont.ImageFont: + """Convert to ImageFont""" + + self.compile() + + # font data + if not self.bitmap: + msg = "No bitmap created" + raise ValueError(msg) + + buf = io.BytesIO() + self.save_metrics(buf) + buf.seek(0) + imgfont = ImageFont.ImageFont() + imgfont._load_pilfont_data(buf, self.bitmap) + return imgfont From 3e14bea593449d76c2b3e6e63aafa26e3c0aedcb Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:18:01 +1100 Subject: [PATCH 2/2] Use `assert_image_equal_tofile` when similarity is zero --- Tests/test_font_pcf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index ce5b36413cf..01d56dfd3e5 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -82,7 +82,7 @@ def test_to_imagefont(request: pytest.FixtureRequest, tmp_path: Path) -> None: im = Image.new("L", (130, 30), "white") draw = ImageDraw.Draw(im) draw.text((0, 0), message, "black", font=imgfont) - assert_image_similar_tofile(im, "Tests/images/test_draw_pbm_target.png", 0) + assert_image_equal_tofile(im, "Tests/images/test_draw_pbm_target.png") def test_textsize(request: pytest.FixtureRequest, tmp_path: Path) -> None: