mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-06 21:03:18 +03:00
Merge bc05a88ce6
into 086e05f42f
This commit is contained in:
commit
a224c1fc37
BIN
Tests/images/multiline_text_justify_anchor.png
Normal file
BIN
Tests/images/multiline_text_justify_anchor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -267,6 +267,23 @@ def test_render_multiline_text_align(
|
||||||
assert_image_similar_tofile(im, f"Tests/images/multiline_text{ext}.png", 0.01)
|
assert_image_similar_tofile(im, f"Tests/images/multiline_text{ext}.png", 0.01)
|
||||||
|
|
||||||
|
|
||||||
|
def test_render_multiline_text_justify_anchor(
|
||||||
|
font: ImageFont.FreeTypeFont,
|
||||||
|
) -> None:
|
||||||
|
im = Image.new("RGB", (280, 240))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
for xy, anchor in (((0, 0), "la"), ((140, 80), "ma"), ((280, 160), "ra")):
|
||||||
|
draw.multiline_text(
|
||||||
|
xy,
|
||||||
|
"hey you you are awesome\nthis looks awkward\nthis\nlooks awkward",
|
||||||
|
font=font,
|
||||||
|
anchor=anchor,
|
||||||
|
align="justify",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_image_equal_tofile(im, "Tests/images/multiline_text_justify_anchor.png")
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_align(font: ImageFont.FreeTypeFont) -> None:
|
def test_unknown_align(font: ImageFont.FreeTypeFont) -> None:
|
||||||
im = Image.new(mode="RGB", size=(300, 100))
|
im = Image.new(mode="RGB", size=(300, 100))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
|
@ -702,8 +702,7 @@ class ImageDraw:
|
||||||
font_size: float | None,
|
font_size: float | None,
|
||||||
) -> tuple[
|
) -> tuple[
|
||||||
ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont,
|
ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont,
|
||||||
str,
|
list[tuple[tuple[float, float], str, AnyStr]],
|
||||||
list[tuple[tuple[float, float], AnyStr]],
|
|
||||||
]:
|
]:
|
||||||
if direction == "ttb":
|
if direction == "ttb":
|
||||||
msg = "ttb direction is unsupported for multiline text"
|
msg = "ttb direction is unsupported for multiline text"
|
||||||
|
@ -753,13 +752,7 @@ class ImageDraw:
|
||||||
left = xy[0]
|
left = xy[0]
|
||||||
width_difference = max_width - widths[idx]
|
width_difference = max_width - widths[idx]
|
||||||
|
|
||||||
# first align left by anchor
|
# align by align parameter
|
||||||
if anchor[0] == "m":
|
|
||||||
left -= width_difference / 2.0
|
|
||||||
elif anchor[0] == "r":
|
|
||||||
left -= width_difference
|
|
||||||
|
|
||||||
# then align by align parameter
|
|
||||||
if align in ("left", "justify"):
|
if align in ("left", "justify"):
|
||||||
pass
|
pass
|
||||||
elif align == "center":
|
elif align == "center":
|
||||||
|
@ -770,8 +763,15 @@ class ImageDraw:
|
||||||
msg = 'align must be "left", "center", "right" or "justify"'
|
msg = 'align must be "left", "center", "right" or "justify"'
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
if align == "justify" and width_difference != 0:
|
if align == "justify" and width_difference != 0 and idx != len(lines) - 1:
|
||||||
words = line.split(" " if isinstance(text, str) else b" ")
|
words = line.split(" " if isinstance(text, str) else b" ")
|
||||||
|
if len(words) > 1:
|
||||||
|
# align left by anchor
|
||||||
|
if anchor[0] == "m":
|
||||||
|
left -= max_width / 2.0
|
||||||
|
elif anchor[0] == "r":
|
||||||
|
left -= max_width
|
||||||
|
|
||||||
word_widths = [
|
word_widths = [
|
||||||
self.textlength(
|
self.textlength(
|
||||||
word,
|
word,
|
||||||
|
@ -783,16 +783,23 @@ class ImageDraw:
|
||||||
)
|
)
|
||||||
for word in words
|
for word in words
|
||||||
]
|
]
|
||||||
|
word_anchor = "l" + anchor[1]
|
||||||
width_difference = max_width - sum(word_widths)
|
width_difference = max_width - sum(word_widths)
|
||||||
for i, word in enumerate(words):
|
for i, word in enumerate(words):
|
||||||
parts.append(((left, top), word))
|
parts.append(((left, top), word_anchor, word))
|
||||||
left += word_widths[i] + width_difference / (len(words) - 1)
|
left += word_widths[i] + width_difference / (len(words) - 1)
|
||||||
else:
|
top += line_spacing
|
||||||
parts.append(((left, top), line))
|
continue
|
||||||
|
|
||||||
|
# align left by anchor
|
||||||
|
if anchor[0] == "m":
|
||||||
|
left -= width_difference / 2.0
|
||||||
|
elif anchor[0] == "r":
|
||||||
|
left -= width_difference
|
||||||
|
parts.append(((left, top), anchor, line))
|
||||||
top += line_spacing
|
top += line_spacing
|
||||||
|
|
||||||
return font, anchor, parts
|
return font, parts
|
||||||
|
|
||||||
def multiline_text(
|
def multiline_text(
|
||||||
self,
|
self,
|
||||||
|
@ -817,7 +824,7 @@ class ImageDraw:
|
||||||
*,
|
*,
|
||||||
font_size: float | None = None,
|
font_size: float | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
font, anchor, lines = self._prepare_multiline_text(
|
font, lines = self._prepare_multiline_text(
|
||||||
xy,
|
xy,
|
||||||
text,
|
text,
|
||||||
font,
|
font,
|
||||||
|
@ -832,7 +839,7 @@ class ImageDraw:
|
||||||
font_size,
|
font_size,
|
||||||
)
|
)
|
||||||
|
|
||||||
for xy, line in lines:
|
for xy, anchor, line in lines:
|
||||||
self.text(
|
self.text(
|
||||||
xy,
|
xy,
|
||||||
line,
|
line,
|
||||||
|
@ -947,7 +954,7 @@ class ImageDraw:
|
||||||
*,
|
*,
|
||||||
font_size: float | None = None,
|
font_size: float | None = None,
|
||||||
) -> tuple[float, float, float, float]:
|
) -> tuple[float, float, float, float]:
|
||||||
font, anchor, lines = self._prepare_multiline_text(
|
font, lines = self._prepare_multiline_text(
|
||||||
xy,
|
xy,
|
||||||
text,
|
text,
|
||||||
font,
|
font,
|
||||||
|
@ -964,7 +971,7 @@ class ImageDraw:
|
||||||
|
|
||||||
bbox: tuple[float, float, float, float] | None = None
|
bbox: tuple[float, float, float, float] | None = None
|
||||||
|
|
||||||
for xy, line in lines:
|
for xy, anchor, line in lines:
|
||||||
bbox_line = self.textbbox(
|
bbox_line = self.textbbox(
|
||||||
xy,
|
xy,
|
||||||
line,
|
line,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user