mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Merge pull request #8046 from srittau/type-annotations
Add various type annotations
This commit is contained in:
		
						commit
						5bacce9dc2
					
				| 
						 | 
					@ -124,8 +124,8 @@ def test_fastpath_translate() -> None:
 | 
				
			||||||
def test_center() -> None:
 | 
					def test_center() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    rotate(im, im.mode, 45, center=(0, 0))
 | 
					    rotate(im, im.mode, 45, center=(0, 0))
 | 
				
			||||||
    rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0))
 | 
					    rotate(im, im.mode, 45, translate=(im.size[0] // 2, 0))
 | 
				
			||||||
    rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
 | 
					    rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] // 2, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rotate_no_fill() -> None:
 | 
					def test_rotate_no_fill() -> None:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,10 +144,12 @@ pixel, the Python Imaging Library provides different resampling *filters*.
 | 
				
			||||||
.. py:currentmodule:: PIL.Image
 | 
					.. py:currentmodule:: PIL.Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.NEAREST
 | 
					.. data:: Resampling.NEAREST
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Pick one nearest pixel from the input image. Ignore all other input pixels.
 | 
					    Pick one nearest pixel from the input image. Ignore all other input pixels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.BOX
 | 
					.. data:: Resampling.BOX
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Each pixel of source image contributes to one pixel of the
 | 
					    Each pixel of source image contributes to one pixel of the
 | 
				
			||||||
    destination image with identical weights.
 | 
					    destination image with identical weights.
 | 
				
			||||||
| 
						 | 
					@ -158,6 +160,7 @@ pixel, the Python Imaging Library provides different resampling *filters*.
 | 
				
			||||||
    .. versionadded:: 3.4.0
 | 
					    .. versionadded:: 3.4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.BILINEAR
 | 
					.. data:: Resampling.BILINEAR
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    For resize calculate the output pixel value using linear interpolation
 | 
					    For resize calculate the output pixel value using linear interpolation
 | 
				
			||||||
    on all pixels that may contribute to the output value.
 | 
					    on all pixels that may contribute to the output value.
 | 
				
			||||||
| 
						 | 
					@ -165,6 +168,7 @@ pixel, the Python Imaging Library provides different resampling *filters*.
 | 
				
			||||||
    in the input image is used.
 | 
					    in the input image is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.HAMMING
 | 
					.. data:: Resampling.HAMMING
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Produces a sharper image than :data:`Resampling.BILINEAR`, doesn't have
 | 
					    Produces a sharper image than :data:`Resampling.BILINEAR`, doesn't have
 | 
				
			||||||
    dislocations on local level like with :data:`Resampling.BOX`.
 | 
					    dislocations on local level like with :data:`Resampling.BOX`.
 | 
				
			||||||
| 
						 | 
					@ -174,6 +178,7 @@ pixel, the Python Imaging Library provides different resampling *filters*.
 | 
				
			||||||
    .. versionadded:: 3.4.0
 | 
					    .. versionadded:: 3.4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.BICUBIC
 | 
					.. data:: Resampling.BICUBIC
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    For resize calculate the output pixel value using cubic interpolation
 | 
					    For resize calculate the output pixel value using cubic interpolation
 | 
				
			||||||
    on all pixels that may contribute to the output value.
 | 
					    on all pixels that may contribute to the output value.
 | 
				
			||||||
| 
						 | 
					@ -181,6 +186,7 @@ pixel, the Python Imaging Library provides different resampling *filters*.
 | 
				
			||||||
    in the input image is used.
 | 
					    in the input image is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. data:: Resampling.LANCZOS
 | 
					.. data:: Resampling.LANCZOS
 | 
				
			||||||
 | 
					    :noindex:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Calculate the output pixel value using a high-quality Lanczos filter (a
 | 
					    Calculate the output pixel value using a high-quality Lanczos filter (a
 | 
				
			||||||
    truncated sinc) on all pixels that may contribute to the output value.
 | 
					    truncated sinc) on all pixels that may contribute to the output value.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,8 +78,6 @@ Constructing images
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. autofunction:: new
 | 
					.. autofunction:: new
 | 
				
			||||||
.. autoclass:: SupportsArrayInterface
 | 
					 | 
				
			||||||
    :show-inheritance:
 | 
					 | 
				
			||||||
.. autofunction:: fromarray
 | 
					.. autofunction:: fromarray
 | 
				
			||||||
.. autofunction:: frombytes
 | 
					.. autofunction:: frombytes
 | 
				
			||||||
.. autofunction:: frombuffer
 | 
					.. autofunction:: frombuffer
 | 
				
			||||||
| 
						 | 
					@ -365,6 +363,14 @@ Classes
 | 
				
			||||||
.. autoclass:: PIL.Image.ImagePointHandler
 | 
					.. autoclass:: PIL.Image.ImagePointHandler
 | 
				
			||||||
.. autoclass:: PIL.Image.ImageTransformHandler
 | 
					.. autoclass:: PIL.Image.ImageTransformHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Protocols
 | 
				
			||||||
 | 
					---------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. autoclass:: SupportsArrayInterface
 | 
				
			||||||
 | 
					    :show-inheritance:
 | 
				
			||||||
 | 
					.. autoclass:: SupportsGetData
 | 
				
			||||||
 | 
					    :show-inheritance:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Constants
 | 
					Constants
 | 
				
			||||||
---------
 | 
					---------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,7 +424,6 @@ See :ref:`concept-filters` for details.
 | 
				
			||||||
.. autoclass:: Resampling
 | 
					.. autoclass:: Resampling
 | 
				
			||||||
    :members:
 | 
					    :members:
 | 
				
			||||||
    :undoc-members:
 | 
					    :undoc-members:
 | 
				
			||||||
    :noindex:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Dither modes
 | 
					Dither modes
 | 
				
			||||||
^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -503,6 +503,12 @@ def _getscaleoffset(expr):
 | 
				
			||||||
# Implementation wrapper
 | 
					# Implementation wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SupportsGetData(Protocol):
 | 
				
			||||||
 | 
					    def getdata(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					    ) -> tuple[Transform, Sequence[int]]: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Image:
 | 
					class Image:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This class represents an image object.  To create
 | 
					    This class represents an image object.  To create
 | 
				
			||||||
| 
						 | 
					@ -1289,7 +1295,7 @@ class Image:
 | 
				
			||||||
        return im.crop((x0, y0, x1, y1))
 | 
					        return im.crop((x0, y0, x1, y1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draft(
 | 
					    def draft(
 | 
				
			||||||
        self, mode: str, size: tuple[int, int]
 | 
					        self, mode: str | None, size: tuple[int, int]
 | 
				
			||||||
    ) -> tuple[str, tuple[int, int, float, float]] | None:
 | 
					    ) -> tuple[str, tuple[int, int, float, float]] | None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Configures the image file loader so it returns a version of the
 | 
					        Configures the image file loader so it returns a version of the
 | 
				
			||||||
| 
						 | 
					@ -1709,7 +1715,12 @@ class Image:
 | 
				
			||||||
            return self.im.entropy(extrema)
 | 
					            return self.im.entropy(extrema)
 | 
				
			||||||
        return self.im.entropy()
 | 
					        return self.im.entropy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def paste(self, im, box=None, mask=None) -> None:
 | 
					    def paste(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        im: Image | str | float | tuple[float, ...],
 | 
				
			||||||
 | 
					        box: tuple[int, int, int, int] | tuple[int, int] | None = None,
 | 
				
			||||||
 | 
					        mask: Image | None = None,
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Pastes another image into this image. The box argument is either
 | 
					        Pastes another image into this image. The box argument is either
 | 
				
			||||||
        a 2-tuple giving the upper left corner, a 4-tuple defining the
 | 
					        a 2-tuple giving the upper left corner, a 4-tuple defining the
 | 
				
			||||||
| 
						 | 
					@ -1737,7 +1748,7 @@ class Image:
 | 
				
			||||||
        See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
 | 
					        See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
 | 
				
			||||||
        combine images with respect to their alpha channels.
 | 
					        combine images with respect to their alpha channels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param im: Source image or pixel value (integer or tuple).
 | 
					        :param im: Source image or pixel value (integer, float or tuple).
 | 
				
			||||||
        :param box: An optional 4-tuple giving the region to paste into.
 | 
					        :param box: An optional 4-tuple giving the region to paste into.
 | 
				
			||||||
           If a 2-tuple is used instead, it's treated as the upper left
 | 
					           If a 2-tuple is used instead, it's treated as the upper left
 | 
				
			||||||
           corner.  If omitted or None, the source is pasted into the
 | 
					           corner.  If omitted or None, the source is pasted into the
 | 
				
			||||||
| 
						 | 
					@ -2146,7 +2157,13 @@ class Image:
 | 
				
			||||||
            min(self.size[1], math.ceil(box[3] + support_y)),
 | 
					            min(self.size[1], math.ceil(box[3] + support_y)),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resize(self, size, resample=None, box=None, reducing_gap=None) -> Image:
 | 
					    def resize(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        size: tuple[int, int],
 | 
				
			||||||
 | 
					        resample: int | None = None,
 | 
				
			||||||
 | 
					        box: tuple[float, float, float, float] | None = None,
 | 
				
			||||||
 | 
					        reducing_gap: float | None = None,
 | 
				
			||||||
 | 
					    ) -> Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns a resized copy of this image.
 | 
					        Returns a resized copy of this image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2211,13 +2228,9 @@ class Image:
 | 
				
			||||||
            msg = "reducing_gap must be 1.0 or greater"
 | 
					            msg = "reducing_gap must be 1.0 or greater"
 | 
				
			||||||
            raise ValueError(msg)
 | 
					            raise ValueError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size = tuple(size)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.load()
 | 
					        self.load()
 | 
				
			||||||
        if box is None:
 | 
					        if box is None:
 | 
				
			||||||
            box = (0, 0) + self.size
 | 
					            box = (0, 0) + self.size
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            box = tuple(box)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.size == size and box == (0, 0) + self.size:
 | 
					        if self.size == size and box == (0, 0) + self.size:
 | 
				
			||||||
            return self.copy()
 | 
					            return self.copy()
 | 
				
			||||||
| 
						 | 
					@ -2252,7 +2265,11 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return self._new(self.im.resize(size, resample, box))
 | 
					        return self._new(self.im.resize(size, resample, box))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reduce(self, factor, box=None):
 | 
					    def reduce(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        factor: int | tuple[int, int],
 | 
				
			||||||
 | 
					        box: tuple[int, int, int, int] | None = None,
 | 
				
			||||||
 | 
					    ) -> Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns a copy of the image reduced ``factor`` times.
 | 
					        Returns a copy of the image reduced ``factor`` times.
 | 
				
			||||||
        If the size of the image is not dividable by ``factor``,
 | 
					        If the size of the image is not dividable by ``factor``,
 | 
				
			||||||
| 
						 | 
					@ -2270,8 +2287,6 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if box is None:
 | 
					        if box is None:
 | 
				
			||||||
            box = (0, 0) + self.size
 | 
					            box = (0, 0) + self.size
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            box = tuple(box)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if factor == (1, 1) and box == (0, 0) + self.size:
 | 
					        if factor == (1, 1) and box == (0, 0) + self.size:
 | 
				
			||||||
            return self.copy()
 | 
					            return self.copy()
 | 
				
			||||||
| 
						 | 
					@ -2287,13 +2302,13 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def rotate(
 | 
					    def rotate(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        angle,
 | 
					        angle: float,
 | 
				
			||||||
        resample=Resampling.NEAREST,
 | 
					        resample: Resampling = Resampling.NEAREST,
 | 
				
			||||||
        expand=0,
 | 
					        expand: int | bool = False,
 | 
				
			||||||
        center=None,
 | 
					        center: tuple[int, int] | None = None,
 | 
				
			||||||
        translate=None,
 | 
					        translate: tuple[int, int] | None = None,
 | 
				
			||||||
        fillcolor=None,
 | 
					        fillcolor: float | tuple[float, ...] | str | None = None,
 | 
				
			||||||
    ):
 | 
					    ) -> Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns a rotated copy of this image.  This method returns a
 | 
					        Returns a rotated copy of this image.  This method returns a
 | 
				
			||||||
        copy of this image, rotated the given number of degrees counter
 | 
					        copy of this image, rotated the given number of degrees counter
 | 
				
			||||||
| 
						 | 
					@ -2600,7 +2615,12 @@ class Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def thumbnail(self, size, resample=Resampling.BICUBIC, reducing_gap=2.0):
 | 
					    def thumbnail(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        size: tuple[float, float],
 | 
				
			||||||
 | 
					        resample: Resampling = Resampling.BICUBIC,
 | 
				
			||||||
 | 
					        reducing_gap: float = 2.0,
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Make this image into a thumbnail.  This method modifies the
 | 
					        Make this image into a thumbnail.  This method modifies the
 | 
				
			||||||
        image to contain a thumbnail version of itself, no larger than
 | 
					        image to contain a thumbnail version of itself, no larger than
 | 
				
			||||||
| 
						 | 
					@ -2661,20 +2681,24 @@ class Image:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        box = None
 | 
					        box = None
 | 
				
			||||||
        if reducing_gap is not None:
 | 
					        if reducing_gap is not None:
 | 
				
			||||||
            size = preserve_aspect_ratio()
 | 
					            preserved_size = preserve_aspect_ratio()
 | 
				
			||||||
            if size is None:
 | 
					            if preserved_size is None:
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					            size = preserved_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            res = self.draft(None, (size[0] * reducing_gap, size[1] * reducing_gap))
 | 
					            res = self.draft(
 | 
				
			||||||
 | 
					                None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
            if res is not None:
 | 
					            if res is not None:
 | 
				
			||||||
                box = res[1]
 | 
					                box = res[1]
 | 
				
			||||||
        if box is None:
 | 
					        if box is None:
 | 
				
			||||||
            self.load()
 | 
					            self.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # load() may have changed the size of the image
 | 
					            # load() may have changed the size of the image
 | 
				
			||||||
            size = preserve_aspect_ratio()
 | 
					            preserved_size = preserve_aspect_ratio()
 | 
				
			||||||
            if size is None:
 | 
					            if preserved_size is None:
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					            size = preserved_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.size != size:
 | 
					        if self.size != size:
 | 
				
			||||||
            im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
 | 
					            im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
 | 
				
			||||||
| 
						 | 
					@ -2690,12 +2714,12 @@ class Image:
 | 
				
			||||||
    # instead of bloating the method docs, add a separate chapter.
 | 
					    # instead of bloating the method docs, add a separate chapter.
 | 
				
			||||||
    def transform(
 | 
					    def transform(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        size,
 | 
					        size: tuple[int, int],
 | 
				
			||||||
        method,
 | 
					        method: Transform | ImageTransformHandler | SupportsGetData,
 | 
				
			||||||
        data=None,
 | 
					        data: Sequence[Any] | None = None,
 | 
				
			||||||
        resample=Resampling.NEAREST,
 | 
					        resample: int = Resampling.NEAREST,
 | 
				
			||||||
        fill=1,
 | 
					        fill: int = 1,
 | 
				
			||||||
        fillcolor=None,
 | 
					        fillcolor: float | tuple[float, ...] | str | None = None,
 | 
				
			||||||
    ) -> Image:
 | 
					    ) -> Image:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Transforms this image.  This method creates a new image with the
 | 
					        Transforms this image.  This method creates a new image with the
 | 
				
			||||||
| 
						 | 
					@ -2929,7 +2953,7 @@ class ImageTransformHandler:
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        size: tuple[int, int],
 | 
					        size: tuple[int, int],
 | 
				
			||||||
        image: Image,
 | 
					        image: Image,
 | 
				
			||||||
        **options: dict[str, str | int | tuple[int, ...] | list[int]],
 | 
					        **options: Any,
 | 
				
			||||||
    ) -> Image:
 | 
					    ) -> Image:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ from __future__ import annotations
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
import numbers
 | 
					import numbers
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
from typing import TYPE_CHECKING, Sequence, cast
 | 
					from typing import TYPE_CHECKING, AnyStr, Sequence, cast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from . import Image, ImageColor
 | 
					from . import Image, ImageColor
 | 
				
			||||||
from ._typing import Coords
 | 
					from ._typing import Coords
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,9 @@ class ImageDraw:
 | 
				
			||||||
    if TYPE_CHECKING:
 | 
					    if TYPE_CHECKING:
 | 
				
			||||||
        from . import ImageFont
 | 
					        from . import ImageFont
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getfont(self) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
 | 
					    def getfont(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					    ) -> ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get the current default font.
 | 
					        Get the current default font.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,14 +122,15 @@ class ImageDraw:
 | 
				
			||||||
            self.font = ImageFont.load_default()
 | 
					            self.font = ImageFont.load_default()
 | 
				
			||||||
        return self.font
 | 
					        return self.font
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getfont(self, font_size: float | None):
 | 
					    def _getfont(
 | 
				
			||||||
 | 
					        self, font_size: float | None
 | 
				
			||||||
 | 
					    ) -> ImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont:
 | 
				
			||||||
        if font_size is not None:
 | 
					        if font_size is not None:
 | 
				
			||||||
            from . import ImageFont
 | 
					            from . import ImageFont
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            font = ImageFont.load_default(font_size)
 | 
					            return ImageFont.load_default(font_size)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            font = self.getfont()
 | 
					            return self.getfont()
 | 
				
			||||||
        return font
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getink(self, ink, fill=None) -> tuple[int | None, int | None]:
 | 
					    def _getink(self, ink, fill=None) -> tuple[int | None, int | None]:
 | 
				
			||||||
        if ink is None and fill is None:
 | 
					        if ink is None and fill is None:
 | 
				
			||||||
| 
						 | 
					@ -460,15 +463,13 @@ class ImageDraw:
 | 
				
			||||||
                    right[3] -= r + 1
 | 
					                    right[3] -= r + 1
 | 
				
			||||||
                self.draw.draw_rectangle(right, ink, 1)
 | 
					                self.draw.draw_rectangle(right, ink, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _multiline_check(self, text) -> bool:
 | 
					    def _multiline_check(self, text: AnyStr) -> bool:
 | 
				
			||||||
        split_character = "\n" if isinstance(text, str) else b"\n"
 | 
					        split_character = "\n" if isinstance(text, str) else b"\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return split_character in text
 | 
					        return split_character in text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _multiline_split(self, text) -> list[str | bytes]:
 | 
					    def _multiline_split(self, text: AnyStr) -> list[AnyStr]:
 | 
				
			||||||
        split_character = "\n" if isinstance(text, str) else b"\n"
 | 
					        return text.split("\n" if isinstance(text, str) else b"\n")
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return text.split(split_character)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _multiline_spacing(self, font, spacing, stroke_width):
 | 
					    def _multiline_spacing(self, font, spacing, stroke_width):
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
| 
						 | 
					@ -479,10 +480,15 @@ class ImageDraw:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def text(
 | 
					    def text(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        xy,
 | 
					        xy: tuple[float, float],
 | 
				
			||||||
        text,
 | 
					        text: str,
 | 
				
			||||||
        fill=None,
 | 
					        fill=None,
 | 
				
			||||||
        font=None,
 | 
					        font: (
 | 
				
			||||||
 | 
					            ImageFont.ImageFont
 | 
				
			||||||
 | 
					            | ImageFont.FreeTypeFont
 | 
				
			||||||
 | 
					            | ImageFont.TransposedFont
 | 
				
			||||||
 | 
					            | None
 | 
				
			||||||
 | 
					        ) = None,
 | 
				
			||||||
        anchor=None,
 | 
					        anchor=None,
 | 
				
			||||||
        spacing=4,
 | 
					        spacing=4,
 | 
				
			||||||
        align="left",
 | 
					        align="left",
 | 
				
			||||||
| 
						 | 
					@ -536,7 +542,7 @@ class ImageDraw:
 | 
				
			||||||
                coord.append(int(xy[i]))
 | 
					                coord.append(int(xy[i]))
 | 
				
			||||||
                start.append(math.modf(xy[i])[0])
 | 
					                start.append(math.modf(xy[i])[0])
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                mask, offset = font.getmask2(
 | 
					                mask, offset = font.getmask2(  # type: ignore[union-attr,misc]
 | 
				
			||||||
                    text,
 | 
					                    text,
 | 
				
			||||||
                    mode,
 | 
					                    mode,
 | 
				
			||||||
                    direction=direction,
 | 
					                    direction=direction,
 | 
				
			||||||
| 
						 | 
					@ -552,7 +558,7 @@ class ImageDraw:
 | 
				
			||||||
                coord = [coord[0] + offset[0], coord[1] + offset[1]]
 | 
					                coord = [coord[0] + offset[0], coord[1] + offset[1]]
 | 
				
			||||||
            except AttributeError:
 | 
					            except AttributeError:
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    mask = font.getmask(
 | 
					                    mask = font.getmask(  # type: ignore[misc]
 | 
				
			||||||
                        text,
 | 
					                        text,
 | 
				
			||||||
                        mode,
 | 
					                        mode,
 | 
				
			||||||
                        direction,
 | 
					                        direction,
 | 
				
			||||||
| 
						 | 
					@ -601,10 +607,15 @@ class ImageDraw:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def multiline_text(
 | 
					    def multiline_text(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        xy,
 | 
					        xy: tuple[float, float],
 | 
				
			||||||
        text,
 | 
					        text: str,
 | 
				
			||||||
        fill=None,
 | 
					        fill=None,
 | 
				
			||||||
        font=None,
 | 
					        font: (
 | 
				
			||||||
 | 
					            ImageFont.ImageFont
 | 
				
			||||||
 | 
					            | ImageFont.FreeTypeFont
 | 
				
			||||||
 | 
					            | ImageFont.TransposedFont
 | 
				
			||||||
 | 
					            | None
 | 
				
			||||||
 | 
					        ) = None,
 | 
				
			||||||
        anchor=None,
 | 
					        anchor=None,
 | 
				
			||||||
        spacing=4,
 | 
					        spacing=4,
 | 
				
			||||||
        align="left",
 | 
					        align="left",
 | 
				
			||||||
| 
						 | 
					@ -634,7 +645,7 @@ class ImageDraw:
 | 
				
			||||||
            font = self._getfont(font_size)
 | 
					            font = self._getfont(font_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        widths = []
 | 
					        widths = []
 | 
				
			||||||
        max_width = 0
 | 
					        max_width: float = 0
 | 
				
			||||||
        lines = self._multiline_split(text)
 | 
					        lines = self._multiline_split(text)
 | 
				
			||||||
        line_spacing = self._multiline_spacing(font, spacing, stroke_width)
 | 
					        line_spacing = self._multiline_spacing(font, spacing, stroke_width)
 | 
				
			||||||
        for line in lines:
 | 
					        for line in lines:
 | 
				
			||||||
| 
						 | 
					@ -688,15 +699,20 @@ class ImageDraw:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def textlength(
 | 
					    def textlength(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        text,
 | 
					        text: str,
 | 
				
			||||||
        font=None,
 | 
					        font: (
 | 
				
			||||||
 | 
					            ImageFont.ImageFont
 | 
				
			||||||
 | 
					            | ImageFont.FreeTypeFont
 | 
				
			||||||
 | 
					            | ImageFont.TransposedFont
 | 
				
			||||||
 | 
					            | None
 | 
				
			||||||
 | 
					        ) = None,
 | 
				
			||||||
        direction=None,
 | 
					        direction=None,
 | 
				
			||||||
        features=None,
 | 
					        features=None,
 | 
				
			||||||
        language=None,
 | 
					        language=None,
 | 
				
			||||||
        embedded_color=False,
 | 
					        embedded_color=False,
 | 
				
			||||||
        *,
 | 
					        *,
 | 
				
			||||||
        font_size=None,
 | 
					        font_size=None,
 | 
				
			||||||
    ):
 | 
					    ) -> float:
 | 
				
			||||||
        """Get the length of a given string, in pixels with 1/64 precision."""
 | 
					        """Get the length of a given string, in pixels with 1/64 precision."""
 | 
				
			||||||
        if self._multiline_check(text):
 | 
					        if self._multiline_check(text):
 | 
				
			||||||
            msg = "can't measure length of multiline text"
 | 
					            msg = "can't measure length of multiline text"
 | 
				
			||||||
| 
						 | 
					@ -788,7 +804,7 @@ class ImageDraw:
 | 
				
			||||||
            font = self._getfont(font_size)
 | 
					            font = self._getfont(font_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        widths = []
 | 
					        widths = []
 | 
				
			||||||
        max_width = 0
 | 
					        max_width: float = 0
 | 
				
			||||||
        lines = self._multiline_split(text)
 | 
					        lines = self._multiline_split(text)
 | 
				
			||||||
        line_spacing = self._multiline_spacing(font, spacing, stroke_width)
 | 
					        line_spacing = self._multiline_spacing(font, spacing, stroke_width)
 | 
				
			||||||
        for line in lines:
 | 
					        for line in lines:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,11 +33,16 @@ import sys
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from enum import IntEnum
 | 
					from enum import IntEnum
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
from typing import BinaryIO
 | 
					from typing import IO, TYPE_CHECKING, Any, BinaryIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from . import Image
 | 
					from . import Image
 | 
				
			||||||
from ._typing import StrOrBytesPath
 | 
					from ._typing import StrOrBytesPath
 | 
				
			||||||
from ._util import is_directory, is_path
 | 
					from ._util import is_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
 | 
					    from . import ImageFile
 | 
				
			||||||
 | 
					    from ._imaging import ImagingFont
 | 
				
			||||||
 | 
					    from ._imagingft import Font
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Layout(IntEnum):
 | 
					class Layout(IntEnum):
 | 
				
			||||||
| 
						 | 
					@ -56,7 +61,7 @@ except ImportError as ex:
 | 
				
			||||||
    core = DeferredError.new(ex)
 | 
					    core = DeferredError.new(ex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _string_length_check(text):
 | 
					def _string_length_check(text: str | bytes | bytearray) -> None:
 | 
				
			||||||
    if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH:
 | 
					    if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH:
 | 
				
			||||||
        msg = "too many characters in string"
 | 
					        msg = "too many characters in string"
 | 
				
			||||||
        raise ValueError(msg)
 | 
					        raise ValueError(msg)
 | 
				
			||||||
| 
						 | 
					@ -81,9 +86,11 @@ def _string_length_check(text):
 | 
				
			||||||
class ImageFont:
 | 
					class ImageFont:
 | 
				
			||||||
    """PIL font wrapper"""
 | 
					    """PIL font wrapper"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _load_pilfont(self, filename):
 | 
					    font: ImagingFont
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _load_pilfont(self, filename: str) -> None:
 | 
				
			||||||
        with open(filename, "rb") as fp:
 | 
					        with open(filename, "rb") as fp:
 | 
				
			||||||
            image = None
 | 
					            image: ImageFile.ImageFile | None = None
 | 
				
			||||||
            for ext in (".png", ".gif", ".pbm"):
 | 
					            for ext in (".png", ".gif", ".pbm"):
 | 
				
			||||||
                if image:
 | 
					                if image:
 | 
				
			||||||
                    image.close()
 | 
					                    image.close()
 | 
				
			||||||
| 
						 | 
					@ -106,7 +113,7 @@ class ImageFont:
 | 
				
			||||||
            self._load_pilfont_data(fp, image)
 | 
					            self._load_pilfont_data(fp, image)
 | 
				
			||||||
            image.close()
 | 
					            image.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _load_pilfont_data(self, file, image):
 | 
					    def _load_pilfont_data(self, file: IO[bytes], image: Image.Image) -> None:
 | 
				
			||||||
        # read PILfont header
 | 
					        # read PILfont header
 | 
				
			||||||
        if file.readline() != b"PILfont\n":
 | 
					        if file.readline() != b"PILfont\n":
 | 
				
			||||||
            msg = "Not a PILfont file"
 | 
					            msg = "Not a PILfont file"
 | 
				
			||||||
| 
						 | 
					@ -153,7 +160,9 @@ class ImageFont:
 | 
				
			||||||
        Image._decompression_bomb_check(self.font.getsize(text))
 | 
					        Image._decompression_bomb_check(self.font.getsize(text))
 | 
				
			||||||
        return self.font.getmask(text, mode)
 | 
					        return self.font.getmask(text, mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getbbox(self, text, *args, **kwargs):
 | 
					    def getbbox(
 | 
				
			||||||
 | 
					        self, text: str | bytes | bytearray, *args: Any, **kwargs: Any
 | 
				
			||||||
 | 
					    ) -> tuple[int, int, int, int]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns bounding box (in pixels) of given text.
 | 
					        Returns bounding box (in pixels) of given text.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,7 +176,9 @@ class ImageFont:
 | 
				
			||||||
        width, height = self.font.getsize(text)
 | 
					        width, height = self.font.getsize(text)
 | 
				
			||||||
        return 0, 0, width, height
 | 
					        return 0, 0, width, height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getlength(self, text, *args, **kwargs):
 | 
					    def getlength(
 | 
				
			||||||
 | 
					        self, text: str | bytes | bytearray, *args: Any, **kwargs: Any
 | 
				
			||||||
 | 
					    ) -> int:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns length (in pixels) of given text.
 | 
					        Returns length (in pixels) of given text.
 | 
				
			||||||
        This is the amount by which following text should be offset.
 | 
					        This is the amount by which following text should be offset.
 | 
				
			||||||
| 
						 | 
					@ -187,6 +198,8 @@ class ImageFont:
 | 
				
			||||||
class FreeTypeFont:
 | 
					class FreeTypeFont:
 | 
				
			||||||
    """FreeType font wrapper (requires _imagingft service)"""
 | 
					    """FreeType font wrapper (requires _imagingft service)"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    font: Font
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(
 | 
					    def __init__(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        font: StrOrBytesPath | BinaryIO | None = None,
 | 
					        font: StrOrBytesPath | BinaryIO | None = None,
 | 
				
			||||||
| 
						 | 
					@ -250,7 +263,7 @@ class FreeTypeFont:
 | 
				
			||||||
        path, size, index, encoding, layout_engine = state
 | 
					        path, size, index, encoding, layout_engine = state
 | 
				
			||||||
        self.__init__(path, size, index, encoding, layout_engine)
 | 
					        self.__init__(path, size, index, encoding, layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getname(self):
 | 
					    def getname(self) -> tuple[str | None, str | None]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        :return: A tuple of the font family (e.g. Helvetica) and the font style
 | 
					        :return: A tuple of the font family (e.g. Helvetica) and the font style
 | 
				
			||||||
            (e.g. Bold)
 | 
					            (e.g. Bold)
 | 
				
			||||||
| 
						 | 
					@ -265,7 +278,9 @@ class FreeTypeFont:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return self.font.ascent, self.font.descent
 | 
					        return self.font.ascent, self.font.descent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getlength(self, text, mode="", direction=None, features=None, language=None):
 | 
					    def getlength(
 | 
				
			||||||
 | 
					        self, text: str, mode="", direction=None, features=None, language=None
 | 
				
			||||||
 | 
					    ) -> float:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns length (in pixels with 1/64 precision) of given text when rendered
 | 
					        Returns length (in pixels with 1/64 precision) of given text when rendered
 | 
				
			||||||
        in font with provided direction, features, and language.
 | 
					        in font with provided direction, features, and language.
 | 
				
			||||||
| 
						 | 
					@ -339,14 +354,14 @@ class FreeTypeFont:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getbbox(
 | 
					    def getbbox(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        text,
 | 
					        text: str,
 | 
				
			||||||
        mode="",
 | 
					        mode: str = "",
 | 
				
			||||||
        direction=None,
 | 
					        direction: str | None = None,
 | 
				
			||||||
        features=None,
 | 
					        features: list[str] | None = None,
 | 
				
			||||||
        language=None,
 | 
					        language: str | None = None,
 | 
				
			||||||
        stroke_width=0,
 | 
					        stroke_width: float = 0,
 | 
				
			||||||
        anchor=None,
 | 
					        anchor: str | None = None,
 | 
				
			||||||
    ):
 | 
					    ) -> tuple[float, float, float, float]:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Returns bounding box (in pixels) of given text relative to given anchor
 | 
					        Returns bounding box (in pixels) of given text relative to given anchor
 | 
				
			||||||
        when rendered in font with provided direction, features, and language.
 | 
					        when rendered in font with provided direction, features, and language.
 | 
				
			||||||
| 
						 | 
					@ -496,7 +511,7 @@ class FreeTypeFont:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getmask2(
 | 
					    def getmask2(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        text,
 | 
					        text: str,
 | 
				
			||||||
        mode="",
 | 
					        mode="",
 | 
				
			||||||
        direction=None,
 | 
					        direction=None,
 | 
				
			||||||
        features=None,
 | 
					        features=None,
 | 
				
			||||||
| 
						 | 
					@ -666,10 +681,11 @@ class FreeTypeFont:
 | 
				
			||||||
            msg = "FreeType 2.9.1 or greater is required"
 | 
					            msg = "FreeType 2.9.1 or greater is required"
 | 
				
			||||||
            raise NotImplementedError(msg) from e
 | 
					            raise NotImplementedError(msg) from e
 | 
				
			||||||
        for axis in axes:
 | 
					        for axis in axes:
 | 
				
			||||||
            axis["name"] = axis["name"].replace(b"\x00", b"")
 | 
					            if axis["name"]:
 | 
				
			||||||
 | 
					                axis["name"] = axis["name"].replace(b"\x00", b"")
 | 
				
			||||||
        return axes
 | 
					        return axes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_variation_by_axes(self, axes):
 | 
					    def set_variation_by_axes(self, axes: list[float]) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        :param axes: A list of values for each axis.
 | 
					        :param axes: A list of values for each axis.
 | 
				
			||||||
        :exception OSError: If the font is not a variation font.
 | 
					        :exception OSError: If the font is not a variation font.
 | 
				
			||||||
| 
						 | 
					@ -714,14 +730,14 @@ class TransposedFont:
 | 
				
			||||||
            return 0, 0, height, width
 | 
					            return 0, 0, height, width
 | 
				
			||||||
        return 0, 0, width, height
 | 
					        return 0, 0, width, height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getlength(self, text, *args, **kwargs):
 | 
					    def getlength(self, text: str, *args, **kwargs) -> float:
 | 
				
			||||||
        if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
 | 
					        if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
 | 
				
			||||||
            msg = "text length is undefined for text rotated by 90 or 270 degrees"
 | 
					            msg = "text length is undefined for text rotated by 90 or 270 degrees"
 | 
				
			||||||
            raise ValueError(msg)
 | 
					            raise ValueError(msg)
 | 
				
			||||||
        return self.font.getlength(text, *args, **kwargs)
 | 
					        return self.font.getlength(text, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def load(filename):
 | 
					def load(filename: str) -> ImageFont:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Load a font file.  This function loads a font object from the given
 | 
					    Load a font file.  This function loads a font object from the given
 | 
				
			||||||
    bitmap font file, and returns the corresponding font object.
 | 
					    bitmap font file, and returns the corresponding font object.
 | 
				
			||||||
| 
						 | 
					@ -735,7 +751,13 @@ def load(filename):
 | 
				
			||||||
    return f
 | 
					    return f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def truetype(font=None, size=10, index=0, encoding="", layout_engine=None):
 | 
					def truetype(
 | 
				
			||||||
 | 
					    font: StrOrBytesPath | BinaryIO | None = None,
 | 
				
			||||||
 | 
					    size: float = 10,
 | 
				
			||||||
 | 
					    index: int = 0,
 | 
				
			||||||
 | 
					    encoding: str = "",
 | 
				
			||||||
 | 
					    layout_engine: Layout | None = None,
 | 
				
			||||||
 | 
					) -> FreeTypeFont:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Load a TrueType or OpenType font from a file or file-like object,
 | 
					    Load a TrueType or OpenType font from a file or file-like object,
 | 
				
			||||||
    and create a font object.
 | 
					    and create a font object.
 | 
				
			||||||
| 
						 | 
					@ -796,7 +818,7 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None):
 | 
				
			||||||
    :exception ValueError: If the font size is not greater than zero.
 | 
					    :exception ValueError: If the font size is not greater than zero.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def freetype(font):
 | 
					    def freetype(font: StrOrBytesPath | BinaryIO | None) -> FreeTypeFont:
 | 
				
			||||||
        return FreeTypeFont(font, size, index, encoding, layout_engine)
 | 
					        return FreeTypeFont(font, size, index, encoding, layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -846,7 +868,7 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None):
 | 
				
			||||||
        raise
 | 
					        raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def load_path(filename):
 | 
					def load_path(filename: str | bytes) -> ImageFont:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a
 | 
					    Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a
 | 
				
			||||||
    bitmap font along the Python path.
 | 
					    bitmap font along the Python path.
 | 
				
			||||||
| 
						 | 
					@ -855,14 +877,13 @@ def load_path(filename):
 | 
				
			||||||
    :return: A font object.
 | 
					    :return: A font object.
 | 
				
			||||||
    :exception OSError: If the file could not be read.
 | 
					    :exception OSError: If the file could not be read.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    if not isinstance(filename, str):
 | 
				
			||||||
 | 
					        filename = filename.decode("utf-8")
 | 
				
			||||||
    for directory in sys.path:
 | 
					    for directory in sys.path:
 | 
				
			||||||
        if is_directory(directory):
 | 
					        try:
 | 
				
			||||||
            if not isinstance(filename, str):
 | 
					            return load(os.path.join(directory, filename))
 | 
				
			||||||
                filename = filename.decode("utf-8")
 | 
					        except OSError:
 | 
				
			||||||
            try:
 | 
					            pass
 | 
				
			||||||
                return load(os.path.join(directory, filename))
 | 
					 | 
				
			||||||
            except OSError:
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
    msg = "cannot find font file"
 | 
					    msg = "cannot find font file"
 | 
				
			||||||
    raise OSError(msg)
 | 
					    raise OSError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -881,6 +902,7 @@ def load_default(size: float | None = None) -> FreeTypeFont | ImageFont:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :return: A font object.
 | 
					    :return: A font object.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    f: FreeTypeFont | ImageFont
 | 
				
			||||||
    if core.__class__.__name__ == "module" or size is not None:
 | 
					    if core.__class__.__name__ == "module" or size is not None:
 | 
				
			||||||
        f = truetype(
 | 
					        f = truetype(
 | 
				
			||||||
            BytesIO(
 | 
					            BytesIO(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from typing import Sequence
 | 
					from typing import Any, Sequence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from . import Image
 | 
					from . import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ class Transform(Image.ImageTransformHandler):
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        size: tuple[int, int],
 | 
					        size: tuple[int, int],
 | 
				
			||||||
        image: Image.Image,
 | 
					        image: Image.Image,
 | 
				
			||||||
        **options: dict[str, str | int | tuple[int, ...] | list[int]],
 | 
					        **options: Any,
 | 
				
			||||||
    ) -> Image.Image:
 | 
					    ) -> Image.Image:
 | 
				
			||||||
        """Perform the transform. Called from :py:meth:`.Image.transform`."""
 | 
					        """Perform the transform. Called from :py:meth:`.Image.transform`."""
 | 
				
			||||||
        # can be overridden
 | 
					        # can be overridden
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -426,7 +426,7 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        return s
 | 
					        return s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draft(
 | 
					    def draft(
 | 
				
			||||||
        self, mode: str, size: tuple[int, int]
 | 
					        self, mode: str | None, size: tuple[int, int]
 | 
				
			||||||
    ) -> tuple[str, tuple[int, int, float, float]] | None:
 | 
					    ) -> tuple[str, tuple[int, int, float, float]] | None:
 | 
				
			||||||
        if len(self.tile) != 1:
 | 
					        if len(self.tile) != 1:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,16 @@
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImagingCore:
 | 
				
			||||||
 | 
					    def __getattr__(self, name: str) -> Any: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImagingFont:
 | 
				
			||||||
 | 
					    def __getattr__(self, name: str) -> Any: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImagingDraw:
 | 
				
			||||||
 | 
					    def __getattr__(self, name: str) -> Any: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PixelAccess:
 | 
				
			||||||
 | 
					    def __getattr__(self, name: str) -> Any: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def font(image, glyphdata: bytes) -> ImagingFont: ...
 | 
				
			||||||
def __getattr__(name: str) -> Any: ...
 | 
					def __getattr__(name: str) -> Any: ...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,69 @@
 | 
				
			||||||
from typing import Any
 | 
					from typing import Any, TypedDict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from . import _imaging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _Axis(TypedDict):
 | 
				
			||||||
 | 
					    minimum: int | None
 | 
				
			||||||
 | 
					    default: int | None
 | 
				
			||||||
 | 
					    maximum: int | None
 | 
				
			||||||
 | 
					    name: bytes | None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Font:
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def family(self) -> str | None: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def style(self) -> str | None: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def ascent(self) -> int: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def descent(self) -> int: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def height(self) -> int: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def x_ppem(self) -> int: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def y_ppem(self) -> int: ...
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def glyphs(self) -> int: ...
 | 
				
			||||||
 | 
					    def render(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        string: str,
 | 
				
			||||||
 | 
					        fill,
 | 
				
			||||||
 | 
					        mode=...,
 | 
				
			||||||
 | 
					        dir=...,
 | 
				
			||||||
 | 
					        features=...,
 | 
				
			||||||
 | 
					        lang=...,
 | 
				
			||||||
 | 
					        stroke_width=...,
 | 
				
			||||||
 | 
					        anchor=...,
 | 
				
			||||||
 | 
					        foreground_ink_long=...,
 | 
				
			||||||
 | 
					        x_start=...,
 | 
				
			||||||
 | 
					        y_start=...,
 | 
				
			||||||
 | 
					        /,
 | 
				
			||||||
 | 
					    ) -> tuple[_imaging.ImagingCore, tuple[int, int]]: ...
 | 
				
			||||||
 | 
					    def getsize(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        string: str | bytes | bytearray,
 | 
				
			||||||
 | 
					        mode=...,
 | 
				
			||||||
 | 
					        dir=...,
 | 
				
			||||||
 | 
					        features=...,
 | 
				
			||||||
 | 
					        lang=...,
 | 
				
			||||||
 | 
					        anchor=...,
 | 
				
			||||||
 | 
					        /,
 | 
				
			||||||
 | 
					    ) -> tuple[tuple[int, int], tuple[int, int]]: ...
 | 
				
			||||||
 | 
					    def getlength(
 | 
				
			||||||
 | 
					        self, string: str, mode=..., dir=..., features=..., lang=..., /
 | 
				
			||||||
 | 
					    ) -> float: ...
 | 
				
			||||||
 | 
					    def getvarnames(self) -> list[bytes]: ...
 | 
				
			||||||
 | 
					    def getvaraxes(self) -> list[_Axis] | None: ...
 | 
				
			||||||
 | 
					    def setvarname(self, instance_index: int, /) -> None: ...
 | 
				
			||||||
 | 
					    def setvaraxes(self, axes: list[float], /) -> None: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getfont(
 | 
				
			||||||
 | 
					    filename: str | bytes,
 | 
				
			||||||
 | 
					    size: float,
 | 
				
			||||||
 | 
					    index=...,
 | 
				
			||||||
 | 
					    encoding=...,
 | 
				
			||||||
 | 
					    font_bytes=...,
 | 
				
			||||||
 | 
					    layout_engine=...,
 | 
				
			||||||
 | 
					) -> Font: ...
 | 
				
			||||||
def __getattr__(name: str) -> Any: ...
 | 
					def __getattr__(name: str) -> Any: ...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user