diff --git a/Tests/test_imagetext.py b/Tests/test_imagetext.py index 699c4cba544..e55299469c2 100644 --- a/Tests/test_imagetext.py +++ b/Tests/test_imagetext.py @@ -170,6 +170,16 @@ def test_wrap_height() -> None: assert text.text == "Text does\nnot fit" +def test_wrap_height_blank_line(layout_engine: ImageFont.Layout) -> None: + font = ImageFont.truetype(FONT_PATH, 10, layout_engine=layout_engine) + text = ImageText.Text("A\n\nB", font) + + wrapped = text.wrap(100, 10) + assert wrapped is not None + assert wrapped.text == "\nB" + assert text.text == "A" + + def test_wrap_scaling_unsupported() -> None: font = ImageFont.load_default_imagefont() text = ImageText.Text("Hello World!", font) @@ -227,6 +237,9 @@ def test_wrap_grow() -> None: with pytest.raises(ValueError, match="Text could not be scaled"): text.wrap(50, 10, "grow") + text.wrap(50, 30, "grow") + assert text.get_bbox()[3] <= 30 + text = ImageText.Text("Hello World!") assert text.wrap(50, 50, ("grow", 18)) is None assert isinstance(text.font, ImageFont.FreeTypeFont) diff --git a/src/PIL/ImageText.py b/src/PIL/ImageText.py index 10297d3f282..385491771ce 100644 --- a/src/PIL/ImageText.py +++ b/src/PIL/ImageText.py @@ -50,11 +50,15 @@ def __init__( if newlines: if not self.add_line(line): break + newlines_all_fit = True for i, line in enumerate(newlines): if i != 0 and not self.add_line(emptystring): + newlines_all_fit = False break self.position += len(line) word = word[len(line) :] + if not newlines_all_fit: + break line = emptystring new_line = line + word @@ -85,7 +89,7 @@ def __init__( def add_line(self, line: AnyStr) -> bool: lines = self.lines + [line] if self.height is not None: - last_line_y = self.text._split(lines=lines)[-1].y + last_line_y = self.text._split(lines=lines, font=self.font)[-1].y last_line_height = self.text._get_bbox(line, self.font)[3] if last_line_y + last_line_height > self.height: return False @@ -331,6 +335,7 @@ def _split( anchor: str | None = None, align: str = "left", lines: list[str] | list[bytes] | None = None, + font: ImageFont.BaseImageFont | None = None, ) -> list[_Line]: if anchor is None: anchor = "lt" if self.direction == "ttb" else "la" @@ -351,9 +356,11 @@ def _split( msg = "anchor not supported for multiline text" raise ValueError(msg) + if font is None: + font = self.font fontmode = self._get_fontmode() line_spacing = ( - self.font.getbbox( + font.getbbox( "A", fontmode, None, @@ -376,7 +383,7 @@ def _split( widths = [] max_width: float = 0 for line in lines: - line_width = self.font.getlength( + line_width = font.getlength( line, fontmode, self.direction, self.features, self.language ) widths.append(line_width) @@ -420,7 +427,7 @@ def _split( left -= max_width word_widths = [ - self.font.getlength( + font.getlength( word, fontmode, self.direction,