Merge pull request #4930 from nulano/anchor-part2

This commit is contained in:
Hugo van Kemenade 2020-10-05 20:19:33 +03:00 committed by GitHub
commit b29cab08d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1844 additions and 21 deletions

View File

@ -1,5 +1,6 @@
NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts NotoNastaliqUrdu-Regular.ttf and NotoSansSymbols-Regular.ttf, from https://github.com/googlei18n/noto-fonts
NotoSans-Regular.ttf, from https://www.google.com/get/noto/
NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/ NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/
AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype
TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1020,7 +1020,7 @@ def test_stroke():
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120) font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120)
# Act # Act
draw.text((10, 10), "A", "#f00", font, stroke_width=2, stroke_fill=stroke_fill) draw.text((12, 12), "A", "#f00", font, stroke_width=2, stroke_fill=stroke_fill)
# Assert # Assert
assert_image_similar_tofile( assert_image_similar_tofile(
@ -1036,7 +1036,7 @@ def test_stroke_descender():
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120) font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120)
# Act # Act
draw.text((10, 0), "y", "#f00", font, stroke_width=2, stroke_fill="#0f0") draw.text((12, 2), "y", "#f00", font, stroke_width=2, stroke_fill="#0f0")
# Assert # Assert
assert_image_similar_tofile(im, "Tests/images/imagedraw_stroke_descender.png", 6.76) assert_image_similar_tofile(im, "Tests/images/imagedraw_stroke_descender.png", 6.76)
@ -1051,7 +1051,7 @@ def test_stroke_multiline():
# Act # Act
draw.multiline_text( draw.multiline_text(
(10, 10), "A\nB", "#f00", font, stroke_width=2, stroke_fill="#0f0" (12, 12), "A\nB", "#f00", font, stroke_width=2, stroke_fill="#0f0"
) )
# Assert # Assert

View File

@ -40,18 +40,21 @@ class TestImageFont:
"textsize": 12, "textsize": 12,
"getters": (13, 16), "getters": (13, 16),
"mask": (107, 13), "mask": (107, 13),
"multiline-anchor": 6,
}, },
(">=2.7",): { (">=2.7",): {
"multiline": 6.2, "multiline": 6.2,
"textsize": 2.5, "textsize": 2.5,
"getters": (12, 16), "getters": (12, 16),
"mask": (108, 13), "mask": (108, 13),
"multiline-anchor": 4,
}, },
"Default": { "Default": {
"multiline": 0.5, "multiline": 0.5,
"textsize": 0.5, "textsize": 0.5,
"getters": (12, 16), "getters": (12, 16),
"mask": (108, 13), "mask": (108, 13),
"multiline-anchor": 4,
}, },
} }
@ -750,6 +753,93 @@ class TestImageFont:
font.set_variation_by_axes([100]) font.set_variation_by_axes([100])
self._check_text(font, "Tests/images/variation_tiny_axes.png", 32.5) self._check_text(font, "Tests/images/variation_tiny_axes.png", 32.5)
@pytest.mark.parametrize(
"anchor",
(
# test horizontal anchors
"ls",
"ms",
"rs",
# test vertical anchors
"ma",
"mt",
"mm",
"mb",
"md",
),
)
def test_anchor(self, anchor):
name, text = "quick", "Quick"
path = f"Tests/images/test_anchor_{name}_{anchor}.png"
f = ImageFont.truetype(
"Tests/fonts/NotoSans-Regular.ttf", 48, layout_engine=self.LAYOUT_ENGINE
)
im = Image.new("RGB", (200, 200), "white")
d = ImageDraw.Draw(im)
d.line(((0, 100), (200, 100)), "gray")
d.line(((100, 0), (100, 200)), "gray")
d.text((100, 100), text, fill="black", anchor=anchor, font=f)
with Image.open(path) as expected:
assert_image_similar(im, expected, 7)
@pytest.mark.parametrize(
"anchor,align",
(
# test horizontal anchors
("lm", "left"),
("lm", "center"),
("lm", "right"),
("mm", "left"),
("mm", "center"),
("mm", "right"),
("rm", "left"),
("rm", "center"),
("rm", "right"),
# test vertical anchors
("ma", "center"),
# ("mm", "center"), # duplicate
("md", "center"),
),
)
def test_anchor_multiline(self, anchor, align):
target = f"Tests/images/test_anchor_multiline_{anchor}_{align}.png"
text = "a\nlong\ntext sample"
f = ImageFont.truetype(
"Tests/fonts/NotoSans-Regular.ttf", 48, layout_engine=self.LAYOUT_ENGINE
)
# test render
im = Image.new("RGB", (600, 400), "white")
d = ImageDraw.Draw(im)
d.line(((0, 200), (600, 200)), "gray")
d.line(((300, 0), (300, 400)), "gray")
d.multiline_text(
(300, 200), text, fill="black", anchor=anchor, font=f, align=align
)
with Image.open(target) as expected:
assert_image_similar(im, expected, self.metrics["multiline-anchor"])
def test_anchor_invalid(self):
font = self.get_font()
im = Image.new("RGB", (100, 100), "white")
d = ImageDraw.Draw(im)
d.font = font
for anchor in ["", "l", "a", "lax", "sa", "xa", "lx"]:
pytest.raises(ValueError, lambda: font.getmask2("hello", anchor=anchor))
pytest.raises(ValueError, lambda: d.text((0, 0), "hello", anchor=anchor))
pytest.raises(
ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
)
for anchor in ["lt", "lb"]:
pytest.raises(
ValueError, lambda: d.multiline_text((0, 0), "foo\nbar", anchor=anchor)
)
@skip_unless_feature("raqm") @skip_unless_feature("raqm")
class TestImageFont_RaqmLayout(TestImageFont): class TestImageFont_RaqmLayout(TestImageFont):

View File

@ -1,6 +1,7 @@
import pytest import pytest
from packaging.version import parse as parse_version
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont, features
from .helper import assert_image_similar, skip_unless_feature from .helper import assert_image_similar, skip_unless_feature
@ -123,7 +124,7 @@ def test_text_direction_ttb_stroke():
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
try: try:
draw.text( draw.text(
(25, 25), (27, 27),
"あい", "あい",
font=ttf, font=ttf,
fill=500, fill=500,
@ -206,3 +207,118 @@ def test_language():
target = "Tests/images/test_language.png" target = "Tests/images/test_language.png"
with Image.open(target) as target_img: with Image.open(target) as target_img:
assert_image_similar(im, target_img, 0.5) assert_image_similar(im, target_img, 0.5)
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
def test_anchor_ttb(anchor):
if parse_version(features.version_module("freetype2")) < parse_version("2.5.1"):
# FreeType 2.5.1 README: Miscellaneous Changes:
# Improved computation of emulated vertical metrics for TrueType fonts.
pytest.skip("FreeType <2.5.1 has incompatible ttb metrics")
text = "f"
path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png"
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120)
im = Image.new("RGB", (200, 400), "white")
d = ImageDraw.Draw(im)
d.line(((0, 200), (200, 200)), "gray")
d.line(((100, 0), (100, 400)), "gray")
try:
d.text((100, 200), text, fill="black", anchor=anchor, direction="ttb", font=f)
except ValueError as ex:
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
pytest.skip("libraqm 0.7 or greater not available")
with Image.open(path) as expected:
assert_image_similar(im, expected, 1) # fails at 5
combine_tests = (
# extends above (e.g. issue #4553)
("caron", "a\u030C\u030C\u030C\u030C\u030Cb", None, None, 0.08),
("caron_la", "a\u030C\u030C\u030C\u030C\u030Cb", "la", None, 0.08),
("caron_lt", "a\u030C\u030C\u030C\u030C\u030Cb", "lt", None, 0.08),
("caron_ls", "a\u030C\u030C\u030C\u030C\u030Cb", "ls", None, 0.08),
("caron_ttb", "ca" + ("\u030C" * 15) + "b", None, "ttb", 0.3),
("caron_ttb_lt", "ca" + ("\u030C" * 15) + "b", "lt", "ttb", 0.3),
# extends below
("caron_below", "a\u032C\u032C\u032C\u032C\u032Cb", None, None, 0.02),
("caron_below_ld", "a\u032C\u032C\u032C\u032C\u032Cb", "ld", None, 0.02),
("caron_below_lb", "a\u032C\u032C\u032C\u032C\u032Cb", "lb", None, 0.02),
("caron_below_ls", "a\u032C\u032C\u032C\u032C\u032Cb", "ls", None, 0.02),
("caron_below_ttb", "a" + ("\u032C" * 15) + "b", None, "ttb", 0.03),
("caron_below_ttb_lb", "a" + ("\u032C" * 15) + "b", "lb", "ttb", 0.03),
# extends to the right (e.g. issue #3745)
("double_breve_below", "a\u035Ci", None, None, 0.02),
("double_breve_below_ma", "a\u035Ci", "ma", None, 0.02),
("double_breve_below_ra", "a\u035Ci", "ra", None, 0.02),
("double_breve_below_ttb", "a\u035Cb", None, "ttb", 0.02),
("double_breve_below_ttb_rt", "a\u035Cb", "rt", "ttb", 0.02),
("double_breve_below_ttb_mt", "a\u035Cb", "mt", "ttb", 0.02),
("double_breve_below_ttb_st", "a\u035Cb", "st", "ttb", 0.02),
# extends to the left (fail=0.064)
("overline", "i\u0305", None, None, 0.02),
("overline_la", "i\u0305", "la", None, 0.02),
("overline_ra", "i\u0305", "ra", None, 0.02),
("overline_ttb", "i\u0305", None, "ttb", 0.02),
("overline_ttb_rt", "i\u0305", "rt", "ttb", 0.02),
("overline_ttb_mt", "i\u0305", "mt", "ttb", 0.02),
("overline_ttb_st", "i\u0305", "st", "ttb", 0.02),
)
# this tests various combining characters for anchor alignment and clipping
@pytest.mark.parametrize(
"name,text,anchor,dir,epsilon", combine_tests, ids=[r[0] for r in combine_tests]
)
def test_combine(name, text, dir, anchor, epsilon):
if (
parse_version(features.version_module("freetype2")) < parse_version("2.5.1")
and dir == "ttb"
):
# FreeType 2.5.1 README: Miscellaneous Changes:
# Improved computation of emulated vertical metrics for TrueType fonts.
pytest.skip("FreeType <2.5.1 has incompatible ttb metrics")
path = f"Tests/images/test_combine_{name}.png"
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
im = Image.new("RGB", (400, 400), "white")
d = ImageDraw.Draw(im)
d.line(((0, 200), (400, 200)), "gray")
d.line(((200, 0), (200, 400)), "gray")
try:
d.text((200, 200), text, fill="black", anchor=anchor, direction=dir, font=f)
except ValueError as ex:
if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction":
pytest.skip("libraqm 0.7 or greater not available")
with Image.open(path) as expected:
assert_image_similar(im, expected, epsilon)
def test_anchor_invalid_ttb():
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new("RGB", (100, 100), "white")
d = ImageDraw.Draw(im)
d.font = font
for anchor in ["", "l", "a", "lax", "xa", "la", "ls", "ld", "lx"]:
pytest.raises(
ValueError, lambda: font.getmask2("hello", anchor=anchor, direction="ttb")
)
pytest.raises(
ValueError, lambda: d.text((0, 0), "hello", anchor=anchor, direction="ttb")
)
pytest.raises(
ValueError,
lambda: d.multiline_text(
(0, 0), "foo\nbar", anchor=anchor, direction="ttb"
),
)
# ttb multiline text does not support anchors at all
pytest.raises(
ValueError,
lambda: d.multiline_text((0, 0), "foo\nbar", anchor="mm", direction="ttb"),
)

BIN
docs/example/anchors.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

28
docs/example/anchors.py Normal file
View File

@ -0,0 +1,28 @@
from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 16)
def test(anchor):
im = Image.new("RGBA", (200, 100), "white")
d = ImageDraw.Draw(im)
d.line(((100, 0), (100, 100)), "gray")
d.line(((0, 50), (200, 50)), "gray")
d.text((100, 50), f"{anchor} example", "black", font, anchor)
return im
if __name__ == "__main__":
im = Image.new("RGBA", (600, 300), "white")
d = ImageDraw.Draw(im)
for y, row in enumerate(
(("ma", "mt", "mm"), ("ms", "mb", "md"), ("ls", "ms", "rs"))
):
for x, anchor in enumerate(row):
im.paste(test(anchor), (x * 200, y * 100))
if x != 0:
d.line(((x * 200, y * 100), (x * 200, (y + 1) * 100)), "black", 3)
if y != 0:
d.line(((x * 200, y * 100), ((x + 1) * 200, y * 100)), "black", 3)
im.save("docs/example/anchors.png")
im.show()

View File

@ -7,4 +7,5 @@ Appendices
:maxdepth: 2 :maxdepth: 2
image-file-formats image-file-formats
text-anchors
writing-your-own-file-decoder writing-your-own-file-decoder

View File

@ -0,0 +1,140 @@
.. _text-anchors:
Text anchors
============
The ``anchor`` parameter determines the alignment of drawn text relative to the ``xy`` parameter.
The default alignment is top left, specifically ``la`` (left-ascender) for horizontal text
and ``lt`` (left-top) for vertical text.
This parameter is only supported by OpenType/TrueType fonts.
Other fonts may ignore the parameter and use the default (top left) alignment.
Specifying an anchor
^^^^^^^^^^^^^^^^^^^^
An anchor is specified with a two-character string. The first character is the
horizontal alignment, the second character is the vertical alignment.
For example, the default value of ``la`` for horizontal text means left-ascender
aligned text.
When drawing text with :py:meth:`PIL.ImageDraw.ImageDraw.text` with a specific anchor,
the text will be placed such that the specified anchor point is at the ``xy`` coordinates.
For example, in the following image, the text is ``ms`` (middle-baseline) aligned, with
``xy`` at the intersection of the two lines:
.. image:: ../../Tests/images/test_anchor_quick_ms.png
:alt: ms (middle-baseline) aligned text.
:align: left
.. code-block:: python
from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
im = Image.new("RGB", (200, 200), "white")
d = ImageDraw.Draw(im)
d.line(((0, 100), (200, 100)), "gray")
d.line(((100, 0), (100, 200)), "gray")
d.text((100, 100), "Quick", fill="black", anchor="ms", font=font)
.. container:: clearer
|
.. only: comment
The container above prevents the image alignment from affecting the following text.
Quick reference
^^^^^^^^^^^^^^^
.. image:: ../resources/anchor_horizontal.svg
:alt: Horizontal text
:align: center
.. image:: ../resources/anchor_vertical.svg
:alt: Vertical text
:align: center
Horizontal anchor alignment
^^^^^^^^^^^^^^^^^^^^^^^^^^^
``l`` --- left
Anchor is to the left of the text.
For *horizontal* text this is the origin of the first glyph, as shown in the `FreeType tutorial`_.
``m`` --- middle
Anchor is horizontally centered with the text.
For *vertical* text it is recommended to use ``s`` (baseline) alignment instead,
as it does not change based on the specific glyphs of the given text.
``r`` --- right
Anchor is to the right of the text.
For *horizontal* text this is the advanced origin of the last glyph, as shown in the `FreeType tutorial`_.
``s`` --- baseline *(vertical text only)*
Anchor is at the baseline (middle) of the text. The exact alignment depends on the font.
For *vertical* text this is the recommended alignment,
as it does not change based on the specific glyphs of the given text
(see image for vertical text above).
Vertical anchor alignment
^^^^^^^^^^^^^^^^^^^^^^^^^
``a`` --- ascender / top *(horizontal text only)*
Anchor is at the ascender line (top) of the first line of text, as defined by the font.
See `Font metrics on Wikipedia`_ for more information.
``t`` --- top *(single-line text only)*
Anchor is at the top of the text.
For *vertical* text this is the origin of the first glyph, as shown in the `FreeType tutorial`_.
For *horizontal* text it is recommended to use ``a`` (ascender) alignment instead,
as it does not change based on the specific glyphs of the given text.
``m`` --- middle
Anchor is vertically centered with the text.
For *horizontal* text this is the midpoint of the first ascender line and the last descender line.
``s`` --- baseline *(horizontal text only)*
Anchor is at the baseline (bottom) of the first line of text, only descenders extend below the anchor.
See `Font metrics on Wikipedia`_ for more information.
``b`` --- bottom *(single-line text only)*
Anchor is at the bottom of the text.
For *vertical* text this is the advanced origin of the last glyph, as shown in the `FreeType tutorial`_.
For *horizontal* text it is recommended to use ``d`` (descender) alignment instead,
as it does not change based on the specific glyphs of the given text.
``d`` --- descender / bottom *(horizontal text only)*
Anchor is at the descender line (bottom) of the last line of text, as defined by the font.
See `Font metrics on Wikipedia`_ for more information.
Examples
^^^^^^^^
The following image shows several examples of anchors for horizontal text.
In each section the ``xy`` parameter was set to the center shown by the intersection
of the two lines.
.. comment: Image generated with ../example/anchors.py
.. image:: ../example/anchors.png
:alt: Text anchor examples
:align: center
.. _Font metrics on Wikipedia: https://en.wikipedia.org/wiki/Typeface#Font_metrics
.. _FreeType tutorial: https://freetype.org/freetype2/docs/tutorial/step2.html

View File

@ -295,18 +295,27 @@ Methods
Draws the string at the given position. Draws the string at the given position.
:param xy: Top left corner of the text. :param xy: The anchor coordinates of the text.
:param text: Text to be drawn. If it contains any newline characters, :param text: Text to be drawn. If it contains any newline characters,
the text is passed on to the text is passed on to
:py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`. :py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`.
:param fill: Color to use for the text. :param fill: Color to use for the text.
:param font: An :py:class:`~PIL.ImageFont.ImageFont` instance. :param font: An :py:class:`~PIL.ImageFont.ImageFont` instance.
:param anchor: The text anchor alignment. Determines the relative location of
the anchor to the text. The default alignment is top left.
See :ref:`text-anchors` for valid values. This parameter is
ignored for non-TrueType fonts.
.. note:: This parameter was present in earlier versions
of Pillow, but implemented only in version 8.0.0.
:param spacing: If the text is passed on to :param spacing: If the text is passed on to
:py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`, :py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`,
the number of pixels between lines. the number of pixels between lines.
:param align: If the text is passed on to :param align: If the text is passed on to
:py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`, :py:meth:`~PIL.ImageDraw.ImageDraw.multiline_text`,
``"left"``, ``"center"`` or ``"right"``. ``"left"``, ``"center"`` or ``"right"``. Determines the relative alignment of lines.
Use the ``anchor`` parameter to specify the alignment to ``xy``.
:param direction: Direction of the text. It can be ``"rtl"`` (right to :param direction: Direction of the text. It can be ``"rtl"`` (right to
left), ``"ltr"`` (left to right) or ``"ttb"`` (top to bottom). left), ``"ltr"`` (left to right) or ``"ttb"`` (top to bottom).
Requires libraqm. Requires libraqm.
@ -347,12 +356,22 @@ Methods
Draws the string at the given position. Draws the string at the given position.
:param xy: Top left corner of the text. :param xy: The anchor coordinates of the text.
:param text: Text to be drawn. :param text: Text to be drawn.
:param fill: Color to use for the text. :param fill: Color to use for the text.
:param font: An :py:class:`~PIL.ImageFont.ImageFont` instance. :param font: An :py:class:`~PIL.ImageFont.ImageFont` instance.
:param anchor: The text anchor alignment. Determines the relative location of
the anchor to the text. The default alignment is top left.
See :ref:`text-anchors` for valid values. This parameter is
ignored for non-TrueType fonts.
.. note:: This parameter was present in earlier versions
of Pillow, but implemented only in version 8.0.0.
:param spacing: The number of pixels between lines. :param spacing: The number of pixels between lines.
:param align: ``"left"``, ``"center"`` or ``"right"``. :param align: ``"left"``, ``"center"`` or ``"right"``. Determines the relative alignment of lines.
Use the ``anchor`` parameter to specify the alignment to ``xy``.
:param direction: Direction of the text. It can be ``"rtl"`` (right to :param direction: Direction of the text. It can be ``"rtl"`` (right to
left), ``"ltr"`` (left to right) or ``"ttb"`` (top to bottom). left), ``"ltr"`` (left to right) or ``"ttb"`` (top to bottom).
Requires libraqm. Requires libraqm.

View File

@ -0,0 +1,467 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1000"
height="400"
viewBox="0 0 264.58333 105.83334"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="pillow horizontal text anchors.svg">
<title
id="title4950">Pillow horizontal text anchors</title>
<defs
id="defs2">
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4674"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1;fill:#ff0000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5227"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5225-6" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5539"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5537" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2021"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2024"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5227-5"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5225-9" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5539-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5537-2" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-5"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2021-9"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-3"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2024-8"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="339.39852"
inkscape:cy="87.176034"
inkscape:document-units="mm"
inkscape:current-layer="layer5"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
inkscape:snap-midpoints="true"
inkscape:window-width="2560"
inkscape:window-height="1021"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-text-baseline="false"
inkscape:object-paths="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Pillow horizontal text anchors</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="H Middle">
<path
style="fill:none;stroke:#0000ff;stroke-width:0.52916673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833346,0.52916673;stroke-dashoffset:0;stroke-opacity:1"
d="m 5.6516665,67.64343 247.1324835,0"
id="path4558"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="m 147.60064,43.158629 -68.307632,0"
id="path2019-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715-4"
d="m 79.293008,43.158629 -68.307665,0"
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5227);marker-end:url(#marker5539)" />
<path
style="display:inline;fill:none;stroke:#0000ff;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Lstart-5);marker-end:url(#Arrow1Lend-3)"
d="M 155.2836,34.962797 V 67.64343"
id="path2019-6-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715-4-6"
d="m 155.2836,67.64343 v 32.70925"
style="display:inline;fill:none;stroke:#0000ff;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5227-5);marker-end:url(#marker5539-3)" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Metrics"
style="display:inline">
<path
style="fill:none;stroke:#0000ff;stroke-width:0.84738779;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M -16.124542,87.690473 H 277.4074 m 0,12.662207 H -43.016837 m 0,-65.389883 H 284.00362"
id="path3719"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
<g
inkscape:label="Text"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-191.16665)">
<g
aria-label="Quick"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Noto Sans';-inkscape-font-specification:'Noto Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
id="text3717">
<path
d="m 46.970343,260.29276 q 0,6.6548 -2.6924,11.3792 -2.6416,4.6736 -7.874,6.4008 l 8.6868,9.0424 h -6.5532 l -7.0104,-8.1788 q -0.3048,0 -0.6604,0 -0.3048,0.0508 -0.6096,0.0508 -5.6388,0 -9.398,-2.3368 -3.7084,-2.3368 -5.5372,-6.5532 -1.8288,-4.2164 -1.8288,-9.8552 0,-5.5372 1.8288,-9.7028 1.8288,-4.2164 5.5372,-6.5532 3.7592,-2.3368 9.4488,-2.3368 5.4356,0 9.144,2.3368 3.7084,2.286 5.588,6.5024 1.9304,4.1656 1.9304,9.8044 z m -28.6512,0 q 0,6.858 2.8956,10.8204 2.8956,3.9116 9.0424,3.9116 6.1468,0 8.9916,-3.9116 2.8956,-3.9624 2.8956,-10.8204 0,-6.858 -2.8448,-10.7188 -2.8448,-3.9116 -8.9916,-3.9116 -6.1976,0 -9.0932,3.9116 -2.8956,3.8608 -2.8956,10.7188 z"
style="stroke-width:0.26458332"
id="path5225" />
<path
d="m 77.158243,251.25036 v 27.2288 h -3.6576 l -0.6604,-3.6068 h -0.2032 q -1.3208,2.1336 -3.6576,3.1496 -2.3368,0.9652 -4.9784,0.9652 -4.9276,0 -7.4168,-2.3368 -2.4892,-2.3876 -2.4892,-7.5692 v -17.8308 h 4.5212 v 17.526 q 0,6.5024 6.0452,6.5024 4.5212,0 6.2484,-2.54 1.778,-2.54 1.778,-7.3152 v -14.1732 z"
style="stroke-width:0.26458332"
id="path5227" />
<path
d="m 88.03897,241.03956 q 1.016,0 1.778,0.7112 0.8128,0.6604 0.8128,2.1336 0,1.4732 -0.8128,2.1844 -0.762,0.6604 -1.778,0.6604 -1.1176,0 -1.8796,-0.6604 -0.762,-0.7112 -0.762,-2.1844 0,-1.4732 0.762,-2.1336 0.762,-0.7112 1.8796,-0.7112 z m 2.1844,10.2108 v 27.2288 h -4.4704 v -27.2288 z"
style="stroke-width:0.26458332"
id="path5229" />
<path
d="m 109.77184,278.98716 q -3.6576,0 -6.4516,-1.4732 -2.794,-1.4732 -4.4196,-4.572 -1.5748,-3.0988 -1.5748,-7.9248 0,-5.0292 1.6256,-8.1788 1.6764,-3.1496 4.572,-4.6228 2.8956,-1.4732 6.5532,-1.4732 2.032,0 3.9624,0.4572 1.9812,0.4064 3.2004,1.016 l -1.3716,3.7084 q -1.2192,-0.4572 -2.8448,-0.8636 -1.6256,-0.4064 -3.048,-0.4064 -8.0264,0 -8.0264,10.3124 0,4.9276 1.9304,7.5692 1.9812,2.5908 5.842,2.5908 2.1844,0 3.9116,-0.4572 1.7272,-0.4572 3.1496,-1.1176 v 3.9624 q -1.3716,0.7112 -3.048,1.0668 -1.6256,0.4064 -3.9624,0.4064 z"
style="stroke-width:0.26458332"
id="path5231" />
<path
d="m 127.67725,239.87116 v 20.1676 q 0,0.8128 -0.1016,2.1336 -0.0508,1.3208 -0.1016,2.286 h 0.2032 q 0.3048,-0.4064 0.9144,-1.1684 0.6096,-0.762 1.2192,-1.524 0.6604,-0.8128 1.1176,-1.3208 l 8.6868,-9.1948 h 5.2324 l -11.0236,11.6332 11.7856,15.5956 h -5.3848 l -9.4488,-12.7 -3.0988,2.6924 v 10.0076 h -4.4196 v -38.608 z"
style="stroke-width:0.26458332"
id="path5233" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="V Middle" />
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="BBox">
<rect
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.75980842;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4526"
width="136.61531"
height="47.587673"
x="10.985343"
y="48.608231" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="BBox Lines"
style="display:inline">
<g
id="g4553">
<path
inkscape:connector-curvature="0"
id="path4529"
d="M 10.985343,48.608231 H 1.4268605"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4531"
d="M 10.985343,96.195905 H 1.4470838"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4533"
d="m 147.60064,48.608231 h 65.42674"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4535"
d="m 147.60064,96.195905 h 65.1586"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4537"
d="M 147.60064,48.608231 V 5.8586308"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4539"
d="M 10.985343,48.608231 V 7.5595236"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4541"
d="m 10.985343,96.195903 v 7.558557"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4543"
d="m 147.60064,96.195903 v 7.747547"
style="fill:none;stroke:#f90000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.38125,2.38125;stroke-dashoffset:3.175;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4537-3"
d="m 79.293008,102.35752 0,-95.5086054"
style="display:inline;fill:none;stroke:#f90000;stroke-width:0.529;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.058,0.529;stroke-dashoffset:2.1159995;stroke-opacity:1"
sodipodi:nodetypes="cc" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer7"
inkscape:label="Labels"
style="display:inline">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="224.63124"
y="97.631248"
id="text4564"><tspan
sodipodi:role="line"
id="tspan4562"
x="224.63124"
y="97.631248"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(d) descender</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="224.40128"
y="84.301186"
id="text4564-3"><tspan
sodipodi:role="line"
id="tspan4562-0"
x="224.40128"
y="84.301186"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(s) baseline</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="223.8721"
y="31.384523"
id="text4564-6"><tspan
sodipodi:role="line"
id="tspan4562-3"
x="223.8721"
y="31.384523"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(a) ascender</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="223.34293"
y="63.399109"
id="text4564-9"><tspan
sodipodi:role="line"
x="223.34293"
y="63.399109"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
id="tspan4600">(m) middle</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="187.62418"
y="45.672024"
id="text4564-38"><tspan
sodipodi:role="line"
id="tspan4562-07"
x="187.62418"
y="45.672024"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(t) top</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="183.88542"
y="93.662498"
id="text4614"><tspan
sodipodi:role="line"
id="tspan4612"
x="183.88542"
y="93.662498"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(b) bottom</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="13.792929"
y="11.011606"
id="text4564-7"><tspan
sodipodi:role="line"
id="tspan4562-6"
x="13.792929"
y="11.011606"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(l) left</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="151.60625"
y="11.1125"
id="text4626"><tspan
sodipodi:role="line"
id="tspan4624"
x="151.60625"
y="11.1125"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(r) right</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888889px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
x="81.158325"
y="11.737965"
id="text4630"><tspan
sodipodi:role="line"
id="tspan4628"
x="81.158325"
y="11.737965"
style="stroke-width:0.26458332;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:4.93888889px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">(m) middle</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer8"
inkscape:label="Title">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="183.35623"
y="16.404165"
id="text4635"><tspan
sodipodi:role="line"
id="tspan4633"
x="183.35623"
y="16.404165"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332">Horizontal text</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,841 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="800"
height="600"
viewBox="0 0 211.66666 158.75001"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="pillow vertical text anchors.svg">
<title
id="title1633">Pillow vertical text anchors</title>
<defs
id="defs2">
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5539"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
transform="scale(0.8) rotate(180) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5537" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5373"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
transform="scale(0.8) rotate(180) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5371" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5363"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
transform="scale(0.8) rotate(180) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5361" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path2024"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5227"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5225" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5151"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5149" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5141"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5139" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path2021"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker2753"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#fe0000;stroke-width:1pt;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path2751" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker2719"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mstart">
<path
transform="scale(0.6) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#fe0000;stroke-opacity:1;fill:#fe0000;fill-opacity:1"
id="path2717" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path2039"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) translate(1,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker2719-4"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow2Mstart">
<path
inkscape:connector-curvature="0"
transform="scale(0.6)"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
id="path2717-0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker2753-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path2751-7" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5141-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5139-4" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5363-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5361-7" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5151-4"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5149-8" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5373-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5371-1" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5227-1"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lstart">
<path
inkscape:connector-curvature="0"
transform="matrix(0.8,0,0,0.8,10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5225-3" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5539-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path5537-6" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-1"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2021-6"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-8"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
id="path2024-1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#fe0000;fill-opacity:1;fill-rule:evenodd;stroke:#fe0000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="325.91895"
inkscape:cy="341.12077"
inkscape:document-units="mm"
inkscape:current-layer="g867"
showgrid="false"
units="px"
inkscape:window-width="2560"
inkscape:window-height="1021"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:object-paths="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Pillow vertical text anchors</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Baseline"
transform="translate(0,52.916667)"
style="display:inline">
<path
style="fill:none;stroke:#0000ff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 25.513393,109.99107 V -63.122024"
id="path820"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path1896"
d="M 129.49464,109.99107 V -63.122024"
style="fill:none;stroke:#0000ff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
inkscape:label="Text"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-138.24998)"
style="display:inline">
<g
aria-label="ド"
inkscape:transform-center-x="-13.363477"
inkscape:transform-center-y="-6.6817387"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
id="text817">
<path
d="m 44.058316,209.35324 c -1.1684,-2.3368 -3.3528,-5.6896 -4.6736,-7.4168 l -2.6924,1.27 c 1.6764,2.2352 3.302,4.8768 4.572,7.5184 z m -6.1468,2.5908 c -1.1684,-2.3368 -3.302,-5.6896 -4.5212,-7.4676 l -2.794,1.2192 c 1.6256,2.2352 3.2004,4.9784 4.4704,7.5692 z m -17.9324,-4.3688 c 0,-1.524 0.2032,-3.6576 0.3556,-5.2324 h -4.8768 c 0.3048,1.5748 0.4064,3.81 0.4064,5.2324 v 29.0068 c 0,1.8796 -0.1016,4.3688 -0.3556,5.9436 h 4.826 c -0.2032,-1.6256 -0.3048,-4.318 -0.3048,-5.9436 l -0.0508,-16.4592 c 5.5372,1.778 14.224,5.1308 19.6088,8.0264 l 1.7272,-4.2164 c -5.2832,-2.5908 -14.732,-6.1976 -21.336,-8.2296 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:tb-rl;text-anchor:start;stroke-width:0.26458332"
id="path1994"
inkscape:connector-curvature="0" />
</g>
<g
aria-label="エ"
inkscape:transform-center-x="-13.363477"
inkscape:transform-center-y="-6.6817387"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:0.49803922;stroke:none;stroke-width:0.26458332"
id="text817-3">
<path
d="m 27.221545,285.85601 v -23.0124 h 11.9888 c 1.4224,0 2.9972,0.0508 4.2672,0.2032 v -4.318 c -1.2192,0.1016 -2.7432,0.254 -4.2672,0.254 H 11.778346 c -1.016,0 -2.8956004,-0.1016 -4.2164004,-0.254 v 4.318 c 1.27,-0.1524 3.2512004,-0.2032 4.2164004,-0.2032 h 11.226799 v 23.0124 H 8.9335456 c -1.3716,0 -2.9464,-0.1016 -4.4196,-0.3048 v 4.5212 c 1.5748,-0.1524 3.048,-0.2032 4.4196,-0.2032 H 41.902745 c 1.016,0 2.794,0.0508 4.1656,0.2032 v -4.5212 c -1.27,0.1524 -2.6416,0.3048 -4.1656,0.3048 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:0.49803922;stroke-width:0.26458332"
id="path1991"
inkscape:connector-curvature="0" />
</g>
<g
aria-label="ドエ"
inkscape:transform-center-x="-13.363477"
inkscape:transform-center-y="-6.6817387"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
id="text1900">
<path
d="m 148.03957,209.35324 c -1.1684,-2.3368 -3.3528,-5.6896 -4.6736,-7.4168 l -2.6924,1.27 c 1.6764,2.2352 3.302,4.8768 4.572,7.5184 z m -6.1468,2.5908 c -1.1684,-2.3368 -3.302,-5.6896 -4.5212,-7.4676 l -2.794,1.2192 c 1.6256,2.2352 3.2004,4.9784 4.4704,7.5692 z m -17.9324,-4.3688 c 0,-1.524 0.2032,-3.6576 0.3556,-5.2324 h -4.8768 c 0.3048,1.5748 0.4064,3.81 0.4064,5.2324 v 29.0068 c 0,1.8796 -0.1016,4.3688 -0.3556,5.9436 h 4.826 c -0.2032,-1.6256 -0.3048,-4.318 -0.3048,-5.9436 l -0.0508,-16.4592 c 5.5372,1.778 14.224,5.1308 19.6088,8.0264 l 1.7272,-4.2164 c -5.2832,-2.5908 -14.732,-6.1976 -21.336,-8.2296 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:tb-rl;text-anchor:start;stroke-width:0.26458332"
id="path1986"
inkscape:connector-curvature="0" />
<path
d="m 131.47877,284.94364 v -23.0124 h 11.9888 c 1.4224,0 2.9972,0.0508 4.2672,0.2032 v -4.318 c -1.2192,0.1016 -2.7432,0.254 -4.2672,0.254 h -27.432 c -1.016,0 -2.8956,-0.1016 -4.2164,-0.254 v 4.318 c 1.27,-0.1524 3.2512,-0.2032 4.2164,-0.2032 h 11.2268 v 23.0124 h -14.0716 c -1.3716,0 -2.9464,-0.1016 -4.4196,-0.3048 v 4.5212 c 1.5748,-0.1524 3.048,-0.2032 4.4196,-0.2032 h 32.9692 c 1.016,0 2.794,0.0508 4.1656,0.2032 v -4.5212 c -1.27,0.1524 -2.6416,0.3048 -4.1656,0.3048 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:tb-rl;text-anchor:start;stroke-width:0.26458332"
id="path1988"
inkscape:connector-curvature="0" />
</g>
<text
inkscape:transform-center-y="-6.6817387"
inkscape:transform-center-x="-13.363477"
id="text1904"
y="247.70522"
x="129.2724"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;line-height:1.25;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:0.49803922;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.79999924px;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:tb-rl;text-anchor:start;fill:#000000;fill-opacity:0.49803922;stroke-width:0.26458332"
y="97.5224"
x="247.70522"
id="tspan1902"
sodipodi:role="line" /></text>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="BBox"
style="display:inline">
<rect
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.79374999;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:13.40000153;stroke-opacity:1"
id="rect841"
width="28.765966"
height="51.387943"
x="15.703658"
y="57.810101" />
<rect
y="57.9813"
x="108.27481"
height="98.753151"
width="42.249935"
id="rect1906"
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.79374999;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:13.40000153;stroke-opacity:1" />
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="Middle Lines"
style="display:inline">
<path
style="fill:none;stroke:#ff0000;stroke-width:0.52916673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833346,0.52916673;stroke-dashoffset:0;stroke-opacity:1"
d="m 30.086628,113.02981 0,-88.716383"
id="path1589"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.52916673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833346,0.52916673;stroke-dashoffset:0;stroke-opacity:1"
d="m 8.7084112,83.504064 76.1496628,0"
id="path1572"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path1912"
d="m 129.39977,161.09646 0,-136.611091"
style="fill:none;stroke:#ff0000;stroke-width:0.52916673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833346,0.52916673;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path1914"
d="m 102.68548,107.35787 93.92308,0"
style="fill:none;stroke:#ff0000;stroke-width:0.52916673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.05833346,0.52916673;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#fe0000;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333000000001;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5151);marker-end:url(#marker5373)"
d="m 108.24863,53.950764 h 21.15114"
id="path2019"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715"
d="M 129.39977,53.950764 H 150.5509"
style="fill:none;stroke:#fe0000;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333000000001;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5141);marker-end:url(#marker5363)" />
<path
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333000000001;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 157.05475,57.987554 V 107.35257"
id="path2019-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715-4"
d="m 157.05475,107.35257 v 49.36498"
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333000000001;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5227);marker-end:url(#marker5539)" />
<path
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5151-4);marker-end:url(#marker5373-2)"
d="m 16.381854,53.710417 14.309817,0"
id="path2019-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
transform="translate(-0.67819643,-0.04677217)" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715-3"
d="m 30.691671,53.710417 14.456149,0"
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5141-2);marker-end:url(#marker5363-1)"
transform="translate(-0.67819643,-0.04677217)" />
<path
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Lstart-1);marker-end:url(#Arrow1Lend-8)"
d="m 52.197739,57.8101 0,25.693964"
id="path2019-6-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path2715-4-5"
d="m 52.197739,83.504064 0,25.693976"
style="display:inline;fill:none;stroke:#fe0000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26458333, 0.26458333;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker5227-1);marker-end:url(#marker5539-7)" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="BBox Lines"
style="display:inline">
<g
id="g867">
<path
inkscape:connector-curvature="0"
id="path846"
d="M 15.703658,57.8101 H 5.1026784"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path848"
d="M 15.703658,109.19804 H 5.2916666"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path850"
d="M 44.469624,109.19804 H 89.53529"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path852"
d="M 89.53529,57.8101 H 44.469624 m 0,0 V 20.43802"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cccc" />
<path
inkscape:connector-curvature="0"
id="path854"
d="M 15.703658,57.8101 V 19.90348"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path856"
d="m 15.703658,109.19804 v 7.0561"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path858"
d="m 44.469624,109.19804 v 7.32337"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g1930"
transform="translate(103.98125)">
<path
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="M 4.2935608,57.9813 H -6.3074188"
id="path1916"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="M 4.2935608,156.73445 H -6.1184306"
id="path1918"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="M 46.595826,156.71755 H 99.697401"
id="path1920"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cccc"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="M 99.697401,57.987554 H 46.595826 m 0,0 V 20.626208"
id="path1922"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cc"
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="M 4.2935608,57.9813 V 20.07468"
id="path1924"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="m 4.2935608,156.73445 v 7.0561"
id="path1926"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#ff0000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.175, 1.5875;stroke-dashoffset:0;stroke-opacity:1"
d="m 46.5435,156.73445 v 7.32337"
id="path1928"
inkscape:connector-curvature="0" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="Labels"
style="display:inline">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="13.66787"
y="27.68601"
id="text872"><tspan
sodipodi:role="line"
id="tspan870"
x="13.66787"
y="27.68601"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:end;stroke-width:0.26458332">(l)</tspan><tspan
sodipodi:role="line"
x="13.66787"
y="33.859623"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:end;stroke-width:0.26458332"
id="tspan874">left</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="27.238834"
y="10.481296"
id="text872-9"><tspan
sodipodi:role="line"
x="27.238834"
y="10.481296"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan874-6">(s) baseline</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="46.504551"
y="27.11688"
id="text872-8"><tspan
sodipodi:role="line"
id="tspan870-83"
x="46.504551"
y="27.11688"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332">(r)</tspan><tspan
sodipodi:role="line"
x="46.504551"
y="33.290493"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan874-62">right</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="58.22459"
y="54.28516"
id="text872-9-1"><tspan
sodipodi:role="line"
x="58.22459"
y="54.28516"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan1548">(t) top</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="58.22459"
y="81.352379"
id="text872-9-13"><tspan
sodipodi:role="line"
x="58.22459"
y="81.352379"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan1552">(m) middle</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="58.22459"
y="106.12718"
id="text872-9-4"><tspan
sodipodi:role="line"
x="58.22459"
y="106.12718"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan874-6-8">(b) bottom</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="30.637653"
y="27.403627"
id="text872-8-4"><tspan
sodipodi:role="line"
id="tspan870-83-6"
x="30.637653"
y="27.403627"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332">(m)</tspan><tspan
sodipodi:role="line"
x="30.637653"
y="31.813349"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
id="tspan874-62-8">middle</tspan></text>
<text
id="text1936"
y="28.347469"
x="110.24078"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="28.347469"
x="110.24078"
id="tspan1932"
sodipodi:role="line">(l)</tspan><tspan
id="tspan1934"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="34.52108"
x="110.24078"
sodipodi:role="line">left</tspan></text>
<text
id="text1940"
y="10.481296"
x="131.22009"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1938"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="10.481296"
x="131.22009"
sodipodi:role="line">(s) baseline</tspan></text>
<text
id="text1946"
y="28.239412"
x="152.16959"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="28.239412"
x="152.16959"
id="tspan1942"
sodipodi:role="line">(r)</tspan><tspan
id="tspan1944"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="34.413025"
x="152.16959"
sodipodi:role="line">right</tspan></text>
<text
id="text1950"
y="55.2981"
x="172.12772"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1948"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="55.2981"
x="172.12772"
sodipodi:role="line">(t) top</tspan></text>
<text
id="text1954"
y="104.37112"
x="172.12772"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1952"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="104.37112"
x="172.12772"
sodipodi:role="line">(m) middle</tspan></text>
<text
id="text1958"
y="153.57021"
x="172.12772"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan1956"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888903px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="153.57021"
x="172.12772"
sodipodi:role="line">(b) bottom</tspan></text>
<text
id="text1964"
y="29.388002"
x="130.51785"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="29.388002"
x="130.51785"
id="tspan1960"
sodipodi:role="line">(m)</tspan><tspan
id="tspan1962"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-orientation:sideways;text-anchor:start;stroke-width:0.26458332"
y="34.679668"
x="130.51785"
sodipodi:role="line">middle</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer7"
inkscape:label="Title"
style="display:inline">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="206.0321"
y="17.163603"
id="text4635"><tspan
sodipodi:role="line"
id="tspan4633"
x="206.0321"
y="17.163603"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.26458332">Vertical</tspan><tspan
sodipodi:role="line"
x="206.0321"
y="29.510824"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87777805px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:end;writing-mode:lr-tb;text-anchor:end;stroke-width:0.26458332"
id="tspan1984">text</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -320,6 +320,7 @@ class ImageDraw:
features=features, features=features,
language=language, language=language,
stroke_width=stroke_width, stroke_width=stroke_width,
anchor=anchor,
*args, *args,
**kwargs, **kwargs,
) )
@ -333,6 +334,7 @@ class ImageDraw:
features, features,
language, language,
stroke_width, stroke_width,
anchor,
*args, *args,
**kwargs, **kwargs,
) )
@ -353,7 +355,7 @@ class ImageDraw:
draw_text(stroke_ink, stroke_width) draw_text(stroke_ink, stroke_width)
# Draw normal text # Draw normal text
draw_text(ink, 0, (stroke_width, stroke_width)) draw_text(ink, 0)
else: else:
# Only draw normal text # Only draw normal text
draw_text(ink) draw_text(ink)
@ -373,6 +375,16 @@ class ImageDraw:
stroke_width=0, stroke_width=0,
stroke_fill=None, stroke_fill=None,
): ):
if direction == "ttb":
raise ValueError("ttb direction is unsupported for multiline text")
if anchor is None:
anchor = "la"
elif len(anchor) != 2:
raise ValueError("anchor must be a 2 character string")
elif anchor[1] in "tb":
raise ValueError("anchor not supported for multiline text")
widths = [] widths = []
max_width = 0 max_width = 0
lines = self._multiline_split(text) lines = self._multiline_split(text)
@ -390,16 +402,33 @@ class ImageDraw:
) )
widths.append(line_width) widths.append(line_width)
max_width = max(max_width, line_width) max_width = max(max_width, line_width)
left, top = xy
top = xy[1]
if anchor[1] == "m":
top -= (len(lines) - 1) * line_spacing / 2.0
elif anchor[1] == "d":
top -= (len(lines) - 1) * line_spacing
for idx, line in enumerate(lines): for idx, line in enumerate(lines):
left = xy[0]
width_difference = max_width - widths[idx]
# first align left by anchor
if anchor[0] == "m":
left -= width_difference / 2.0
elif anchor[0] == "r":
left -= width_difference
# then align by align parameter
if align == "left": if align == "left":
pass # left = x pass
elif align == "center": elif align == "center":
left += (max_width - widths[idx]) / 2.0 left += width_difference / 2.0
elif align == "right": elif align == "right":
left += max_width - widths[idx] left += width_difference
else: else:
raise ValueError('align must be "left", "center" or "right"') raise ValueError('align must be "left", "center" or "right"')
self.text( self.text(
(left, top), (left, top),
line, line,
@ -413,7 +442,6 @@ class ImageDraw:
stroke_fill=stroke_fill, stroke_fill=stroke_fill,
) )
top += line_spacing top += line_spacing
left = xy[0]
def textsize( def textsize(
self, self,

View File

@ -347,6 +347,7 @@ class FreeTypeFont:
features=None, features=None,
language=None, language=None,
stroke_width=0, stroke_width=0,
anchor=None,
): ):
""" """
Create a bitmap for the text. Create a bitmap for the text.
@ -395,6 +396,12 @@ class FreeTypeFont:
.. versionadded:: 6.2.0 .. versionadded:: 6.2.0
:param anchor: The text anchor alignment. Determines the relative location of
the anchor to the text. The default alignment is top left.
See :ref:`text-anchors` for valid values.
.. versionadded:: 8.0.0
:return: An internal PIL storage memory instance as defined by the :return: An internal PIL storage memory instance as defined by the
:py:mod:`PIL.Image.core` interface module. :py:mod:`PIL.Image.core` interface module.
""" """
@ -405,6 +412,7 @@ class FreeTypeFont:
features=features, features=features,
language=language, language=language,
stroke_width=stroke_width, stroke_width=stroke_width,
anchor=anchor,
)[0] )[0]
def getmask2( def getmask2(
@ -416,6 +424,7 @@ class FreeTypeFont:
features=None, features=None,
language=None, language=None,
stroke_width=0, stroke_width=0,
anchor=None,
*args, *args,
**kwargs, **kwargs,
): ):
@ -466,14 +475,21 @@ class FreeTypeFont:
.. versionadded:: 6.2.0 .. versionadded:: 6.2.0
:param anchor: The text anchor alignment. Determines the relative location of
the anchor to the text. The default alignment is top left.
See :ref:`text-anchors` for valid values.
.. versionadded:: 8.0.0
:return: A tuple of an internal PIL storage memory instance as defined by the :return: A tuple of an internal PIL storage memory instance as defined by the
:py:mod:`PIL.Image.core` interface module, and the text offset, the :py:mod:`PIL.Image.core` interface module, and the text offset, the
gap between the starting coordinate and the first marking gap between the starting coordinate and the first marking
""" """
size, offset = self.font.getsize( size, offset = self.font.getsize(
text, mode == "1", direction, features, language text, mode == "1", direction, features, language, anchor
) )
size = size[0] + stroke_width * 2, size[1] + stroke_width * 2 size = size[0] + stroke_width * 2, size[1] + stroke_width * 2
offset = offset[0] - stroke_width, offset[1] - stroke_width
im = fill("L", size, 0) im = fill("L", size, 0)
self.font.render( self.font.render(
text, im.id, mode == "1", direction, features, language, stroke_width text, im.id, mode == "1", direction, features, language, stroke_width

View File

@ -626,17 +626,25 @@ font_getsize(FontObject* self, PyObject* args)
int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */ int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
const char *dir = NULL; const char *dir = NULL;
const char *lang = NULL; const char *lang = NULL;
const char *anchor = NULL;
PyObject *features = Py_None; PyObject *features = Py_None;
PyObject *string; PyObject *string;
/* calculate size and bearing for a given string */ /* calculate size and bearing for a given string */
if (!PyArg_ParseTuple(args, "O|izOz:getsize", &string, &mask, &dir, &features, &lang)) { if (!PyArg_ParseTuple(args, "O|izOzz:getsize", &string, &mask, &dir, &features, &lang, &anchor)) {
return NULL; return NULL;
} }
horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1; horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
if (anchor == NULL) {
anchor = horizontal_dir ? "la" : "lt";
}
if (strlen(anchor) != 2) {
goto bad_anchor;
}
count = text_layout(string, self, dir, features, lang, &glyph_info, mask); count = text_layout(string, self, dir, features, lang, &glyph_info, mask);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
@ -720,11 +728,75 @@ font_getsize(FontObject* self, PyObject* args)
x_anchor = y_anchor = 0; x_anchor = y_anchor = 0;
if (face) { if (face) {
if (horizontal_dir) { if (horizontal_dir) {
switch (anchor[0]) {
case 'l': // left
x_anchor = 0; x_anchor = 0;
break;
case 'm': // middle (left + right) / 2
x_anchor = PIXEL(position / 2);
break;
case 'r': // right
x_anchor = PIXEL(position);
break;
case 's': // vertical baseline
default:
goto bad_anchor;
}
switch (anchor[1]) {
case 'a': // ascender
y_anchor = PIXEL(self->face->size->metrics.ascender); y_anchor = PIXEL(self->face->size->metrics.ascender);
} else { break;
x_anchor = x_min; case 't': // top
y_anchor = y_max;
break;
case 'm': // middle (ascender + descender) / 2
y_anchor = PIXEL((self->face->size->metrics.ascender + self->face->size->metrics.descender) / 2);
break;
case 's': // horizontal baseline
y_anchor = 0; y_anchor = 0;
break;
case 'b': // bottom
y_anchor = y_min;
break;
case 'd': // descender
y_anchor = PIXEL(self->face->size->metrics.descender);
break;
default:
goto bad_anchor;
}
} else {
switch (anchor[0]) {
case 'l': // left
x_anchor = x_min;
break;
case 'm': // middle (left + right) / 2
x_anchor = (x_min + x_max) / 2;
break;
case 'r': // right
x_anchor = x_max;
break;
case 's': // vertical baseline
x_anchor = 0;
break;
default:
goto bad_anchor;
}
switch (anchor[1]) {
case 't': // top
y_anchor = 0;
break;
case 'm': // middle (top + bottom) / 2
y_anchor = PIXEL(position / 2);
break;
case 'b': // bottom
y_anchor = PIXEL(position);
break;
case 'a': // ascender
case 's': // horizontal baseline
case 'd': // descender
default:
goto bad_anchor;
}
} }
} }
@ -733,6 +805,10 @@ font_getsize(FontObject* self, PyObject* args)
(x_max - x_min), (y_max - y_min), (x_max - x_min), (y_max - y_min),
(-x_anchor + x_min), -(-y_anchor + y_max) (-x_anchor + x_min), -(-y_anchor + y_max)
); );
bad_anchor:
PyErr_Format(PyExc_ValueError, "bad anchor specified: %s", anchor);
return NULL;
} }
static PyObject* static PyObject*