From 1551e120ae0a295ae98c65ce5d39c90656d79514 Mon Sep 17 00:00:00 2001 From: nulano Date: Wed, 7 Oct 2020 22:43:29 +0100 Subject: [PATCH] add textlength and textbbox to ImageDraw --- .../test_combine_multiline_lm_center.png | Bin 4132 -> 4160 bytes .../images/test_combine_multiline_lm_left.png | Bin 4117 -> 4223 bytes .../test_combine_multiline_lm_right.png | Bin 4139 -> 4170 bytes .../test_combine_multiline_mm_center.png | Bin 4107 -> 4243 bytes .../images/test_combine_multiline_mm_left.png | Bin 4100 -> 4216 bytes .../test_combine_multiline_mm_right.png | Bin 4102 -> 4247 bytes .../test_combine_multiline_rm_center.png | Bin 4105 -> 4160 bytes .../images/test_combine_multiline_rm_left.png | Bin 4110 -> 4149 bytes .../test_combine_multiline_rm_right.png | Bin 4101 -> 4215 bytes Tests/test_imagefont.py | 26 ++- Tests/test_imagefontctl.py | 24 ++- src/PIL/ImageDraw.py | 153 ++++++++++++++++-- 12 files changed, 185 insertions(+), 18 deletions(-) diff --git a/Tests/images/test_combine_multiline_lm_center.png b/Tests/images/test_combine_multiline_lm_center.png index f293f8d5f1581d7b588ac9bdd85d2e7a0c3dfd99..7b1e9c4e42f69874b4c508d16bc85527d5d902b7 100644 GIT binary patch literal 4160 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 CJA=Fc literal 4132 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 literal 4117 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 diff --git a/Tests/images/test_combine_multiline_lm_right.png b/Tests/images/test_combine_multiline_lm_right.png index 73e2ca9d04d5b019cbcbe944060b764b2ea71aee..7caf5cb742a27f001106cc3ade926f2f177e71fb 100644 GIT binary patch literal 4170 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 diff --git a/Tests/images/test_combine_multiline_mm_center.png b/Tests/images/test_combine_multiline_mm_center.png index 46ec20173395cbe8f1f0327e488078017e3d0339..a859e9570c840c2f3ff8c1078a4c216707dfe86f 100644 GIT binary patch literal 4243 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 T-aH8YY>?KX<8lAr0RHTE literal 4107 zcmeHKS6EY79!Jr^23STI`Y4uFN)!Y^2z;(60zw?6lLQNGzz{kl5Kweg2BnB3hL#<{ z1f&P)9X^^75+MYUgh&g7DiDZ-5caS;`|UpL!#>Qs%|mi;PQH82zx>Mo#$C6wl-;Ae zM@mXc*6OOo4JoN@Nn4*?+rf%F=ht-b-D_oW(LN$$juYwAzp~l1SY}IeOPe@uu&k`4 zc_Qvsa$oKvz3klmgEc=ohCKYReeYd;D_U;u)KP`7GEsI;Z|VvA1l_dKrQSBCURj)7 zE7Q=Ra(QD+Y@|xDqjYd1)HD(s%}Bv!1ffhv%JSMb};{Zu-(M1#bv4tlF7D<{O1b$JB!WEi)#wGCCGVaE0;~pK}{1LMUoGGfMAvSR5@4Ul?AWuSHKWeqH8uoAB-#oI7W4Zx0XZ zIzHBsSe&14bL=1#D{!s~7~xY$S#7sdq+QDeQoHg>O1{z{jdi>7 zqeL`ZAL$;>3C*@lRM+$9{CF>iO!gY2dd4g0h^Dd=4gJ}#qH&DBU(|^DdXZ#?vtxXT z(}EDMRS14~>N`|{3TFp))M1w8qVs{ST)up{9=kIAx!e!@1B0$GV`F2Xk*m!9e$*g! zqPS7wS{pXU>rR(P2C}OH%e=ZT%)RTg6Mv1fEHOgb;I)aSn5Et~Hi^L|npd7hh!;Da z$g1E|e@aeSdQYRdVfT&4>bOpDWQZJfipN0ypMM(}RaH^18aZ zb{kJLRb>@9UDW6e(aOvKy7jTFr>Cb5R3Yg3kn;bpk#>8^%gX_}x@j~m9UT*NfwMlT5(TOq1{gb!ZKh8U!dsRN=F$m;H+C4Skup_Dc<->3r`jj8|`t zm5lrsfZ#Nvz&qHmmPfnqwm<6{9ZAx3{dP$G~D#%p=uTt;fn?B ztYin#Bpd4>wR)eAubJ@x**FlLYo$MK_R`6L-3l_F%Dm~}TpS^*{%gzL#42lmQQlz@ zz`j~gsaPyNKOCW%Sph^Za=v=xtQyZ%?Hr}Nm<6P;F;2mB(a_O<^ zlH<~q=(P!g;Iu9KOn)VsJ4uQ$gPLp+tLsbdPuY5#>+*6|B}PqT+w_Fsy^+Fs)F>w% z-LUq>gwkU)_6!u`9L^kiY)AZ+u!Uh|c`*8yK9r~6xzLc{pI$2VBg@}^0c z3H5&lkD1IQ7z6Zhy#mMjD6malI{HQ*B?~*P=pL0UX@?;Y2rH{D&_zNUCpmIQymZJk zlMj#zqmvh=O`~Z92)%A_qqIX^OIv$OY$tm%Zx#c2hAwq#4t`cMwgTG4b66%X7++O_ zVneW4iFi%ryuYdBER)5;~?)62!f~O}e*F%dx<@%*(cqMgk}x!t9H3b6){QA8PzQjm2PGzj-tG z>x@Q>co7(7Mive@ga{~YbrYC+nB{&0OhNl|m4&+Ho)fFR?A9ZccLMpKz?L`WpK}1n zt7>X$_*>*x=5(J48t(-2jC#-r2o~I!iNChiM+&pf-n}y2CXoMz;?x){5B%KzOewhY z`4*jswdp3|{tEI>GLi|Vy|}LN`v)|y*gHCsy-h-<0_MsGfKxSARD=OvHJ5xFI|MTg zK8Sf9T&SI9vEsmZI zon|uS+u)INl7ZclS`5j6$KdQm`Qk%O!2h46VcGlXK7=~x8E^cYWi%mj2E&_P_2 zm=_>wS3l^}?~T%LEsnOy6qf_1e;_SmI783-c(ULMeSg$Ky)f;EaX|abwVj!xqoW{q zZFM>0CWC^MmZk^NTBlE^xsh60T2i%~@TsYpf$d6`a3gc`O)5>7CWe=R_&-cqzr^Fo zkRpv608IKZ{C8BU-trSGeYK&HBIrJQC1S5@N)2yFJ*Pv&Z6kAw_^VR(alzc diff --git a/Tests/images/test_combine_multiline_mm_left.png b/Tests/images/test_combine_multiline_mm_left.png index ad2fa7a3959230a7d438fa692d9114e5b06d293f..aadb5191f0e7df6ae1838ca6b04745268de17728 100644 GIT binary patch literal 4216 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 sq)Epb{z}gH3sL0nTmDag9FofH^0IWV!Z literal 4102 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

Gc&a5H1zmVybWfk{$63_yW#%@t&MX| literal 4105 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 KSMo2rM*I^!sCPC1 diff --git a/Tests/images/test_combine_multiline_rm_left.png b/Tests/images/test_combine_multiline_rm_left.png index 901410fab4ec39c441258accfc5a604be95afc6a..b8c3b5b143d2b7b67116daaef4f7b3f119777494 100644 GIT binary patch literal 4149 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 literal 4101 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 diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 5dd062459..adb75a1ff 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -221,12 +221,15 @@ class TestImageFont: "Tests/fonts/" + font, size, layout_engine=self.LAYOUT_ENGINE ) + im = Image.new(mode, (1, 1), 0) + d = ImageDraw.Draw(im) + if self.LAYOUT_ENGINE == ImageFont.LAYOUT_BASIC: - length = f.getlength(text, mode) + length = d.textlength(text, f) assert length == self.metrics["getlength"][length_basic_index] else: # disable kerning, kerning metrics changed - length = f.getlength(text, mode, features=["-kern"]) + length = d.textlength(text, f, features=["-kern"]) assert length == length_raqm def test_render_multiline(self): @@ -813,20 +816,20 @@ class TestImageFont: else: width, height = (128, 44) + bbox_expected = (left, top, left + width, top + height) + f = ImageFont.truetype( "Tests/fonts/NotoSans-Regular.ttf", 48, layout_engine=self.LAYOUT_ENGINE ) - # test getbbox - assert f.getbbox(text, anchor=anchor) == (left, top, left + width, top + height) - - # test render im = Image.new("RGB", (200, 200), "white") d = ImageDraw.Draw(im) d.line(((0, 100), (200, 100)), "gray") d.line(((100, 0), (100, 200)), "gray") d.text((100, 100), text, fill="black", anchor=anchor, font=f) + assert d.textbbox((0, 0), text, f, anchor=anchor) == bbox_expected + with Image.open(path) as expected: assert_image_similar(im, expected, 7) @@ -879,13 +882,24 @@ class TestImageFont: pytest.raises(ValueError, lambda: font.getmask2("hello", anchor=anchor)) pytest.raises(ValueError, lambda: font.getbbox("hello", anchor=anchor)) pytest.raises(ValueError, lambda: d.text((0, 0), "hello", anchor=anchor)) + pytest.raises( + ValueError, lambda: d.textbbox((0, 0), "hello", anchor=anchor) + ) pytest.raises( ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor) ) + pytest.raises( + ValueError, + lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor), + ) for anchor in ["lt", "lb"]: pytest.raises( ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor) ) + pytest.raises( + ValueError, + lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor), + ) @skip_unless_feature("raqm") diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py index b585a2aa2..7fa5f76ab 100644 --- a/Tests/test_imagefontctl.py +++ b/Tests/test_imagefontctl.py @@ -222,10 +222,12 @@ def test_language(): ids=("None", "ltr", "rtl2", "rtl", "ttb"), ) def test_getlength(mode, text, direction, expected): - try: - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + im = Image.new(mode, (1, 1), 0) + d = ImageDraw.Draw(im) - assert ttf.getlength(text, mode, direction) == expected + try: + assert d.textlength(text, ttf, direction) == expected except ValueError as ex: if ( direction == "ttb" @@ -374,6 +376,8 @@ def test_combine_multiline(anchor, align): d = ImageDraw.Draw(im) d.line(((0, 200), (400, 200)), "gray") d.line(((200, 0), (200, 400)), "gray") + bbox = d.multiline_textbbox((200, 200), text, anchor=anchor, font=f, align=align) + d.rectangle(bbox, outline="red") d.multiline_text((200, 200), text, fill="black", anchor=anchor, font=f, align=align) with Image.open(path) as expected: @@ -396,14 +400,28 @@ def test_anchor_invalid_ttb(): pytest.raises( ValueError, lambda: d.text((0, 0), "hello", anchor=anchor, direction="ttb") ) + pytest.raises( + ValueError, + lambda: d.textbbox((0, 0), "hello", anchor=anchor, direction="ttb"), + ) pytest.raises( ValueError, lambda: d.multiline_text( (0, 0), "foo\nbar", anchor=anchor, direction="ttb" ), ) + pytest.raises( + ValueError, + lambda: d.multiline_textbbox( + (0, 0), "foo\nbar", anchor=anchor, direction="ttb" + ), + ) # ttb multiline text does not support anchors at all pytest.raises( ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor="mm", direction="ttb"), ) + pytest.raises( + ValueError, + lambda: d.multiline_textbbox((0, 0), "foo\nbar", anchor="mm", direction="ttb"), + ) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 1379cf1f7..822ca3edf 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -385,9 +385,6 @@ class ImageDraw: elif anchor[1] in "tb": raise ValueError("anchor not supported for multiline text") - if font is None: - font = self.getfont() - widths = [] max_width = 0 lines = self._multiline_split(text) @@ -395,12 +392,8 @@ class ImageDraw: self.textsize("A", font=font, stroke_width=stroke_width)[1] + spacing ) for line in lines: - line_width = font.getlength( - line, - self.fontmode, - direction=direction, - features=features, - language=language, + line_width = self.textlength( + line, font, direction=direction, features=features, language=language ) widths.append(line_width) max_width = max(max_width, line_width) @@ -487,6 +480,148 @@ class ImageDraw: max_width = max(max_width, line_width) return max_width, len(lines) * line_spacing - spacing + def textlength(self, text, font=None, direction=None, features=None, language=None): + """Get the length of a given string, in pixels with 1/64 precision.""" + if self._multiline_check(text): + raise ValueError("can't measure length of multiline text") + + if font is None: + font = self.getfont() + try: + return font.getlength(text, self.fontmode, direction, features, language) + except AttributeError: + size = self.textsize( + text, font, direction=direction, features=features, language=language + ) + if direction == "ttb": + return size[1] + return size[0] + + def textbbox( + self, + xy, + text, + font=None, + anchor=None, + spacing=4, + align="left", + direction=None, + features=None, + language=None, + stroke_width=0, + ): + """Get the bounding box of a given string, in pixels.""" + if self._multiline_check(text): + return self.multiline_textbbox( + xy, + text, + font, + anchor, + spacing, + align, + direction, + features, + language, + stroke_width, + ) + + if font is None: + font = self.getfont() + bbox = font.getbbox( + text, self.fontmode, direction, features, language, stroke_width, anchor + ) + return bbox[0] + xy[0], bbox[1] + xy[1], bbox[2] + xy[0], bbox[3] + xy[1] + + def multiline_textbbox( + self, + xy, + text, + font=None, + anchor=None, + spacing=4, + align="left", + direction=None, + features=None, + language=None, + stroke_width=0, + ): + if direction == "ttb": + raise ValueError("ttb direction is unsupported for multiline text") + + if anchor is None: + anchor = "la" + elif len(anchor) != 2: + raise ValueError("anchor must be a 2 character string") + elif anchor[1] in "tb": + raise ValueError("anchor not supported for multiline text") + + widths = [] + max_width = 0 + lines = self._multiline_split(text) + line_spacing = ( + self.textsize("A", font=font, stroke_width=stroke_width)[1] + spacing + ) + for line in lines: + line_width = self.textlength( + line, font, direction=direction, features=features, language=language + ) + widths.append(line_width) + max_width = max(max_width, line_width) + + top = xy[1] + if anchor[1] == "m": + top -= (len(lines) - 1) * line_spacing / 2.0 + elif anchor[1] == "d": + top -= (len(lines) - 1) * line_spacing + + bbox = None + + for idx, line in enumerate(lines): + left = xy[0] + width_difference = max_width - widths[idx] + + # first align left by anchor + if anchor[0] == "m": + left -= width_difference / 2.0 + elif anchor[0] == "r": + left -= width_difference + + # then align by align parameter + if align == "left": + pass + elif align == "center": + left += width_difference / 2.0 + elif align == "right": + left += width_difference + else: + raise ValueError('align must be "left", "center" or "right"') + + bbox_line = self.textbbox( + (left, top), + line, + font, + anchor, + direction=direction, + features=features, + language=language, + stroke_width=stroke_width, + ) + if bbox is None: + bbox = bbox_line + else: + bbox = ( + min(bbox[0], bbox_line[0]), + min(bbox[1], bbox_line[1]), + max(bbox[2], bbox_line[2]), + max(bbox[3], bbox_line[3]), + ) + + top += line_spacing + + if bbox is None: + return xy[0], xy[1], xy[0], xy[1] + return bbox + def Draw(im, mode=None): """