Repository: python-pillow/Pillow

Issue:
Provide additional keyword args for ImageDraw.text(...) method for multiline text
The check for `if self._multiline_check(text):` inside of the `ImageDraw.text(...)` method [1] is great, but if True, it goes to the next line `return self.multiline_text(xy, text, fill, font, anchor)` and doesn't allow the user to pass important keyword args to the `multiline_text(...)` function like **align** and **spacing**.  Instead, why not do something like:

``` py
def text(self, xy, text, fill=None, font=None, anchor=None, **kwargs):
    """:param kwargs: additional args to pass to multiline_text if the text is multiline"""
    if self._multiline_check(text):
        return self.multiline_text(xy, text, fill, font, anchor, **kwargs)
```

Then I can call the `.text(...)` function with those additional params:

``` py
draw = ImageDraw.Draw(myImage)
draw.text((0,0), 'hello world', align='left', spacing=5)
```

This would be a passive change to the current `.text(...)` method call.

[1] https://github.com/python-pillow/Pillow/blob/master/PIL/ImageDraw.py#L245



Discussion:

Resolving patch:
diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py
--- a/PIL/ImageDraw.py
+++ b/PIL/ImageDraw.py
@@ -241,9 +241,9 @@ def _multiline_split(self, text):
 
         return text.split(split_character)
 
-    def text(self, xy, text, fill=None, font=None, anchor=None):
+    def text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs):
         if self._multiline_check(text):
-            return self.multiline_text(xy, text, fill, font, anchor)
+            return self.multiline_text(xy, text, fill, font, anchor, *args, **kwargs)
 
         ink, fill = self._getink(fill)
         if font is None:
@@ -288,9 +288,9 @@ def multiline_text(self, xy, text, fill=None, font=None, anchor=None,
     ##
     # Get the size of a given string, in pixels.
 
-    def textsize(self, text, font=None):
+    def textsize(self, text, font=None, *args, **kwargs):
         if self._multiline_check(text):
-            return self.multiline_textsize(text, font)
+            return self.multiline_textsize(text, font, *args, **kwargs)
 
         if font is None:
             font = self.getfont()


Test patch:
diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py
--- a/Tests/test_imagefont.py
+++ b/Tests/test_imagefont.py
@@ -121,6 +121,7 @@ def test_textsize_equal(self):
             size = draw.textsize(txt, ttf)
             draw.text((10, 10), txt, font=ttf)
             draw.rectangle((10, 10, 10 + size[0], 10 + size[1]))
+            del draw
 
             target = 'Tests/images/rectangle_surrounding_text.png'
             target_img = Image.open(target)
@@ -159,12 +160,20 @@ def test_render_multiline_text(self):
 
             self.assert_image_similar(im, target_img, .5)
 
+            # Test that text() can pass on additional arguments
+            # to multiline_text()
+            draw.text((0, 0), TEST_TEXT, fill=None, font=ttf, anchor=None,
+                      spacing=4, align="left")
+            draw.text((0, 0), TEST_TEXT, None, ttf, None, 4, "left")
+            del draw
+
             # Test align center and right
             for align, ext in {"center": "_center",
                                "right": "_right"}.items():
                 im = Image.new(mode='RGB', size=(300, 100))
                 draw = ImageDraw.Draw(im)
                 draw.multiline_text((0, 0), TEST_TEXT, font=ttf, align=align)
+                del draw
 
                 target = 'Tests/images/multiline_text'+ext+'.png'
                 target_img = Image.open(target)
@@ -191,6 +200,12 @@ def test_multiline_size(self):
             self.assertEqual(draw.textsize(TEST_TEXT, font=ttf),
                              draw.multiline_textsize(TEST_TEXT, font=ttf))
 
+            # Test that textsize() can pass on additional arguments
+            # to multiline_textsize()
+            draw.textsize(TEST_TEXT, font=ttf, spacing=4)
+            draw.textsize(TEST_TEXT, ttf, 4)
+            del draw
+
         def test_multiline_width(self):
             ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
             im = Image.new(mode='RGB', size=(300, 100))
@@ -199,6 +214,7 @@ def test_multiline_width(self):
             self.assertEqual(draw.textsize("longest line", font=ttf)[0],
                              draw.multiline_textsize("longest line\nline",
                                                      font=ttf)[0])
+            del draw
 
         def test_multiline_spacing(self):
             ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
@@ -206,6 +222,7 @@ def test_multiline_spacing(self):
             im = Image.new(mode='RGB', size=(300, 100))
             draw = ImageDraw.Draw(im)
             draw.multiline_text((0, 0), TEST_TEXT, font=ttf, spacing=10)
+            del draw
 
             target = 'Tests/images/multiline_text_spacing.png'
             target_img = Image.open(target)
@@ -229,6 +246,7 @@ def test_rotated_transposed_font(self):
             # Rotated font
             draw.font = transposed_font
             box_size_b = draw.textsize(word)
+            del draw
 
             # Check (w,h) of box a is (h,w) of box b
             self.assertEqual(box_size_a[0], box_size_b[1])
@@ -251,6 +269,7 @@ def test_unrotated_transposed_font(self):
             # Rotated font
             draw.font = transposed_font
             box_size_b = draw.textsize(word)
+            del draw
 
             # Check boxes a and b are same size
             self.assertEqual(box_size_a, box_size_b)
@@ -346,6 +365,7 @@ def test_default_font(self):
             # Act
             default_font = ImageFont.load_default()
             draw.text((10, 10), txt, font=default_font)
+            del draw
 
             # Assert
             self.assert_image_equal(im, target_img)