Repository: python-pillow/Pillow

Problem statement:
Truetype fonts not being rendered correctly with the TEXT method
### What did you do?
Created an image suitable for the Pimoroni InkyHat display
Added italic text onto the image object at different places

### What did you expect to happen?
The whole of the last character of the text to be displayed as it did to render correctly on Stretch on the Pi Zero
Looking at the font from a Mac (Mojave), the characters look fine.

### What actually happened?
Depending on the length of the text, some or all of the last character is missing when using some italic fonts.  If the text length is around 105 - 110 pixels then you can lose some / all of the very last character.

**Padding out the text string with spaces so it is longer than 110 pixels fixes the issue**

### What are your OS, Python and Pillow versions?

* OS: Raspbian Buster Lite (10.1) Kernel 4.19.75+ #1270 Tue Sep 24 18:38:54 BST 2019 armv6l GNU/Linux (running on a Pi Zero)
* Python: 3.7.3 - not tested under Python 2
* Pillow: 6.2.1 (installed using pip3)

The fonts used are available from [Font Squirrel](https://www.fontsquirrel.com) - the two are:

Open Sans [here](https://www.fontsquirrel.com/fonts/open-sans)
Ubuntu [here](https://www.fontsquirrel.com/fonts/ubuntu?q%5Bterm%5D=ubuntu&q%5Bsearch_check%5D=Y)

```python
from PIL import Image, ImageDraw, ImageFont

image_obj = Image.new('P', (212, 104), color = (255,255,255))
screen_image = ImageDraw.Draw(image_obj)

osbi = ImageFont.truetype('Fonts/OpenSans-BoldItalic.ttf', 15)
screen_image.text((10,10), 'Network Status test',fill = (0,0,0) , font = osbi)
screen_image.text((10,30), 'Bit longer no iffy ending',fill = (0,0,0) , font = osbi)

ubuntu = ImageFont.truetype('Fonts/Ubuntu-BI.ttf', 15)
screen_image.text((10,60), 'Network Status test',fill = (0,0,0) , font = ubuntu)
screen_image.text((10,80), 'Bit longer no iffy ending',fill = (0,0,0) , font = ubuntu)

image_obj.save('italic-test.png')
```
![italic-test](https://user-images.githubusercontent.com/39886283/67718207-2ec54880-f9c7-11e9-90c7-a77f70050e8e.png)



Hints:
Have now discovered that:

1) It is not only Italic fonts (can reproduce on various 'light' fonts)
2) The range of ending positions is not limited to 110 Pixels - I now have one at 129 pixels
I can replicate this error on macOS with updated libs.  I've seen issues similar to this using Pillow to render text for little 1-bit OLED displays.  
It looks like Pillow is using fontmode='1' since you have chosen mode 'P'.  
What happens if you use 'L' or 'RGB' instead of 'P'?
If you add `screen_image.fontmode='L'` before rendering text does the problem go away?  
This may be related to https://github.com/python-pillow/Pillow/issues/2293 (i.e. it may be a libfreetype problem).  

Patch:
diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py
--- a/src/PIL/ImageFont.py
+++ b/src/PIL/ImageFont.py
@@ -259,7 +259,7 @@ def getsize(
 
         :return: (width, height)
         """
-        size, offset = self.font.getsize(text, direction, features, language)
+        size, offset = self.font.getsize(text, False, direction, features, language)
         return (
             size[0] + stroke_width * 2 + offset[0],
             size[1] + stroke_width * 2 + offset[1],
@@ -468,7 +468,9 @@ def getmask2(
                  :py:mod:`PIL.Image.core` interface module, and the text offset, the
                  gap between the starting coordinate and the first marking
         """
-        size, offset = self.font.getsize(text, direction, features, language)
+        size, offset = self.font.getsize(
+            text, mode == "1", direction, features, language
+        )
         size = size[0] + stroke_width * 2, size[1] + stroke_width * 2
         im = fill("L", size, 0)
         self.font.render(


Test patch:
diff --git a/Tests/images/text_mono.gif b/Tests/images/text_mono.gif
new file mode 100644
Binary files /dev/null and b/Tests/images/text_mono.gif differ
diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py
--- a/Tests/test_imagefont.py
+++ b/Tests/test_imagefont.py
@@ -11,6 +11,7 @@
 
 from .helper import (
     assert_image_equal,
+    assert_image_equal_tofile,
     assert_image_similar,
     assert_image_similar_tofile,
     is_pypy,
@@ -724,3 +725,19 @@ def _check_text(font, path, epsilon):
 @skip_unless_feature("raqm")
 class TestImageFont_RaqmLayout(TestImageFont):
     LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM
+
+
+def test_render_mono_size():
+    # issue 4177
+
+    if distutils.version.StrictVersion(ImageFont.core.freetype2_version) < "2.4":
+        pytest.skip("Different metrics")
+
+    im = Image.new("P", (100, 30), "white")
+    draw = ImageDraw.Draw(im)
+    ttf = ImageFont.truetype(
+        "Tests/fonts/DejaVuSans.ttf", 18, layout_engine=ImageFont.LAYOUT_BASIC
+    )
+
+    draw.text((10, 10), "r" * 10, "black", ttf)
+    assert_image_equal_tofile(im, "Tests/images/text_mono.gif")