Allow ImageDraw text() to use ImageText

This commit is contained in:
Andrew Murray 2025-07-21 13:07:38 +10:00
parent 24681a3927
commit 969e468749
3 changed files with 51 additions and 13 deletions

View File

@ -2,9 +2,9 @@ from __future__ import annotations
import pytest
from PIL import ImageFont, ImageText
from PIL import Image, ImageDraw, ImageFont, ImageText
from .helper import skip_unless_feature
from .helper import assert_image_similar_tofile, skip_unless_feature
FONT_PATH = "Tests/fonts/FreeMono.ttf"
@ -39,3 +39,34 @@ def test_get_bbox(font: ImageFont.FreeTypeFont) -> None:
assert ImageText.ImageText("M", font).get_bbox() == (0, 4, 12, 16)
assert ImageText.ImageText("y", font).get_bbox() == (0, 7, 12, 20)
assert ImageText.ImageText("a", font).get_bbox() == (0, 7, 12, 16)
def test_standard_embedded_color(layout_engine: ImageFont.Layout) -> None:
font = ImageFont.truetype(FONT_PATH, 40, layout_engine=layout_engine)
text = ImageText.ImageText("Hello World!", font)
text.embed_color()
im = Image.new("RGB", (300, 64), "white")
draw = ImageDraw.Draw(im)
draw.text((10, 10), text, "#fa6")
assert_image_similar_tofile(im, "Tests/images/standard_embedded.png", 3.1)
@skip_unless_feature("freetype2")
def test_stroke() -> None:
for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items():
# Arrange
im = Image.new("RGB", (120, 130))
draw = ImageDraw.Draw(im)
font = ImageFont.truetype(FONT_PATH, 120)
text = ImageText.ImageText("A", font)
text.stroke(2, stroke_fill)
# Act
draw.text((12, 12), text, "#f00")
# Assert
assert_image_similar_tofile(
im, "Tests/images/imagedraw_stroke_" + suffix + ".png", 3.1
)

View File

@ -6,7 +6,7 @@
The :py:mod:`~PIL.ImageText` module defines a class with the same name. Instances of
this class provide a way to use fonts with text strings or bytes. The result is a
simple API to apply styling to pieces of text and measure them.
simple API to apply styling to pieces of text and measure or draw them.
Example
-------
@ -23,6 +23,10 @@ Example
print(text.get_length()) # 154.0
print(text.get_bbox()) # (-2, 3, 156, 22)
im = Image.new("RGB", text.get_bbox()[2:])
d = ImageDraw.Draw(im)
d.text((0, 0), text, "#f00")
Methods
-------

View File

@ -537,7 +537,7 @@ class ImageDraw:
def text(
self,
xy: tuple[float, float],
text: AnyStr,
text: AnyStr | ImageText.ImageText,
fill: _Ink | None = None,
font: (
ImageFont.ImageFont
@ -558,15 +558,18 @@ class ImageDraw:
**kwargs: Any,
) -> None:
"""Draw text."""
if font is None:
font = self._getfont(kwargs.get("font_size"))
imagetext = ImageText.ImageText(
text, font, self.mode, spacing, direction, features, language
)
if embedded_color:
imagetext.embed_color()
if stroke_width:
imagetext.stroke(stroke_width, stroke_fill)
if isinstance(text, ImageText.ImageText):
imagetext = text
else:
if font is None:
font = self._getfont(kwargs.get("font_size"))
imagetext = ImageText.ImageText(
text, font, self.mode, spacing, direction, features, language
)
if embedded_color:
imagetext.embed_color()
if stroke_width:
imagetext.stroke(stroke_width, stroke_fill)
def getink(fill: _Ink | None) -> int:
ink, fill_ink = self._getink(fill)