We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`PIL` text provider: Critical issues if `font_size` is `< 1`
**Software Versions**
* Python: `3.8.9`
* OS: Windows
* Kivy: `2.3.0rc2`
* Kivy installation method: `python -m pip install --pre "kivy[base]"` / `pip install Kivy==2.3.0rc2`


**Describe the bug**
After upgrading from Pillow 9.x.x to Pillow 10.x.x, some errors are occurring, some with no clear cause. Some critical errors already existed in previous versions of kivy/Pillow.

🔴  Note: This same code works correctly (without errors) with the `"sdl2"` text provider


# Issue 1:
### Works in `9.x.x`, breaks in `10.x.x`:
```python
import os
os.environ["KIVY_TEXT"] = "pil"

from kivy.app import App
from kivy.uix.label import Label


class LabelTest(App):
    def build(self):
        return Label(text='Kivy rulz', font_size=0)

LabelTest().run()
```

### Error:
```
   File "lib\site-packages\kivy\uix\label.py", line 432, in texture_update
     self._label.refresh()
   File "lib\site-packages\kivy\core\text\__init__.py", line 836, in refresh
     sz = self.render()
   File "lib\site-packages\kivy\core\text\__init__.py", line 772, in render
     options['space_width'] = self.get_extents(' ')[0]
   File "lib\site-packages\kivy\core\text\text_pil.py", line 39, in get_extents
     font = self._select_font()
   File "lib\site-packages\kivy\core\text\text_pil.py", line 33, in _select_font
     font = ImageFont.truetype(fontname, fontsize)
   File "lib\site-packages\PIL\ImageFont.py", line 797, in truetype
     return freetype(font)
   File "lib\site-packages\PIL\ImageFont.py", line 794, in freetype
     return FreeTypeFont(font, size, index, encoding, layout_engine)
   File "lib\site-packages\PIL\ImageFont.py", line 226, in __init__
     self.font = core.getfont(
 OSError: invalid ppem value
```

# Issue 2:

### Breaks in `9.x.x`, and in `10.x.x`, and in previous versions of kivy:

```python
import os
os.environ["KIVY_TEXT"] = "pil"

from kivy.app import App
from kivy.uix.label import Label


class LabelTest(App):
    def build(self):
        return Label(text='Kivy rulz', font_size=-10)

LabelTest().run()
```

### Error:
```
   File "lib\site-packages\kivy\uix\label.py", line 432, in texture_update
     self._label.refresh()
   File "lib\site-packages\kivy\core\text\__init__.py", line 836, in refresh
     sz = self.render()
   File "lib\site-packages\kivy\core\text\__init__.py", line 812, in render
     w, h, clipped = layout_text(text, lines, (0, 0), (uw, uh), options,
   File "kivy\\core\\text\\text_layout.pyx", line 408, in kivy.core.text.text_layout.layout_text
   File "kivy\\core\\text\\text_layout.pyx", line 235, in kivy.core.text.text_layout.layout_text_unrestricted
   File "lib\site-packages\kivy\core\text\text_pil.py", line 37, in get_extents
     left, top, right, bottom = font.getbbox(text)
   File "lib\site-packages\PIL\ImageFont.py", line 408, in getbbox
     size, offset = self.font.getsize(
 OSError: invalid argument
```

# Issue 3:
### Works in `9.x.x`, breaks in `10.x.x`:
```
There is still no minimum reproducible code
```

### Error:
```
File "lib\site-packages\kivy\core\text\__init__.py", line 828, in _texture_fill
    self.render(real=True)
  File "lib\site-packages\kivy\core\text\markup.py", line 143, in render
    ret = self._render_real()
  File "lib\site-packages\kivy\core\text\__init__.py", line 752, in _render_real
    self.render_lines(lines, options, self._render_text, y, size)
  File "lib\site-packages\kivy\core\text\markup.py", line 500, in render_lines
    render_text(word.text, x, y + script_pos)
  File "lib\site-packages\kivy\core\text\text_pil.py", line 66, in _render_text
    self._pil_draw.text((int(x), int(y)),
  File "lib\site-packages\PIL\ImageDraw.py", line 565, in text
    draw_text(ink)
  File "lib\site-packages\PIL\ImageDraw.py", line 508, in draw_text
    mask, offset = font.getmask2(
  File "lib\site-packages\PIL\ImageFont.py", line 580, in getmask2
    offset = self.font.render(
OSError: unsupported bitmap pixel mode
```

**Expected behavior**
Behave like the `sdl2` text provider

### Proposed solutions
- issues 1 and 2 -  Limit within the `PIL` text provider the font size to `> 0`
- issue 3 -  If the root cause of the issue is not identified, treat the error on the line [66](https://github.com/kivy/kivy/blob/master/kivy/core/text/text_pil.py#L66):
```python
self._pil_draw.text((int(x), int(y)),
                    text, font=self._select_font(), fill=color)
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kivy/core/text/text_pil.py`
Content:
```
1 '''
2 Text PIL: Draw text with PIL
3 '''
4 
5 __all__ = ('LabelPIL', )
6 
7 from PIL import Image, ImageFont, ImageDraw
8 
9 
10 from kivy.compat import text_type
11 from kivy.core.text import LabelBase
12 from kivy.core.image import ImageData
13 
14 # used for fetching extends before creature image surface
15 default_font = ImageFont.load_default()
16 
17 
18 class LabelPIL(LabelBase):
19     _cache = {}
20 
21     def _select_font(self):
22         fontsize = int(self.options['font_size'])
23         fontname = self.options['font_name_r']
24         try:
25             id = '%s.%s' % (text_type(fontname), text_type(fontsize))
26         except UnicodeDecodeError:
27             id = '%s.%s' % (fontname, fontsize)
28 
29         if id not in self._cache:
30             font = ImageFont.truetype(fontname, fontsize)
31             self._cache[id] = font
32 
33         return self._cache[id]
34 
35     def get_extents(self, text):
36         font = self._select_font()
37         left, top, right, bottom = font.getbbox(text)
38         ascent, descent = font.getmetrics()
39 
40         if self.options['limit_render_to_text_bbox']:
41             h = bottom - top
42         else:
43             h = ascent + descent
44         w = right - left
45 
46         return w, h
47 
48     def get_cached_extents(self):
49         return self.get_extents
50 
51     def _render_begin(self):
52         # create a surface, context, font...
53         self._pil_im = Image.new('RGBA', self._size, color=(255, 255, 255, 0))
54         self._pil_draw = ImageDraw.Draw(self._pil_im)
55 
56     def _render_text(self, text, x, y):
57         color = tuple([int(c * 255) for c in self.options['color']])
58 
59         # Adjust x and y position to avoid text cutoff
60         if self.options['limit_render_to_text_bbox']:
61             font = self._select_font()
62             bbox = font.getbbox(text)
63             x -= bbox[0]
64             y -= bbox[1]
65 
66         self._pil_draw.text((int(x), int(y)),
67                             text, font=self._select_font(), fill=color)
68 
69     def _render_end(self):
70         data = ImageData(self._size[0], self._size[1],
71                          self._pil_im.mode.lower(), self._pil_im.tobytes())
72 
73         del self._pil_im
74         del self._pil_draw
75 
76         return data
77
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kivy/core/text/text_pil.py b/kivy/core/text/text_pil.py
--- a/kivy/core/text/text_pil.py
+++ b/kivy/core/text/text_pil.py
@@ -19,6 +19,9 @@
     _cache = {}
 
     def _select_font(self):
+        if self.options['font_size'] < 1:
+            return None
+
         fontsize = int(self.options['font_size'])
         fontname = self.options['font_name_r']
         try:
@@ -34,6 +37,9 @@
 
     def get_extents(self, text):
         font = self._select_font()
+        if not font:
+            return 0, 0
+
         left, top, right, bottom = font.getbbox(text)
         ascent, descent = font.getmetrics()
 
@@ -54,17 +60,19 @@
         self._pil_draw = ImageDraw.Draw(self._pil_im)
 
     def _render_text(self, text, x, y):
+        font = self._select_font()
+        if not font:
+            return
+
         color = tuple([int(c * 255) for c in self.options['color']])
 
         # Adjust x and y position to avoid text cutoff
         if self.options['limit_render_to_text_bbox']:
-            font = self._select_font()
             bbox = font.getbbox(text)
             x -= bbox[0]
             y -= bbox[1]
 
-        self._pil_draw.text((int(x), int(y)),
-                            text, font=self._select_font(), fill=color)
+        self._pil_draw.text((int(x), int(y)), text, font=font, fill=color)
 
     def _render_end(self):
         data = ImageData(self._size[0], self._size[1],

{"golden_diff": "diff --git a/kivy/core/text/text_pil.py b/kivy/core/text/text_pil.py\n--- a/kivy/core/text/text_pil.py\n+++ b/kivy/core/text/text_pil.py\n@@ -19,6 +19,9 @@\n     _cache = {}\n \n     def _select_font(self):\n+        if self.options['font_size'] < 1:\n+            return None\n+\n         fontsize = int(self.options['font_size'])\n         fontname = self.options['font_name_r']\n         try:\n@@ -34,6 +37,9 @@\n \n     def get_extents(self, text):\n         font = self._select_font()\n+        if not font:\n+            return 0, 0\n+\n         left, top, right, bottom = font.getbbox(text)\n         ascent, descent = font.getmetrics()\n \n@@ -54,17 +60,19 @@\n         self._pil_draw = ImageDraw.Draw(self._pil_im)\n \n     def _render_text(self, text, x, y):\n+        font = self._select_font()\n+        if not font:\n+            return\n+\n         color = tuple([int(c * 255) for c in self.options['color']])\n \n         # Adjust x and y position to avoid text cutoff\n         if self.options['limit_render_to_text_bbox']:\n-            font = self._select_font()\n             bbox = font.getbbox(text)\n             x -= bbox[0]\n             y -= bbox[1]\n \n-        self._pil_draw.text((int(x), int(y)),\n-                            text, font=self._select_font(), fill=color)\n+        self._pil_draw.text((int(x), int(y)), text, font=font, fill=color)\n \n     def _render_end(self):\n         data = ImageData(self._size[0], self._size[1],\n", "issue": "`PIL` text provider: Critical issues if `font_size` is `< 1`\n**Software Versions**\r\n* Python: `3.8.9`\r\n* OS: Windows\r\n* Kivy: `2.3.0rc2`\r\n* Kivy installation method: `python -m pip install --pre \"kivy[base]\"` / `pip install Kivy==2.3.0rc2`\r\n\r\n\r\n**Describe the bug**\r\nAfter upgrading from Pillow 9.x.x to Pillow 10.x.x, some errors are occurring, some with no clear cause. Some critical errors already existed in previous versions of kivy/Pillow.\r\n\r\n\ud83d\udd34  Note: This same code works correctly (without errors) with the `\"sdl2\"` text provider\r\n\r\n\r\n# Issue 1:\r\n### Works in `9.x.x`, breaks in `10.x.x`:\r\n```python\r\nimport os\r\nos.environ[\"KIVY_TEXT\"] = \"pil\"\r\n\r\nfrom kivy.app import App\r\nfrom kivy.uix.label import Label\r\n\r\n\r\nclass LabelTest(App):\r\n    def build(self):\r\n        return Label(text='Kivy rulz', font_size=0)\r\n\r\nLabelTest().run()\r\n```\r\n\r\n### Error:\r\n```\r\n   File \"lib\\site-packages\\kivy\\uix\\label.py\", line 432, in texture_update\r\n     self._label.refresh()\r\n   File \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 836, in refresh\r\n     sz = self.render()\r\n   File \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 772, in render\r\n     options['space_width'] = self.get_extents(' ')[0]\r\n   File \"lib\\site-packages\\kivy\\core\\text\\text_pil.py\", line 39, in get_extents\r\n     font = self._select_font()\r\n   File \"lib\\site-packages\\kivy\\core\\text\\text_pil.py\", line 33, in _select_font\r\n     font = ImageFont.truetype(fontname, fontsize)\r\n   File \"lib\\site-packages\\PIL\\ImageFont.py\", line 797, in truetype\r\n     return freetype(font)\r\n   File \"lib\\site-packages\\PIL\\ImageFont.py\", line 794, in freetype\r\n     return FreeTypeFont(font, size, index, encoding, layout_engine)\r\n   File \"lib\\site-packages\\PIL\\ImageFont.py\", line 226, in __init__\r\n     self.font = core.getfont(\r\n OSError: invalid ppem value\r\n```\r\n\r\n# Issue 2:\r\n\r\n### Breaks in `9.x.x`, and in `10.x.x`, and in previous versions of kivy:\r\n\r\n```python\r\nimport os\r\nos.environ[\"KIVY_TEXT\"] = \"pil\"\r\n\r\nfrom kivy.app import App\r\nfrom kivy.uix.label import Label\r\n\r\n\r\nclass LabelTest(App):\r\n    def build(self):\r\n        return Label(text='Kivy rulz', font_size=-10)\r\n\r\nLabelTest().run()\r\n```\r\n\r\n### Error:\r\n```\r\n   File \"lib\\site-packages\\kivy\\uix\\label.py\", line 432, in texture_update\r\n     self._label.refresh()\r\n   File \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 836, in refresh\r\n     sz = self.render()\r\n   File \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 812, in render\r\n     w, h, clipped = layout_text(text, lines, (0, 0), (uw, uh), options,\r\n   File \"kivy\\\\core\\\\text\\\\text_layout.pyx\", line 408, in kivy.core.text.text_layout.layout_text\r\n   File \"kivy\\\\core\\\\text\\\\text_layout.pyx\", line 235, in kivy.core.text.text_layout.layout_text_unrestricted\r\n   File \"lib\\site-packages\\kivy\\core\\text\\text_pil.py\", line 37, in get_extents\r\n     left, top, right, bottom = font.getbbox(text)\r\n   File \"lib\\site-packages\\PIL\\ImageFont.py\", line 408, in getbbox\r\n     size, offset = self.font.getsize(\r\n OSError: invalid argument\r\n```\r\n\r\n# Issue 3:\r\n### Works in `9.x.x`, breaks in `10.x.x`:\r\n```\r\nThere is still no minimum reproducible code\r\n```\r\n\r\n### Error:\r\n```\r\nFile \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 828, in _texture_fill\r\n    self.render(real=True)\r\n  File \"lib\\site-packages\\kivy\\core\\text\\markup.py\", line 143, in render\r\n    ret = self._render_real()\r\n  File \"lib\\site-packages\\kivy\\core\\text\\__init__.py\", line 752, in _render_real\r\n    self.render_lines(lines, options, self._render_text, y, size)\r\n  File \"lib\\site-packages\\kivy\\core\\text\\markup.py\", line 500, in render_lines\r\n    render_text(word.text, x, y + script_pos)\r\n  File \"lib\\site-packages\\kivy\\core\\text\\text_pil.py\", line 66, in _render_text\r\n    self._pil_draw.text((int(x), int(y)),\r\n  File \"lib\\site-packages\\PIL\\ImageDraw.py\", line 565, in text\r\n    draw_text(ink)\r\n  File \"lib\\site-packages\\PIL\\ImageDraw.py\", line 508, in draw_text\r\n    mask, offset = font.getmask2(\r\n  File \"lib\\site-packages\\PIL\\ImageFont.py\", line 580, in getmask2\r\n    offset = self.font.render(\r\nOSError: unsupported bitmap pixel mode\r\n```\r\n\r\n**Expected behavior**\r\nBehave like the `sdl2` text provider\r\n\r\n### Proposed solutions\r\n- issues 1 and 2 -  Limit within the `PIL` text provider the font size to `> 0`\r\n- issue 3 -  If the root cause of the issue is not identified, treat the error on the line [66](https://github.com/kivy/kivy/blob/master/kivy/core/text/text_pil.py#L66):\r\n```python\r\nself._pil_draw.text((int(x), int(y)),\r\n                    text, font=self._select_font(), fill=color)\r\n```\r\n\n", "before_files": [{"content": "'''\nText PIL: Draw text with PIL\n'''\n\n__all__ = ('LabelPIL', )\n\nfrom PIL import Image, ImageFont, ImageDraw\n\n\nfrom kivy.compat import text_type\nfrom kivy.core.text import LabelBase\nfrom kivy.core.image import ImageData\n\n# used for fetching extends before creature image surface\ndefault_font = ImageFont.load_default()\n\n\nclass LabelPIL(LabelBase):\n    _cache = {}\n\n    def _select_font(self):\n        fontsize = int(self.options['font_size'])\n        fontname = self.options['font_name_r']\n        try:\n            id = '%s.%s' % (text_type(fontname), text_type(fontsize))\n        except UnicodeDecodeError:\n            id = '%s.%s' % (fontname, fontsize)\n\n        if id not in self._cache:\n            font = ImageFont.truetype(fontname, fontsize)\n            self._cache[id] = font\n\n        return self._cache[id]\n\n    def get_extents(self, text):\n        font = self._select_font()\n        left, top, right, bottom = font.getbbox(text)\n        ascent, descent = font.getmetrics()\n\n        if self.options['limit_render_to_text_bbox']:\n            h = bottom - top\n        else:\n            h = ascent + descent\n        w = right - left\n\n        return w, h\n\n    def get_cached_extents(self):\n        return self.get_extents\n\n    def _render_begin(self):\n        # create a surface, context, font...\n        self._pil_im = Image.new('RGBA', self._size, color=(255, 255, 255, 0))\n        self._pil_draw = ImageDraw.Draw(self._pil_im)\n\n    def _render_text(self, text, x, y):\n        color = tuple([int(c * 255) for c in self.options['color']])\n\n        # Adjust x and y position to avoid text cutoff\n        if self.options['limit_render_to_text_bbox']:\n            font = self._select_font()\n            bbox = font.getbbox(text)\n            x -= bbox[0]\n            y -= bbox[1]\n\n        self._pil_draw.text((int(x), int(y)),\n                            text, font=self._select_font(), fill=color)\n\n    def _render_end(self):\n        data = ImageData(self._size[0], self._size[1],\n                         self._pil_im.mode.lower(), self._pil_im.tobytes())\n\n        del self._pil_im\n        del self._pil_draw\n\n        return data\n", "path": "kivy/core/text/text_pil.py"}], "after_files": [{"content": "'''\nText PIL: Draw text with PIL\n'''\n\n__all__ = ('LabelPIL', )\n\nfrom PIL import Image, ImageFont, ImageDraw\n\n\nfrom kivy.compat import text_type\nfrom kivy.core.text import LabelBase\nfrom kivy.core.image import ImageData\n\n# used for fetching extends before creature image surface\ndefault_font = ImageFont.load_default()\n\n\nclass LabelPIL(LabelBase):\n    _cache = {}\n\n    def _select_font(self):\n        if self.options['font_size'] < 1:\n            return None\n\n        fontsize = int(self.options['font_size'])\n        fontname = self.options['font_name_r']\n        try:\n            id = '%s.%s' % (text_type(fontname), text_type(fontsize))\n        except UnicodeDecodeError:\n            id = '%s.%s' % (fontname, fontsize)\n\n        if id not in self._cache:\n            font = ImageFont.truetype(fontname, fontsize)\n            self._cache[id] = font\n\n        return self._cache[id]\n\n    def get_extents(self, text):\n        font = self._select_font()\n        if not font:\n            return 0, 0\n\n        left, top, right, bottom = font.getbbox(text)\n        ascent, descent = font.getmetrics()\n\n        if self.options['limit_render_to_text_bbox']:\n            h = bottom - top\n        else:\n            h = ascent + descent\n        w = right - left\n\n        return w, h\n\n    def get_cached_extents(self):\n        return self.get_extents\n\n    def _render_begin(self):\n        # create a surface, context, font...\n        self._pil_im = Image.new('RGBA', self._size, color=(255, 255, 255, 0))\n        self._pil_draw = ImageDraw.Draw(self._pil_im)\n\n    def _render_text(self, text, x, y):\n        font = self._select_font()\n        if not font:\n            return\n\n        color = tuple([int(c * 255) for c in self.options['color']])\n\n        # Adjust x and y position to avoid text cutoff\n        if self.options['limit_render_to_text_bbox']:\n            bbox = font.getbbox(text)\n            x -= bbox[0]\n            y -= bbox[1]\n\n        self._pil_draw.text((int(x), int(y)), text, font=font, fill=color)\n\n    def _render_end(self):\n        data = ImageData(self._size[0], self._size[1],\n                         self._pil_im.mode.lower(), self._pil_im.tobytes())\n\n        del self._pil_im\n        del self._pil_draw\n\n        return data\n", "path": "kivy/core/text/text_pil.py"}]}