|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import base64 |
|
import os |
|
import sys |
|
import warnings |
|
from enum import IntEnum |
|
from io import BytesIO |
|
|
|
from . import Image |
|
from ._util import is_directory, is_path |
|
|
|
|
|
class Layout(IntEnum): |
|
BASIC = 0 |
|
RAQM = 1 |
|
|
|
|
|
MAX_STRING_LENGTH = 1_000_000 |
|
|
|
|
|
try: |
|
from . import _imagingft as core |
|
except ImportError as ex: |
|
from ._util import DeferredError |
|
|
|
core = DeferredError(ex) |
|
|
|
|
|
def _string_length_check(text): |
|
if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH: |
|
msg = "too many characters in string" |
|
raise ValueError(msg) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ImageFont: |
|
"""PIL font wrapper""" |
|
|
|
def _load_pilfont(self, filename): |
|
with open(filename, "rb") as fp: |
|
image = None |
|
for ext in (".png", ".gif", ".pbm"): |
|
if image: |
|
image.close() |
|
try: |
|
fullname = os.path.splitext(filename)[0] + ext |
|
image = Image.open(fullname) |
|
except Exception: |
|
pass |
|
else: |
|
if image and image.mode in ("1", "L"): |
|
break |
|
else: |
|
if image: |
|
image.close() |
|
msg = "cannot find glyph data file" |
|
raise OSError(msg) |
|
|
|
self.file = fullname |
|
|
|
self._load_pilfont_data(fp, image) |
|
image.close() |
|
|
|
def _load_pilfont_data(self, file, image): |
|
|
|
if file.readline() != b"PILfont\n": |
|
msg = "Not a PILfont file" |
|
raise SyntaxError(msg) |
|
file.readline().split(b";") |
|
self.info = [] |
|
while True: |
|
s = file.readline() |
|
if not s or s == b"DATA\n": |
|
break |
|
self.info.append(s) |
|
|
|
|
|
data = file.read(256 * 20) |
|
|
|
|
|
if image.mode not in ("1", "L"): |
|
msg = "invalid font image mode" |
|
raise TypeError(msg) |
|
|
|
image.load() |
|
|
|
self.font = Image.core.font(image.im, data) |
|
|
|
def getmask(self, text, mode="", *args, **kwargs): |
|
""" |
|
Create a bitmap for the text. |
|
|
|
If the font uses antialiasing, the bitmap should have mode ``L`` and use a |
|
maximum value of 255. Otherwise, it should have mode ``1``. |
|
|
|
:param text: Text to render. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
.. versionadded:: 1.1.5 |
|
|
|
:return: An internal PIL storage memory instance as defined by the |
|
:py:mod:`PIL.Image.core` interface module. |
|
""" |
|
return self.font.getmask(text, mode) |
|
|
|
def getbbox(self, text, *args, **kwargs): |
|
""" |
|
Returns bounding box (in pixels) of given text. |
|
|
|
.. versionadded:: 9.2.0 |
|
|
|
:param text: Text to render. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
:return: ``(left, top, right, bottom)`` bounding box |
|
""" |
|
_string_length_check(text) |
|
width, height = self.font.getsize(text) |
|
return 0, 0, width, height |
|
|
|
def getlength(self, text, *args, **kwargs): |
|
""" |
|
Returns length (in pixels) of given text. |
|
This is the amount by which following text should be offset. |
|
|
|
.. versionadded:: 9.2.0 |
|
""" |
|
_string_length_check(text) |
|
width, height = self.font.getsize(text) |
|
return width |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FreeTypeFont: |
|
"""FreeType font wrapper (requires _imagingft service)""" |
|
|
|
def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None): |
|
|
|
|
|
self.path = font |
|
self.size = size |
|
self.index = index |
|
self.encoding = encoding |
|
|
|
if layout_engine not in (Layout.BASIC, Layout.RAQM): |
|
layout_engine = Layout.BASIC |
|
if core.HAVE_RAQM: |
|
layout_engine = Layout.RAQM |
|
elif layout_engine == Layout.RAQM and not core.HAVE_RAQM: |
|
warnings.warn( |
|
"Raqm layout was requested, but Raqm is not available. " |
|
"Falling back to basic layout." |
|
) |
|
layout_engine = Layout.BASIC |
|
|
|
self.layout_engine = layout_engine |
|
|
|
def load_from_bytes(f): |
|
self.font_bytes = f.read() |
|
self.font = core.getfont( |
|
"", size, index, encoding, self.font_bytes, layout_engine |
|
) |
|
|
|
if is_path(font): |
|
if sys.platform == "win32": |
|
font_bytes_path = font if isinstance(font, bytes) else font.encode() |
|
try: |
|
font_bytes_path.decode("ascii") |
|
except UnicodeDecodeError: |
|
|
|
|
|
with open(font, "rb") as f: |
|
load_from_bytes(f) |
|
return |
|
self.font = core.getfont( |
|
font, size, index, encoding, layout_engine=layout_engine |
|
) |
|
else: |
|
load_from_bytes(font) |
|
|
|
def __getstate__(self): |
|
return [self.path, self.size, self.index, self.encoding, self.layout_engine] |
|
|
|
def __setstate__(self, state): |
|
path, size, index, encoding, layout_engine = state |
|
self.__init__(path, size, index, encoding, layout_engine) |
|
|
|
def getname(self): |
|
""" |
|
:return: A tuple of the font family (e.g. Helvetica) and the font style |
|
(e.g. Bold) |
|
""" |
|
return self.font.family, self.font.style |
|
|
|
def getmetrics(self): |
|
""" |
|
:return: A tuple of the font ascent (the distance from the baseline to |
|
the highest outline point) and descent (the distance from the |
|
baseline to the lowest outline point, a negative value) |
|
""" |
|
return self.font.ascent, self.font.descent |
|
|
|
def getlength(self, text, mode="", direction=None, features=None, language=None): |
|
""" |
|
Returns length (in pixels with 1/64 precision) of given text when rendered |
|
in font with provided direction, features, and language. |
|
|
|
This is the amount by which following text should be offset. |
|
Text bounding box may extend past the length in some fonts, |
|
e.g. when using italics or accents. |
|
|
|
The result is returned as a float; it is a whole number if using basic layout. |
|
|
|
Note that the sum of two lengths may not equal the length of a concatenated |
|
string due to kerning. If you need to adjust for kerning, include the following |
|
character and subtract its length. |
|
|
|
For example, instead of :: |
|
|
|
hello = font.getlength("Hello") |
|
world = font.getlength("World") |
|
hello_world = hello + world # not adjusted for kerning |
|
assert hello_world == font.getlength("HelloWorld") # may fail |
|
|
|
use :: |
|
|
|
hello = font.getlength("HelloW") - font.getlength("W") # adjusted for kerning |
|
world = font.getlength("World") |
|
hello_world = hello + world # adjusted for kerning |
|
assert hello_world == font.getlength("HelloWorld") # True |
|
|
|
or disable kerning with (requires libraqm) :: |
|
|
|
hello = draw.textlength("Hello", font, features=["-kern"]) |
|
world = draw.textlength("World", font, features=["-kern"]) |
|
hello_world = hello + world # kerning is disabled, no need to adjust |
|
assert hello_world == draw.textlength("HelloWorld", font, features=["-kern"]) |
|
|
|
.. versionadded:: 8.0.0 |
|
|
|
:param text: Text to measure. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
:param direction: Direction of the text. It can be 'rtl' (right to |
|
left), 'ltr' (left to right) or 'ttb' (top to bottom). |
|
Requires libraqm. |
|
|
|
:param features: A list of OpenType font features to be used during text |
|
layout. This is usually used to turn on optional |
|
font features that are not enabled by default, |
|
for example 'dlig' or 'ss01', but can be also |
|
used to turn off default font features for |
|
example '-liga' to disable ligatures or '-kern' |
|
to disable kerning. To get all supported |
|
features, see |
|
https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist |
|
Requires libraqm. |
|
|
|
:param language: Language of the text. Different languages may use |
|
different glyph shapes or ligatures. This parameter tells |
|
the font which language the text is in, and to apply the |
|
correct substitutions as appropriate, if available. |
|
It should be a `BCP 47 language code |
|
<https://www.w3.org/International/articles/language-tags/>`_ |
|
Requires libraqm. |
|
|
|
:return: Width for horizontal, height for vertical text. |
|
""" |
|
_string_length_check(text) |
|
return self.font.getlength(text, mode, direction, features, language) / 64 |
|
|
|
def getbbox( |
|
self, |
|
text, |
|
mode="", |
|
direction=None, |
|
features=None, |
|
language=None, |
|
stroke_width=0, |
|
anchor=None, |
|
): |
|
""" |
|
Returns bounding box (in pixels) of given text relative to given anchor |
|
when rendered in font with provided direction, features, and language. |
|
|
|
Use :py:meth:`getlength()` to get the offset of following text with |
|
1/64 pixel precision. The bounding box includes extra margins for |
|
some fonts, e.g. italics or accents. |
|
|
|
.. versionadded:: 8.0.0 |
|
|
|
:param text: Text to render. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
:param direction: Direction of the text. It can be 'rtl' (right to |
|
left), 'ltr' (left to right) or 'ttb' (top to bottom). |
|
Requires libraqm. |
|
|
|
:param features: A list of OpenType font features to be used during text |
|
layout. This is usually used to turn on optional |
|
font features that are not enabled by default, |
|
for example 'dlig' or 'ss01', but can be also |
|
used to turn off default font features for |
|
example '-liga' to disable ligatures or '-kern' |
|
to disable kerning. To get all supported |
|
features, see |
|
https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist |
|
Requires libraqm. |
|
|
|
:param language: Language of the text. Different languages may use |
|
different glyph shapes or ligatures. This parameter tells |
|
the font which language the text is in, and to apply the |
|
correct substitutions as appropriate, if available. |
|
It should be a `BCP 47 language code |
|
<https://www.w3.org/International/articles/language-tags/>`_ |
|
Requires libraqm. |
|
|
|
:param stroke_width: The width of the text stroke. |
|
|
|
: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. |
|
|
|
:return: ``(left, top, right, bottom)`` bounding box |
|
""" |
|
_string_length_check(text) |
|
size, offset = self.font.getsize( |
|
text, mode, direction, features, language, anchor |
|
) |
|
left, top = offset[0] - stroke_width, offset[1] - stroke_width |
|
width, height = size[0] + 2 * stroke_width, size[1] + 2 * stroke_width |
|
return left, top, left + width, top + height |
|
|
|
def getmask( |
|
self, |
|
text, |
|
mode="", |
|
direction=None, |
|
features=None, |
|
language=None, |
|
stroke_width=0, |
|
anchor=None, |
|
ink=0, |
|
start=None, |
|
): |
|
""" |
|
Create a bitmap for the text. |
|
|
|
If the font uses antialiasing, the bitmap should have mode ``L`` and use a |
|
maximum value of 255. If the font has embedded color data, the bitmap |
|
should have mode ``RGBA``. Otherwise, it should have mode ``1``. |
|
|
|
:param text: Text to render. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
.. versionadded:: 1.1.5 |
|
|
|
:param direction: Direction of the text. It can be 'rtl' (right to |
|
left), 'ltr' (left to right) or 'ttb' (top to bottom). |
|
Requires libraqm. |
|
|
|
.. versionadded:: 4.2.0 |
|
|
|
:param features: A list of OpenType font features to be used during text |
|
layout. This is usually used to turn on optional |
|
font features that are not enabled by default, |
|
for example 'dlig' or 'ss01', but can be also |
|
used to turn off default font features for |
|
example '-liga' to disable ligatures or '-kern' |
|
to disable kerning. To get all supported |
|
features, see |
|
https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist |
|
Requires libraqm. |
|
|
|
.. versionadded:: 4.2.0 |
|
|
|
:param language: Language of the text. Different languages may use |
|
different glyph shapes or ligatures. This parameter tells |
|
the font which language the text is in, and to apply the |
|
correct substitutions as appropriate, if available. |
|
It should be a `BCP 47 language code |
|
<https://www.w3.org/International/articles/language-tags/>`_ |
|
Requires libraqm. |
|
|
|
.. versionadded:: 6.0.0 |
|
|
|
:param stroke_width: The width of the text stroke. |
|
|
|
.. 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 |
|
|
|
:param ink: Foreground ink for rendering in RGBA mode. |
|
|
|
.. versionadded:: 8.0.0 |
|
|
|
:param start: Tuple of horizontal and vertical offset, as text may render |
|
differently when starting at fractional coordinates. |
|
|
|
.. versionadded:: 9.4.0 |
|
|
|
:return: An internal PIL storage memory instance as defined by the |
|
:py:mod:`PIL.Image.core` interface module. |
|
""" |
|
return self.getmask2( |
|
text, |
|
mode, |
|
direction=direction, |
|
features=features, |
|
language=language, |
|
stroke_width=stroke_width, |
|
anchor=anchor, |
|
ink=ink, |
|
start=start, |
|
)[0] |
|
|
|
def getmask2( |
|
self, |
|
text, |
|
mode="", |
|
direction=None, |
|
features=None, |
|
language=None, |
|
stroke_width=0, |
|
anchor=None, |
|
ink=0, |
|
start=None, |
|
*args, |
|
**kwargs, |
|
): |
|
""" |
|
Create a bitmap for the text. |
|
|
|
If the font uses antialiasing, the bitmap should have mode ``L`` and use a |
|
maximum value of 255. If the font has embedded color data, the bitmap |
|
should have mode ``RGBA``. Otherwise, it should have mode ``1``. |
|
|
|
:param text: Text to render. |
|
:param mode: Used by some graphics drivers to indicate what mode the |
|
driver prefers; if empty, the renderer may return either |
|
mode. Note that the mode is always a string, to simplify |
|
C-level implementations. |
|
|
|
.. versionadded:: 1.1.5 |
|
|
|
:param direction: Direction of the text. It can be 'rtl' (right to |
|
left), 'ltr' (left to right) or 'ttb' (top to bottom). |
|
Requires libraqm. |
|
|
|
.. versionadded:: 4.2.0 |
|
|
|
:param features: A list of OpenType font features to be used during text |
|
layout. This is usually used to turn on optional |
|
font features that are not enabled by default, |
|
for example 'dlig' or 'ss01', but can be also |
|
used to turn off default font features for |
|
example '-liga' to disable ligatures or '-kern' |
|
to disable kerning. To get all supported |
|
features, see |
|
https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist |
|
Requires libraqm. |
|
|
|
.. versionadded:: 4.2.0 |
|
|
|
:param language: Language of the text. Different languages may use |
|
different glyph shapes or ligatures. This parameter tells |
|
the font which language the text is in, and to apply the |
|
correct substitutions as appropriate, if available. |
|
It should be a `BCP 47 language code |
|
<https://www.w3.org/International/articles/language-tags/>`_ |
|
Requires libraqm. |
|
|
|
.. versionadded:: 6.0.0 |
|
|
|
:param stroke_width: The width of the text stroke. |
|
|
|
.. 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 |
|
|
|
:param ink: Foreground ink for rendering in RGBA mode. |
|
|
|
.. versionadded:: 8.0.0 |
|
|
|
:param start: Tuple of horizontal and vertical offset, as text may render |
|
differently when starting at fractional coordinates. |
|
|
|
.. versionadded:: 9.4.0 |
|
|
|
: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 |
|
gap between the starting coordinate and the first marking |
|
""" |
|
_string_length_check(text) |
|
if start is None: |
|
start = (0, 0) |
|
im = None |
|
|
|
def fill(mode, size): |
|
nonlocal im |
|
|
|
im = Image.core.fill(mode, size) |
|
return im |
|
|
|
size, offset = self.font.render( |
|
text, |
|
fill, |
|
mode, |
|
direction, |
|
features, |
|
language, |
|
stroke_width, |
|
anchor, |
|
ink, |
|
start[0], |
|
start[1], |
|
Image.MAX_IMAGE_PIXELS, |
|
) |
|
Image._decompression_bomb_check(size) |
|
return im, offset |
|
|
|
def font_variant( |
|
self, font=None, size=None, index=None, encoding=None, layout_engine=None |
|
): |
|
""" |
|
Create a copy of this FreeTypeFont object, |
|
using any specified arguments to override the settings. |
|
|
|
Parameters are identical to the parameters used to initialize this |
|
object. |
|
|
|
:return: A FreeTypeFont object. |
|
""" |
|
if font is None: |
|
try: |
|
font = BytesIO(self.font_bytes) |
|
except AttributeError: |
|
font = self.path |
|
return FreeTypeFont( |
|
font=font, |
|
size=self.size if size is None else size, |
|
index=self.index if index is None else index, |
|
encoding=self.encoding if encoding is None else encoding, |
|
layout_engine=layout_engine or self.layout_engine, |
|
) |
|
|
|
def get_variation_names(self): |
|
""" |
|
:returns: A list of the named styles in a variation font. |
|
:exception OSError: If the font is not a variation font. |
|
""" |
|
try: |
|
names = self.font.getvarnames() |
|
except AttributeError as e: |
|
msg = "FreeType 2.9.1 or greater is required" |
|
raise NotImplementedError(msg) from e |
|
return [name.replace(b"\x00", b"") for name in names] |
|
|
|
def set_variation_by_name(self, name): |
|
""" |
|
:param name: The name of the style. |
|
:exception OSError: If the font is not a variation font. |
|
""" |
|
names = self.get_variation_names() |
|
if not isinstance(name, bytes): |
|
name = name.encode() |
|
index = names.index(name) + 1 |
|
|
|
if index == getattr(self, "_last_variation_index", None): |
|
|
|
|
|
|
|
return |
|
self._last_variation_index = index |
|
|
|
self.font.setvarname(index) |
|
|
|
def get_variation_axes(self): |
|
""" |
|
:returns: A list of the axes in a variation font. |
|
:exception OSError: If the font is not a variation font. |
|
""" |
|
try: |
|
axes = self.font.getvaraxes() |
|
except AttributeError as e: |
|
msg = "FreeType 2.9.1 or greater is required" |
|
raise NotImplementedError(msg) from e |
|
for axis in axes: |
|
axis["name"] = axis["name"].replace(b"\x00", b"") |
|
return axes |
|
|
|
def set_variation_by_axes(self, axes): |
|
""" |
|
:param axes: A list of values for each axis. |
|
:exception OSError: If the font is not a variation font. |
|
""" |
|
try: |
|
self.font.setvaraxes(axes) |
|
except AttributeError as e: |
|
msg = "FreeType 2.9.1 or greater is required" |
|
raise NotImplementedError(msg) from e |
|
|
|
|
|
class TransposedFont: |
|
"""Wrapper for writing rotated or mirrored text""" |
|
|
|
def __init__(self, font, orientation=None): |
|
""" |
|
Wrapper that creates a transposed font from any existing font |
|
object. |
|
|
|
:param font: A font object. |
|
:param orientation: An optional orientation. If given, this should |
|
be one of Image.Transpose.FLIP_LEFT_RIGHT, Image.Transpose.FLIP_TOP_BOTTOM, |
|
Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_180, or |
|
Image.Transpose.ROTATE_270. |
|
""" |
|
self.font = font |
|
self.orientation = orientation |
|
|
|
def getmask(self, text, mode="", *args, **kwargs): |
|
im = self.font.getmask(text, mode, *args, **kwargs) |
|
if self.orientation is not None: |
|
return im.transpose(self.orientation) |
|
return im |
|
|
|
def getbbox(self, text, *args, **kwargs): |
|
|
|
|
|
left, top, right, bottom = self.font.getbbox(text, *args, **kwargs) |
|
width = right - left |
|
height = bottom - top |
|
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): |
|
return 0, 0, height, width |
|
return 0, 0, width, height |
|
|
|
def getlength(self, text, *args, **kwargs): |
|
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): |
|
msg = "text length is undefined for text rotated by 90 or 270 degrees" |
|
raise ValueError(msg) |
|
_string_length_check(text) |
|
return self.font.getlength(text, *args, **kwargs) |
|
|
|
|
|
def load(filename): |
|
""" |
|
Load a font file. This function loads a font object from the given |
|
bitmap font file, and returns the corresponding font object. |
|
|
|
:param filename: Name of font file. |
|
:return: A font object. |
|
:exception OSError: If the file could not be read. |
|
""" |
|
f = ImageFont() |
|
f._load_pilfont(filename) |
|
return f |
|
|
|
|
|
def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): |
|
""" |
|
Load a TrueType or OpenType font from a file or file-like object, |
|
and create a font object. |
|
This function loads a font object from the given file or file-like |
|
object, and creates a font object for a font of the given size. |
|
|
|
Pillow uses FreeType to open font files. On Windows, be aware that FreeType |
|
will keep the file open as long as the FreeTypeFont object exists. Windows |
|
limits the number of files that can be open in C at once to 512, so if many |
|
fonts are opened simultaneously and that limit is approached, an |
|
``OSError`` may be thrown, reporting that FreeType "cannot open resource". |
|
A workaround would be to copy the file(s) into memory, and open that instead. |
|
|
|
This function requires the _imagingft service. |
|
|
|
:param font: A filename or file-like object containing a TrueType font. |
|
If the file is not found in this filename, the loader may also |
|
search in other directories, such as the :file:`fonts/` |
|
directory on Windows or :file:`/Library/Fonts/`, |
|
:file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on |
|
macOS. |
|
|
|
:param size: The requested size, in pixels. |
|
:param index: Which font face to load (default is first available face). |
|
:param encoding: Which font encoding to use (default is Unicode). Possible |
|
encodings include (see the FreeType documentation for more |
|
information): |
|
|
|
* "unic" (Unicode) |
|
* "symb" (Microsoft Symbol) |
|
* "ADOB" (Adobe Standard) |
|
* "ADBE" (Adobe Expert) |
|
* "ADBC" (Adobe Custom) |
|
* "armn" (Apple Roman) |
|
* "sjis" (Shift JIS) |
|
* "gb " (PRC) |
|
* "big5" |
|
* "wans" (Extended Wansung) |
|
* "joha" (Johab) |
|
* "lat1" (Latin-1) |
|
|
|
This specifies the character set to use. It does not alter the |
|
encoding of any text provided in subsequent operations. |
|
:param layout_engine: Which layout engine to use, if available: |
|
:data:`.ImageFont.Layout.BASIC` or :data:`.ImageFont.Layout.RAQM`. |
|
If it is available, Raqm layout will be used by default. |
|
Otherwise, basic layout will be used. |
|
|
|
Raqm layout is recommended for all non-English text. If Raqm layout |
|
is not required, basic layout will have better performance. |
|
|
|
You can check support for Raqm layout using |
|
:py:func:`PIL.features.check_feature` with ``feature="raqm"``. |
|
|
|
.. versionadded:: 4.2.0 |
|
:return: A font object. |
|
:exception OSError: If the file could not be read. |
|
""" |
|
|
|
def freetype(font): |
|
return FreeTypeFont(font, size, index, encoding, layout_engine) |
|
|
|
try: |
|
return freetype(font) |
|
except OSError: |
|
if not is_path(font): |
|
raise |
|
ttf_filename = os.path.basename(font) |
|
|
|
dirs = [] |
|
if sys.platform == "win32": |
|
|
|
|
|
|
|
windir = os.environ.get("WINDIR") |
|
if windir: |
|
dirs.append(os.path.join(windir, "fonts")) |
|
elif sys.platform in ("linux", "linux2"): |
|
lindirs = os.environ.get("XDG_DATA_DIRS") |
|
if not lindirs: |
|
|
|
|
|
lindirs = "/usr/share" |
|
dirs += [os.path.join(lindir, "fonts") for lindir in lindirs.split(":")] |
|
elif sys.platform == "darwin": |
|
dirs += [ |
|
"/Library/Fonts", |
|
"/System/Library/Fonts", |
|
os.path.expanduser("~/Library/Fonts"), |
|
] |
|
|
|
ext = os.path.splitext(ttf_filename)[1] |
|
first_font_with_a_different_extension = None |
|
for directory in dirs: |
|
for walkroot, walkdir, walkfilenames in os.walk(directory): |
|
for walkfilename in walkfilenames: |
|
if ext and walkfilename == ttf_filename: |
|
return freetype(os.path.join(walkroot, walkfilename)) |
|
elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename: |
|
fontpath = os.path.join(walkroot, walkfilename) |
|
if os.path.splitext(fontpath)[1] == ".ttf": |
|
return freetype(fontpath) |
|
if not ext and first_font_with_a_different_extension is None: |
|
first_font_with_a_different_extension = fontpath |
|
if first_font_with_a_different_extension: |
|
return freetype(first_font_with_a_different_extension) |
|
raise |
|
|
|
|
|
def load_path(filename): |
|
""" |
|
Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a |
|
bitmap font along the Python path. |
|
|
|
:param filename: Name of font file. |
|
:return: A font object. |
|
:exception OSError: If the file could not be read. |
|
""" |
|
for directory in sys.path: |
|
if is_directory(directory): |
|
if not isinstance(filename, str): |
|
filename = filename.decode("utf-8") |
|
try: |
|
return load(os.path.join(directory, filename)) |
|
except OSError: |
|
pass |
|
msg = "cannot find font file" |
|
raise OSError(msg) |
|
|
|
|
|
def load_default(): |
|
"""Load a "better than nothing" default font. |
|
|
|
.. versionadded:: 1.1.4 |
|
|
|
:return: A font object. |
|
""" |
|
f = ImageFont() |
|
f._load_pilfont_data( |
|
|
|
BytesIO( |
|
base64.b64decode( |
|
b""" |
|
UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA |
|
BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL |
|
AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA |
|
AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB |
|
ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A |
|
BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB |
|
//kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA |
|
AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH |
|
AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA |
|
ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv |
|
AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/ |
|
/gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5 |
|
AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA |
|
AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG |
|
AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA |
|
BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA |
|
AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA |
|
2AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF |
|
AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA//// |
|
+gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA |
|
////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA |
|
BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv |
|
AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA |
|
AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA |
|
AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA |
|
BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP// |
|
//kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA |
|
AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF |
|
AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB |
|
mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn |
|
AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA |
|
AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7 |
|
AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA |
|
Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB |
|
//sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA |
|
AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ |
|
AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC |
|
DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ |
|
AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/ |
|
+wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5 |
|
AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/ |
|
///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG |
|
AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA |
|
BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA |
|
Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC |
|
eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG |
|
AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA//// |
|
+gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA |
|
////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA |
|
BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT |
|
AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A |
|
AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA |
|
Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA |
|
Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP// |
|
//cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA |
|
AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ |
|
AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA |
|
LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5 |
|
AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA |
|
AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5 |
|
AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA |
|
AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG |
|
AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA |
|
EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK |
|
AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA |
|
pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG |
|
AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA//// |
|
+QAGAAIAzgAKANUAEw== |
|
""" |
|
) |
|
), |
|
Image.open( |
|
BytesIO( |
|
base64.b64decode( |
|
b""" |
|
iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u |
|
Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9 |
|
M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g |
|
LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F |
|
IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA |
|
Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791 |
|
NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx |
|
in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9 |
|
SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY |
|
AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt |
|
y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG |
|
ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY |
|
lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H |
|
/Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3 |
|
AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47 |
|
c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/ |
|
/yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw |
|
pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv |
|
oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR |
|
evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA |
|
AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v// |
|
Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR |
|
w7IkEbzhVQAAAABJRU5ErkJggg== |
|
""" |
|
) |
|
) |
|
), |
|
) |
|
return f |
|
|