diff --git a/docs/example/anchors.png b/docs/example/anchors.png new file mode 100644 index 000000000..37b4d8219 Binary files /dev/null and b/docs/example/anchors.png differ diff --git a/docs/example/anchors.py b/docs/example/anchors.py new file mode 100644 index 000000000..72361cefc --- /dev/null +++ b/docs/example/anchors.py @@ -0,0 +1,29 @@ +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), "Sample", "black", font, anchor) + d.text((10, 100), "anchor=%s" % anchor, "gray", font, "ld") + 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() diff --git a/docs/handbook/appendices.rst b/docs/handbook/appendices.rst index e6c415cc6..6afaef071 100644 --- a/docs/handbook/appendices.rst +++ b/docs/handbook/appendices.rst @@ -7,4 +7,5 @@ Appendices :maxdepth: 2 image-file-formats + text-anchors writing-your-own-file-decoder diff --git a/docs/handbook/text-anchors.rst b/docs/handbook/text-anchors.rst new file mode 100644 index 000000000..e62210edd --- /dev/null +++ b/docs/handbook/text-anchors.rst @@ -0,0 +1,140 @@ + +.. _text-anchors: + +Text anchors +============ + +The ``anchor`` parameter determines 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.Draw.text` with a specific anchor, +text will be placed such that the specified anchor point is at the ``xy`` coordinates. + +For example, in the following image, text is ``ms`` (middle--baseline) aligned, with ``xy`` at +the intersection of the two lines: + +.. image:: ../../Tests/images/test_anchor_quick_ms.png + :alt: 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 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 diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index b6c64ac97..9fca33a01 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -70,64 +70,10 @@ contains font metrics, the latter raster data. To load a bitmap font, use the load functions in the :py:mod:`~PIL.ImageFont` module. -To load a OpenType/TrueType font, use the truetype function in the +To load a OpenType/TrueType font, use the ``truetype`` function in the :py:mod:`~PIL.ImageFont` module. Note that this function depends on third-party libraries, and may not available in all PIL builds. -Text anchors -^^^^^^^^^^^^ - -The ``anchor`` parameter determines the position of the ``xy`` coordinates relative to the text. -It consists of two characters, the horizontal and vertical alignment. - -The default value is ``la`` for horizontal text and ``lt`` for vertical text. - -This parameter is ignored for legacy PIL fonts, where the anchor is always top-left. - -+---+-----------------------+-------------------------------------------------------+ -| Horizontal anchor alignment | -+===+=======================+=======================================================+ -| l | left | Anchor is to the left of the text. | -+---+-----------------------+-------------------------------------------------------+ -| m | middle | Anchor is horizontally centered with the text. | -+---+-----------------------+-------------------------------------------------------+ -| r | right | Anchor is to the right of the text. | -+---+-----------------------+-------------------------------------------------------+ -| s | baseline | **(vertical text only)** | -| | | Anchor is at the baseline (middle) of the text. | -| | | The exact alignment depends on the font. | -+---+-----------------------+-------------------------------------------------------+ - -+---+-----------------------+-------------------------------------------------------+ -| Vertical anchor alignment | -+===+=======================+=======================================================+ -| a | ascender (top) | **(horizontal text only)** | -| | | Anchor is at the ascender line (top) | -| | | of the first line of text. | -+---+-----------------------+-------------------------------------------------------+ -| t | top | **(single-line text only)** | -| | | Anchor is at the top of the 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. | -+---+-----------------------+-------------------------------------------------------+ -| b | bottom | **(single-line text only)** | -| | | Anchor is at the bottom of the text. | -+---+-----------------------+-------------------------------------------------------+ -| d | descender (bottom) | **(horizontal text only)** | -| | | Anchor is at the descender line (bottom) | -| | | of the last line of text. | -+---+-----------------------+-------------------------------------------------------+ - -See `Font metrics on Wikipedia `_ -for more information on the specific terms used. - Example: Draw Partial Opacity Text ---------------------------------- @@ -340,8 +286,8 @@ Methods :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 legacy PIL fonts. + 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 7.2.0. @@ -400,8 +346,8 @@ Methods :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 legacy PIL fonts. + 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 7.2.0. diff --git a/docs/resources/anchor_horizontal.svg b/docs/resources/anchor_horizontal.svg new file mode 100644 index 000000000..a0648a10c --- /dev/null +++ b/docs/resources/anchor_horizontal.svg @@ -0,0 +1,467 @@ + + + + + Pillow horizontal text anchors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Pillow horizontal text anchors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (d) descender + (s) baseline + (a) ascender + (m) middle + (t) top + (b) bottom + (l) left + (r) right + (m) middle + + + Horizontal text + + diff --git a/docs/resources/anchor_vertical.svg b/docs/resources/anchor_vertical.svg new file mode 100644 index 000000000..95da30ffd --- /dev/null +++ b/docs/resources/anchor_vertical.svg @@ -0,0 +1,841 @@ + + + + + Pillow vertical text anchors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Pillow vertical text anchors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (l)left + (s) baseline + (r)right + (t) top + (m) middle + (b) bottom + (m)middle + (l)left + (s) baseline + (r)right + (t) top + (m) middle + (b) bottom + (m)middle + + + Verticaltext + + diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index c9278d0ac..5612270d4 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -396,7 +396,7 @@ class FreeTypeFont: :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. + See :ref:`text-anchors` for valid values. .. versionadded:: 7.2.0 @@ -475,7 +475,7 @@ class FreeTypeFont: :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. + See :ref:`text-anchors` for valid values. .. versionadded:: 7.2.0