Repository: python-pillow/Pillow

Issue:
getmask2() got an unexpected keyword argument 'align'
### What did you do?
Run a py script that uses PIL

### What did you expect to happen?
The script uses PIL to show an image with text

### What actually happened?
Error happened

### What versions of Pillow and Python are you using?
PIL 4.2.1 and Python 3.5.2

Here is the script I am using 
https://github.com/Aioxas/ax-cogs/blob/master/horoscope/horoscope.py

and the traceback is
```python
Exception in command 'tsujiura'
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/discord/ext/commands/core.py", line 50, in wrapped
    ret = yield from coro(*args, **kwargs)
  File "/home/yukirin/Kanon/cogs/horoscope.py", line 152, in _cookie
    self.fortune_process(fortune[0])
  File "/home/yukirin/Kanon/cogs/horoscope.py", line 213, in fortune_process
    draw.text((134, 165), line1, (0, 0, 0), font=font, align="center")
  File "lib/PIL/ImageDraw.py", line 217, in text
    mask, offset = font.getmask2(text, self.fontmode, *args, **kwargs)
TypeError: getmask2() got an unexpected keyword argument 'align'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/discord/ext/commands/bot.py", line 846, in process_commands
    yield from command.invoke(ctx)
  File "/usr/local/lib/python3.5/dist-packages/discord/ext/commands/core.py", line 374, in invoke
    yield from injected(*ctx.args, **ctx.kwargs)
  File "/usr/local/lib/python3.5/dist-packages/discord/ext/commands/core.py", line 54, in wrapped
    raise CommandInvokeError(e) from e
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: getmask2() got an unexpected keyword argument 'align'
```

I fixed it by reverting to PIL 4.0.0, so I assume PIL 4.2.1 breaking it?
(I was asked by the dev of that script I use to post an issue here)





Discussion:
What kind of font are you using?
From https://github.com/Aioxas/ax-cogs/blob/master/horoscope/horoscope.py#L204-L216:
```python
    def fortune_process(self, fortune):
        img = Image.open("data/horoscope/cookie.png")
        draw = ImageDraw.Draw(img)
        font = ImageFont.truetype("data/horoscope/FortuneCookieNF.ttf", 15)
        line = fortune.split()
        sep = " "
        line1 = sep.join(line[:5])
        line2 = sep.join(line[5:10])
        line3 = sep.join(line[10:])
        draw.text((134, 165), line1, (0, 0, 0), font=font, align="center")
        draw.text((134, 180), line2, (0, 0, 0), font=font, align="center")
        draw.text((134, 195), line3, (0, 0, 0), font=font, align="center")
        img.save("data/horoscope/cookie-edit.png")
```

Font is here: https://github.com/Aioxas/ax-cogs/blob/master/horoscope/data/horoscope/FortuneCookieNF.ttf

Reproducible with Pillow 4.2.1 and 4.2.0/Python 2.7.13/macOS Sierra:

```python
from PIL import Image, ImageDraw, ImageFont
img = Image.new("RGB", (400, 400), "white")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("FortuneCookieNF.ttf", 15)
line1 = "some text"
draw.text((134, 165), line1, (0, 0, 0), font=font, align="center")
img.show()
```

And also when changing the font:
```python
from PIL import Image, ImageDraw, ImageFont
img = Image.new("RGB", (400, 400), "white")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("/Library/Fonts/Arial.ttf", 15)
line1 = "some text"
draw.text((134, 165), line1, (0, 0, 0), font=font, align="center")
img.show()
```
```
Traceback (most recent call last):
  File "2639.py", line 6, in <module>
    draw.text((134, 165), line1, (0, 0, 0), font=font, align="center")
  File "/usr/local/lib/python2.7/site-packages/PIL/ImageDraw.py", line 217, in text
    mask, offset = font.getmask2(text, self.fontmode, *args, **kwargs)
TypeError: getmask2() got an unexpected keyword argument 'align'
```

Works with Pillow 4.1.0.
Can be fixed by adding `*args, **kwargs` into:
```python
def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None):
 ```

Resolving patch:
diff --git a/PIL/ImageFont.py b/PIL/ImageFont.py
--- a/PIL/ImageFont.py
+++ b/PIL/ImageFont.py
@@ -36,6 +36,7 @@ class _imagingft_not_installed(object):
     def __getattr__(self, id):
         raise ImportError("The _imagingft C module is not installed")
 
+
 try:
     from . import _imagingft as core
 except ImportError:
@@ -113,7 +114,6 @@ def getmask(self, text, mode="", *args, **kwargs):
         return self.font.getmask(text, mode)
 
 
-
 ##
 # Wrapper for FreeType fonts.  Application code should use the
 # <b>truetype</b> factory function to create font objects.
@@ -162,7 +162,7 @@ def getoffset(self, text):
     def getmask(self, text, mode="", direction=None, features=None):
         return self.getmask2(text, mode, direction=direction, features=features)[0]
 
-    def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None):
+    def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None, *args, **kwargs):
         size, offset = self.font.getsize(text, direction, features)
         im = fill("L", size, 0)
         self.font.render(text, im.id, mode == "1", direction, features)
@@ -250,7 +250,7 @@ def truetype(font=None, size=10, index=0, encoding="",
                      and "armn" (Apple Roman). See the FreeType documentation
                      for more information.
     :param layout_engine: Which layout engine to use, if available:
-                     `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`.                  
+                     `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`.
     :return: A font object.
     :exception IOError: If the file could not be read.
     """


Test patch:
diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py
--- a/Tests/test_imagefont.py
+++ b/Tests/test_imagefont.py
@@ -40,13 +40,15 @@ def __exit__(self, type, value, traceback):
         else:
             delattr(self._parent_obj, self._attr_name)
 
+
 @unittest.skipUnless(HAS_FREETYPE, "ImageFont not Available")
 class TestImageFont(PillowTestCase):
     LAYOUT_ENGINE = ImageFont.LAYOUT_BASIC
 
     # Freetype has different metrics depending on the version.
     # (and, other things, but first things first)
-    METRICS = { ('2', '3'): {'multiline': 30,
+    METRICS = {
+                ('2', '3'): {'multiline': 30,
                              'textsize': 12,
                              'getters': (13, 16)},
                 ('2', '7'): {'multiline': 6.2,
@@ -213,6 +215,14 @@ def test_unknown_align(self):
                                                       font=ttf,
                                                       align="unknown"))
 
+    def test_draw_align(self):
+        im = Image.new('RGB', (300, 100), 'white')
+        draw = ImageDraw.Draw(im)
+        ttf = self.get_font()
+        line = "some text"
+        draw.text((100, 40), line, (0, 0, 0), font=ttf, align='left')
+        del draw
+
     def test_multiline_size(self):
         ttf = self.get_font()
         im = Image.new(mode='RGB', size=(300, 100))
@@ -395,7 +405,7 @@ def test_default_font(self):
 
     def test_getsize_empty(self):
         font = self.get_font()
-        # should not crash. 
+        # should not crash.
         self.assertEqual((0, 0), font.getsize(''))
 
     def _test_fake_loading_font(self, path_to_fake, fontname):
@@ -494,5 +504,6 @@ def test_imagefont_getters(self):
 class TestImageFont_RaqmLayout(TestImageFont):
     LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM
 
+
 if __name__ == '__main__':
     unittest.main()