From b1f5ee904348cdb6e899af005c4f8e628b66da8f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Aug 2023 17:00:04 +1000 Subject: [PATCH] Added font_size keyword arguments to ImageDraw text methods --- Tests/images/imagedraw_default_font_size.png | Bin 0 -> 1999 bytes Tests/test_imagedraw.py | 29 +++++++++++- src/PIL/ImageDraw.py | 44 ++++++++++++++----- 3 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 Tests/images/imagedraw_default_font_size.png diff --git a/Tests/images/imagedraw_default_font_size.png b/Tests/images/imagedraw_default_font_size.png new file mode 100644 index 0000000000000000000000000000000000000000..f695b5cd6ff2ebc6b50036a17e6c7d6e4b520404 GIT binary patch literal 1999 zcmV;=2Qc`FP)X0ssI2)g9N-000M;NklZVjGXJ%$vTU!?s1j8_qNc6|jEkpie zb;JH)etsTB(dW;fA3b`Myt~usym8~k;x*tGCBYh9l5}CSEVlqj^sAfS z=u%}_JT%yxOix2$mw*N z&1R)i85b89G?7Rof?oKcpfL%Ccs!n3t+raN9*^h!`}b8Rtym`~r)dhy)R^YfFFlZ8T|*Xxx^r7-O0&!3e_Wm;O=-o1Mr4o6E%OV}&~Q&^Z6 zM61<~kB=uOCm%d`(Btu3zI++#oSK^I?(WXY$`S|!Jv}{MuQx3%Eo}YSY_`>EeemEx zW@e^9Akb>HlarI{*RKy-Qv4`E5HiZ~SpX~+%V03{_xFd@ACjPpvazudMN!a}%jJ`k zlW=onXJ=y=#^>{cx(kIuy0<{LZ^_<%-Ye1A86A zFr(23mCIx@v)LRr3&9i?>;-VST=n(!pnd7mrMkL07}H=dtXj1Sn5$Q>24^iW3F_a{ z((>iY7wDLfkl^$APM$m&sFT1X2tr1AU^T>IvBhFxGMQoZ2eL9~FTiTGu3ftpw2O<2 z)oS(J+#E3VdcD)>6bJ+p6BB`sQmIrbm9ki@)YMcuozCO&qNAe;5-pOFl9ES{9@*`7 z*rQM=L?Tg9QBh-KBZ45$o;`!gO(qlk`6ggtQy}B@;>C;8r%xLUhPJjgu~>{B8Wnilym@m_M>d=N^5x5kiHYj!>awyjE|&}6 z@ce*Vb1^U&43o)(?*ZnfO`CveG#cU1{QNwPMl@>x`6>La*Rf;AT3cJiVzJ3&QYaJ~ zH*WNk4f*!%8$4+U>d#;>@Mk}QAk)*+_$^8XGC>HGsINdE&}cO9GeLTKI$qq?ty@7mA|j%opdge01VP9gP6&eZ_4SpNmEqqh zD=I2{KHtE=02%k7SqP@E7_S{Wb_@;cWFxYfB_uG{V2w{IVrxkJJRAyy7yu~;=VH5C;VPNx&!PoRI@ zx^=-d!Fw5#$=tPTS6yA5&*y{JD+EDua&qS8<|GmckH^c&$r&9T9UB{qh=_ph_*dOm zuU>un^l8tYJzOsL;>C*=iv`0lko(@fdv3S8yu3UmB}Fcm8w>_`(ee3wGMOwYDhik` zm#eR@FEKGOs9JnFaQhw}9tOAX^XJd|-M&Lztq8IZOku%Z2!cdLMovvl>2$jE^z@93 zjCb$eX|-CY({8t`RH}@OjI6Az{{DUxML8T!*!t(?<@tO*rBcb~^LOvwt=H?v$H&3) zB7e~#2tr0VjHA(L?%cT(k0Y%9si~2P}ECfMfVq)6c+h=BGzJLFI`}XZ? z*RH`OqE@TDUThY!`&)%fp}1dB3M z7J?}(*b9)HoZQ>nYq#5NHd{wW2mIZ@Fia|ys#GeQ&E|AEySuxSl9EW)zoevObaWI9 z$z(G4GEII_5(FWmoXmI1Q2NKl#ts}ffKdDkA@~Hg+z5XUrJ(r3P>Yg+f`WpAf`WpA hf`WpAf`Ve%@fWx;{FE*3h&liO002ovPDHLkV1h)W>~#PD literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index f4e9b36e2..e59ad5d43 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -1,8 +1,9 @@ +import contextlib import os.path import pytest -from PIL import Image, ImageColor, ImageDraw, ImageFont +from PIL import Image, ImageColor, ImageDraw, ImageFont, features from .helper import ( assert_image_equal, @@ -1344,6 +1345,32 @@ def test_setting_default_font(): assert isinstance(draw.getfont(), ImageFont.load_default().__class__) +def test_default_font_size(): + freetype_support = features.check_module("freetype2") + text = "Default font at a specific size." + + im = Image.new("RGB", (220, 25)) + draw = ImageDraw.Draw(im) + with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError): + draw.text((0, 0), text, font_size=16) + assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png") + + with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError): + assert draw.textlength(text, font_size=16) == 216 + + with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError): + assert draw.textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19) + + im = Image.new("RGB", (220, 25)) + draw = ImageDraw.Draw(im) + with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError): + draw.multiline_text((0, 0), text, font_size=16) + assert_image_equal_tofile(im, "Tests/images/imagedraw_default_font_size.png") + + with contextlib.nullcontext() if freetype_support else pytest.raises(ImportError): + assert draw.multiline_textbbox((0, 0), text, font_size=16) == (0, 3, 216, 19) + + @pytest.mark.parametrize("bbox", BBOX) def test_same_color_outline(bbox): # Prepare shape diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 7d1790faa..fbf320d72 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -113,6 +113,15 @@ class ImageDraw: self.font = ImageFont.load_default() return self.font + def _getfont(self, font_size): + if font_size is not None: + from . import ImageFont + + font = ImageFont.load_default(font_size) + else: + font = self.getfont() + return font + def _getink(self, ink, fill=None): if ink is None and fill is None: if self.fill: @@ -456,6 +465,13 @@ class ImageDraw: **kwargs, ): """Draw text.""" + if embedded_color and self.mode not in ("RGB", "RGBA"): + msg = "Embedded color supported only in RGB and RGBA modes" + raise ValueError(msg) + + if font is None: + font = self._getfont(kwargs.get("font_size")) + if self._multiline_check(text): return self.multiline_text( xy, @@ -473,13 +489,6 @@ class ImageDraw: embedded_color, ) - if embedded_color and self.mode not in ("RGB", "RGBA"): - msg = "Embedded color supported only in RGB and RGBA modes" - raise ValueError(msg) - - if font is None: - font = self.getfont() - def getink(fill): ink, fill = self._getink(fill) if ink is None: @@ -570,6 +579,8 @@ class ImageDraw: stroke_width=0, stroke_fill=None, embedded_color=False, + *, + font_size=None, ): if direction == "ttb": msg = "ttb direction is unsupported for multiline text" @@ -584,6 +595,9 @@ class ImageDraw: msg = "anchor not supported for multiline text" raise ValueError(msg) + if font is None: + font = self._getfont(font_size) + widths = [] max_width = 0 lines = self._multiline_split(text) @@ -645,6 +659,8 @@ class ImageDraw: features=None, language=None, embedded_color=False, + *, + font_size=None, ): """Get the length of a given string, in pixels with 1/64 precision.""" if self._multiline_check(text): @@ -655,7 +671,7 @@ class ImageDraw: raise ValueError(msg) if font is None: - font = self.getfont() + font = self._getfont(font_size) mode = "RGBA" if embedded_color else self.fontmode return font.getlength(text, mode, direction, features, language) @@ -672,12 +688,17 @@ class ImageDraw: language=None, stroke_width=0, embedded_color=False, + *, + font_size=None, ): """Get the bounding box of a given string, in pixels.""" if embedded_color and self.mode not in ("RGB", "RGBA"): msg = "Embedded color supported only in RGB and RGBA modes" raise ValueError(msg) + if font is None: + font = self._getfont(font_size) + if self._multiline_check(text): return self.multiline_textbbox( xy, @@ -693,8 +714,6 @@ class ImageDraw: embedded_color, ) - if font is None: - font = self.getfont() mode = "RGBA" if embedded_color else self.fontmode bbox = font.getbbox( text, mode, direction, features, language, stroke_width, anchor @@ -714,6 +733,8 @@ class ImageDraw: language=None, stroke_width=0, embedded_color=False, + *, + font_size=None, ): if direction == "ttb": msg = "ttb direction is unsupported for multiline text" @@ -728,6 +749,9 @@ class ImageDraw: msg = "anchor not supported for multiline text" raise ValueError(msg) + if font is None: + font = self._getfont(font_size) + widths = [] max_width = 0 lines = self._multiline_split(text)