Skip to content

Commit eed5926

Browse files
committed
Moved Anchor and Direction into ImageFont
1 parent 0e0515c commit eed5926

File tree

8 files changed

+68
-60
lines changed

8 files changed

+68
-60
lines changed

Tests/test_imagefont.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from packaging.version import parse as parse_version
1515

1616
from PIL import Image, ImageDraw, ImageFont, features
17-
from PIL._typing import Anchor, StrOrBytesPath
17+
from PIL._typing import StrOrBytesPath
1818

1919
from .helper import (
2020
assert_image_equal,
@@ -795,7 +795,7 @@ def test_variation_set_by_axes(font: ImageFont.FreeTypeFont) -> None:
795795
ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
796796
)
797797
def test_anchor(
798-
layout_engine: ImageFont.Layout, anchor: Anchor, left: int, top: int
798+
layout_engine: ImageFont.Layout, anchor: ImageFont.Anchor, left: int, top: int
799799
) -> None:
800800
name, text = "quick", "Quick"
801801
path = f"Tests/images/test_anchor_{name}_{anchor}.png"
@@ -842,7 +842,7 @@ def test_anchor(
842842
),
843843
)
844844
def test_anchor_multiline(
845-
layout_engine: ImageFont.Layout, anchor: Anchor, align: ImageDraw.Align
845+
layout_engine: ImageFont.Layout, anchor: ImageFont.Anchor, align: ImageDraw.Align
846846
) -> None:
847847
target = f"Tests/images/test_anchor_multiline_{anchor}_{align}.png"
848848
text = "a\nlong\ntext sample"
@@ -880,7 +880,7 @@ def test_anchor_invalid(font: ImageFont.FreeTypeFont) -> None:
880880
with pytest.raises(ValueError):
881881
d.multiline_textbbox((0, 0), "foo\nbar", anchor=anchor) # type: ignore[arg-type]
882882

883-
anchors: list[Anchor] = ["lt", "lb"]
883+
anchors: list[ImageFont.Anchor] = ["lt", "lb"]
884884
for anchor2 in anchors:
885885
with pytest.raises(ValueError):
886886
d.multiline_text((0, 0), "foo\nbar", anchor=anchor2)

Tests/test_imagefontctl.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import pytest
44

55
from PIL import Image, ImageDraw, ImageFont
6-
from PIL._typing import Anchor, Direction
76

87
from .helper import assert_image_similar_tofile, skip_unless_feature
98

@@ -233,7 +232,9 @@ def test_getlength(
233232
("i" + ("\u030C" * 15) + "i", "i" + "\u032C" * 15 + "i", "\u035Cii", "i\u0305i"),
234233
ids=("caron-above", "caron-below", "double-breve", "overline"),
235234
)
236-
def test_getlength_combine(mode: str, direction: Direction, text: str) -> None:
235+
def test_getlength_combine(
236+
mode: str, direction: ImageFont.Direction, text: str
237+
) -> None:
237238
if text == "i\u0305i" and direction == "ttb":
238239
pytest.skip("fails with this font")
239240

@@ -253,7 +254,7 @@ def test_getlength_combine(mode: str, direction: Direction, text: str) -> None:
253254

254255

255256
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
256-
def test_anchor_ttb(anchor: Anchor) -> None:
257+
def test_anchor_ttb(anchor: ImageFont.Anchor) -> None:
257258
text = "f"
258259
path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png"
259260
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120)
@@ -310,7 +311,11 @@ def test_anchor_ttb(anchor: Anchor) -> None:
310311
"name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
311312
)
312313
def test_combine(
313-
name: str, text: str, anchor: Anchor | None, dir: Direction | None, epsilon: float
314+
name: str,
315+
text: str,
316+
anchor: ImageFont.Anchor | None,
317+
dir: ImageFont.Direction | None,
318+
epsilon: float,
314319
) -> None:
315320
path = f"Tests/images/test_combine_{name}.png"
316321
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
@@ -342,7 +347,7 @@ def test_combine(
342347
("rm", "right"), # pass with getsize
343348
),
344349
)
345-
def test_combine_multiline(anchor: Anchor, align: ImageDraw.Align) -> None:
350+
def test_combine_multiline(anchor: ImageFont.Anchor, align: ImageDraw.Align) -> None:
346351
# test that multiline text uses getlength, not getsize or getbbox
347352

348353
path = f"Tests/images/test_combine_multiline_{anchor}_{align}.png"

docs/example/anchors.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
from __future__ import annotations
22

33
from PIL import Image, ImageDraw, ImageFont
4-
from PIL._typing import Anchor
54

65
font = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 16)
76

87

9-
def test(anchor: Anchor) -> Image.Image:
8+
def test(anchor: ImageFont.Anchor) -> Image.Image:
109
im = Image.new("RGBA", (200, 100), "white")
1110
d = ImageDraw.Draw(im)
1211
d.line(((100, 0), (100, 100)), "gray")
@@ -18,7 +17,7 @@ def test(anchor: Anchor) -> Image.Image:
1817
if __name__ == "__main__":
1918
im = Image.new("RGBA", (600, 300), "white")
2019
d = ImageDraw.Draw(im)
21-
anchors: list[list[Anchor]] = [
20+
anchors: list[list[ImageFont.Anchor]] = [
2221
["ma", "mt", "mm"],
2322
["ms", "mb", "md"],
2423
["ls", "ms", "rs"],

docs/reference/ImageFont.rst

+5
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ Constants
9292
raise a :py:exc:`ValueError` if the number of characters is over this limit. The
9393
check can be disabled by setting ``ImageFont.MAX_STRING_LENGTH = None``.
9494

95+
.. class:: Anchor
96+
97+
Type hint literal with the possible anchor values. See :ref:`text-anchors` for
98+
details.
99+
95100
Dictionaries
96101
------------
97102

src/PIL/ImageDraw.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
from . import Image, ImageColor
4141
from ._deprecate import deprecate
42-
from ._typing import Anchor, Coords, Direction
42+
from ._typing import Coords
4343

4444
# experimental access to the outline API
4545
Outline: Callable[[], Image.core._Outline] | None
@@ -585,10 +585,10 @@ def text(
585585
| ImageFont.TransposedFont
586586
| None
587587
) = None,
588-
anchor: Anchor | None = None,
588+
anchor: ImageFont.Anchor | None = None,
589589
spacing: float = 4,
590590
align: Align = "left",
591-
direction: Direction | None = None,
591+
direction: ImageFont.Direction | None = None,
592592
features: list[str] | None = None,
593593
language: str | None = None,
594594
stroke_width: float = 0,
@@ -710,10 +710,10 @@ def multiline_text(
710710
| ImageFont.TransposedFont
711711
| None
712712
) = None,
713-
anchor: Anchor | None = None,
713+
anchor: ImageFont.Anchor | None = None,
714714
spacing: float = 4,
715715
align: Align = "left",
716-
direction: Direction | None = None,
716+
direction: ImageFont.Direction | None = None,
717717
features: list[str] | None = None,
718718
language: str | None = None,
719719
stroke_width: float = 0,
@@ -800,7 +800,7 @@ def textlength(
800800
| ImageFont.TransposedFont
801801
| None
802802
) = None,
803-
direction: Direction | None = None,
803+
direction: ImageFont.Direction | None = None,
804804
features: list[str] | None = None,
805805
language: str | None = None,
806806
embedded_color: bool = False,
@@ -830,10 +830,10 @@ def textbbox(
830830
| ImageFont.TransposedFont
831831
| None
832832
) = None,
833-
anchor: Anchor | None = None,
833+
anchor: ImageFont.Anchor | None = None,
834834
spacing: float = 4,
835835
align: Align = "left",
836-
direction: Direction | None = None,
836+
direction: ImageFont.Direction | None = None,
837837
features: list[str] | None = None,
838838
language: str | None = None,
839839
stroke_width: float = 0,
@@ -880,10 +880,10 @@ def multiline_textbbox(
880880
| ImageFont.TransposedFont
881881
| None
882882
) = None,
883-
anchor: Anchor | None = None,
883+
anchor: ImageFont.Anchor | None = None,
884884
spacing: float = 4,
885885
align: Align = "left",
886-
direction: Direction | None = None,
886+
direction: ImageFont.Direction | None = None,
887887
features: list[str] | None = None,
888888
language: str | None = None,
889889
stroke_width: float = 0,

src/PIL/ImageFont.py

+31-2
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,46 @@
3434
from enum import IntEnum
3535
from io import BytesIO
3636
from types import ModuleType
37-
from typing import IO, TYPE_CHECKING, Any, BinaryIO, TypedDict, cast
37+
from typing import IO, TYPE_CHECKING, Any, BinaryIO, Literal, TypedDict, cast
3838

3939
from . import Image, features
40-
from ._typing import Anchor, Direction, StrOrBytesPath
40+
from ._typing import StrOrBytesPath
4141
from ._util import DeferredError, is_path
4242

4343
if TYPE_CHECKING:
4444
from . import ImageFile
4545
from ._imaging import ImagingFont
4646
from ._imagingft import Font
4747

48+
Anchor = Literal[
49+
"la",
50+
"lt",
51+
"lm",
52+
"ls",
53+
"lb",
54+
"ld",
55+
"ma",
56+
"mt",
57+
"mm",
58+
"ms",
59+
"mb",
60+
"md",
61+
"ra",
62+
"rt",
63+
"rm",
64+
"rs",
65+
"rb",
66+
"rd",
67+
"sa",
68+
"st",
69+
"sm",
70+
"ss",
71+
"sb",
72+
"sd",
73+
]
74+
75+
Direction = Literal["rtl", "ltr", "ttb"]
76+
4877

4978
class Axis(TypedDict):
5079
minimum: int | None

src/PIL/_imagingft.pyi

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from typing import Any, Callable
22

33
from . import ImageFont, _imaging
4-
from ._typing import Anchor, Direction
54

65
class Font:
76
@property
@@ -25,11 +24,11 @@ class Font:
2524
string: str | bytes,
2625
fill: Callable[[int, int], _imaging.ImagingCore],
2726
mode: str,
28-
dir: Direction | None,
27+
dir: ImageFont.Direction | None,
2928
features: list[str] | None,
3029
lang: str | None,
3130
stroke_width: float,
32-
anchor: Anchor | None,
31+
anchor: ImageFont.Anchor | None,
3332
foreground_ink_long: int,
3433
x_start: float,
3534
y_start: float,
@@ -39,17 +38,17 @@ class Font:
3938
self,
4039
string: str | bytes | bytearray,
4140
mode: str,
42-
dir: Direction | None,
41+
dir: ImageFont.Direction | None,
4342
features: list[str] | None,
4443
lang: str | None,
45-
anchor: Anchor | None,
44+
anchor: ImageFont.Anchor | None,
4645
/,
4746
) -> tuple[tuple[int, int], tuple[int, int]]: ...
4847
def getlength(
4948
self,
5049
string: str | bytes,
5150
mode: str,
52-
dir: Direction | None,
51+
dir: ImageFont.Direction | None,
5352
features: list[str] | None,
5453
lang: str | None,
5554
/,

src/PIL/_typing.py

+1-30
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import sys
55
from collections.abc import Sequence
6-
from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, Union
6+
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, Union
77

88
if TYPE_CHECKING:
99
from numbers import _IntegralLike as IntegralLike
@@ -49,33 +49,4 @@ def read(self, length: int = ..., /) -> _T_co: ...
4949

5050
StrOrBytesPath = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]
5151

52-
Anchor = Literal[
53-
"la",
54-
"lt",
55-
"lm",
56-
"ls",
57-
"lb",
58-
"ld",
59-
"ma",
60-
"mt",
61-
"mm",
62-
"ms",
63-
"mb",
64-
"md",
65-
"ra",
66-
"rt",
67-
"rm",
68-
"rs",
69-
"rb",
70-
"rd",
71-
"sa",
72-
"st",
73-
"sm",
74-
"ss",
75-
"sb",
76-
"sd",
77-
]
78-
79-
Direction = Literal["rtl", "ltr", "ttb"]
80-
8152
__all__ = ["Buffer", "IntegralLike", "StrOrBytesPath", "SupportsRead", "TypeGuard"]

0 commit comments

Comments
 (0)