Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ImageFont.py 49KB

1 year ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # PIL raster font management
  6. #
  7. # History:
  8. # 1996-08-07 fl created (experimental)
  9. # 1997-08-25 fl minor adjustments to handle fonts from pilfont 0.3
  10. # 1999-02-06 fl rewrote most font management stuff in C
  11. # 1999-03-17 fl take pth files into account in load_path (from Richard Jones)
  12. # 2001-02-17 fl added freetype support
  13. # 2001-05-09 fl added TransposedFont wrapper class
  14. # 2002-03-04 fl make sure we have a "L" or "1" font
  15. # 2002-12-04 fl skip non-directory entries in the system path
  16. # 2003-04-29 fl add embedded default font
  17. # 2003-09-27 fl added support for truetype charmap encodings
  18. #
  19. # Todo:
  20. # Adapt to PILFONT2 format (16-bit fonts, compressed, single file)
  21. #
  22. # Copyright (c) 1997-2003 by Secret Labs AB
  23. # Copyright (c) 1996-2003 by Fredrik Lundh
  24. #
  25. # See the README file for information on usage and redistribution.
  26. #
  27. import base64
  28. import math
  29. import os
  30. import sys
  31. import warnings
  32. from enum import IntEnum
  33. from io import BytesIO
  34. from . import Image
  35. from ._deprecate import deprecate
  36. from ._util import is_directory, is_path
  37. class Layout(IntEnum):
  38. BASIC = 0
  39. RAQM = 1
  40. def __getattr__(name):
  41. for enum, prefix in {Layout: "LAYOUT_"}.items():
  42. if name.startswith(prefix):
  43. name = name[len(prefix) :]
  44. if name in enum.__members__:
  45. deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
  46. return enum[name]
  47. msg = f"module '{__name__}' has no attribute '{name}'"
  48. raise AttributeError(msg)
  49. try:
  50. from . import _imagingft as core
  51. except ImportError as ex:
  52. from ._util import DeferredError
  53. core = DeferredError(ex)
  54. _UNSPECIFIED = object()
  55. # FIXME: add support for pilfont2 format (see FontFile.py)
  56. # --------------------------------------------------------------------
  57. # Font metrics format:
  58. # "PILfont" LF
  59. # fontdescriptor LF
  60. # (optional) key=value... LF
  61. # "DATA" LF
  62. # binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox)
  63. #
  64. # To place a character, cut out srcbox and paste at dstbox,
  65. # relative to the character position. Then move the character
  66. # position according to dx, dy.
  67. # --------------------------------------------------------------------
  68. class ImageFont:
  69. """PIL font wrapper"""
  70. def _load_pilfont(self, filename):
  71. with open(filename, "rb") as fp:
  72. image = None
  73. for ext in (".png", ".gif", ".pbm"):
  74. if image:
  75. image.close()
  76. try:
  77. fullname = os.path.splitext(filename)[0] + ext
  78. image = Image.open(fullname)
  79. except Exception:
  80. pass
  81. else:
  82. if image and image.mode in ("1", "L"):
  83. break
  84. else:
  85. if image:
  86. image.close()
  87. msg = "cannot find glyph data file"
  88. raise OSError(msg)
  89. self.file = fullname
  90. self._load_pilfont_data(fp, image)
  91. image.close()
  92. def _load_pilfont_data(self, file, image):
  93. # read PILfont header
  94. if file.readline() != b"PILfont\n":
  95. msg = "Not a PILfont file"
  96. raise SyntaxError(msg)
  97. file.readline().split(b";")
  98. self.info = [] # FIXME: should be a dictionary
  99. while True:
  100. s = file.readline()
  101. if not s or s == b"DATA\n":
  102. break
  103. self.info.append(s)
  104. # read PILfont metrics
  105. data = file.read(256 * 20)
  106. # check image
  107. if image.mode not in ("1", "L"):
  108. msg = "invalid font image mode"
  109. raise TypeError(msg)
  110. image.load()
  111. self.font = Image.core.font(image.im, data)
  112. def getsize(self, text, *args, **kwargs):
  113. """
  114. .. deprecated:: 9.2.0
  115. Use :py:meth:`.getbbox` or :py:meth:`.getlength` instead.
  116. See :ref:`deprecations <Font size and offset methods>` for more information.
  117. Returns width and height (in pixels) of given text.
  118. :param text: Text to measure.
  119. :return: (width, height)
  120. """
  121. deprecate("getsize", 10, "getbbox or getlength")
  122. return self.font.getsize(text)
  123. def getmask(self, text, mode="", *args, **kwargs):
  124. """
  125. Create a bitmap for the text.
  126. If the font uses antialiasing, the bitmap should have mode ``L`` and use a
  127. maximum value of 255. Otherwise, it should have mode ``1``.
  128. :param text: Text to render.
  129. :param mode: Used by some graphics drivers to indicate what mode the
  130. driver prefers; if empty, the renderer may return either
  131. mode. Note that the mode is always a string, to simplify
  132. C-level implementations.
  133. .. versionadded:: 1.1.5
  134. :return: An internal PIL storage memory instance as defined by the
  135. :py:mod:`PIL.Image.core` interface module.
  136. """
  137. return self.font.getmask(text, mode)
  138. def getbbox(self, text, *args, **kwargs):
  139. """
  140. Returns bounding box (in pixels) of given text.
  141. .. versionadded:: 9.2.0
  142. :param text: Text to render.
  143. :param mode: Used by some graphics drivers to indicate what mode the
  144. driver prefers; if empty, the renderer may return either
  145. mode. Note that the mode is always a string, to simplify
  146. C-level implementations.
  147. :return: ``(left, top, right, bottom)`` bounding box
  148. """
  149. width, height = self.font.getsize(text)
  150. return 0, 0, width, height
  151. def getlength(self, text, *args, **kwargs):
  152. """
  153. Returns length (in pixels) of given text.
  154. This is the amount by which following text should be offset.
  155. .. versionadded:: 9.2.0
  156. """
  157. width, height = self.font.getsize(text)
  158. return width
  159. ##
  160. # Wrapper for FreeType fonts. Application code should use the
  161. # <b>truetype</b> factory function to create font objects.
  162. class FreeTypeFont:
  163. """FreeType font wrapper (requires _imagingft service)"""
  164. def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None):
  165. # FIXME: use service provider instead
  166. self.path = font
  167. self.size = size
  168. self.index = index
  169. self.encoding = encoding
  170. if layout_engine not in (Layout.BASIC, Layout.RAQM):
  171. layout_engine = Layout.BASIC
  172. if core.HAVE_RAQM:
  173. layout_engine = Layout.RAQM
  174. elif layout_engine == Layout.RAQM and not core.HAVE_RAQM:
  175. warnings.warn(
  176. "Raqm layout was requested, but Raqm is not available. "
  177. "Falling back to basic layout."
  178. )
  179. layout_engine = Layout.BASIC
  180. self.layout_engine = layout_engine
  181. def load_from_bytes(f):
  182. self.font_bytes = f.read()
  183. self.font = core.getfont(
  184. "", size, index, encoding, self.font_bytes, layout_engine
  185. )
  186. if is_path(font):
  187. if sys.platform == "win32":
  188. font_bytes_path = font if isinstance(font, bytes) else font.encode()
  189. try:
  190. font_bytes_path.decode("ascii")
  191. except UnicodeDecodeError:
  192. # FreeType cannot load fonts with non-ASCII characters on Windows
  193. # So load it into memory first
  194. with open(font, "rb") as f:
  195. load_from_bytes(f)
  196. return
  197. self.font = core.getfont(
  198. font, size, index, encoding, layout_engine=layout_engine
  199. )
  200. else:
  201. load_from_bytes(font)
  202. def __getstate__(self):
  203. return [self.path, self.size, self.index, self.encoding, self.layout_engine]
  204. def __setstate__(self, state):
  205. path, size, index, encoding, layout_engine = state
  206. self.__init__(path, size, index, encoding, layout_engine)
  207. def _multiline_split(self, text):
  208. split_character = "\n" if isinstance(text, str) else b"\n"
  209. return text.split(split_character)
  210. def getname(self):
  211. """
  212. :return: A tuple of the font family (e.g. Helvetica) and the font style
  213. (e.g. Bold)
  214. """
  215. return self.font.family, self.font.style
  216. def getmetrics(self):
  217. """
  218. :return: A tuple of the font ascent (the distance from the baseline to
  219. the highest outline point) and descent (the distance from the
  220. baseline to the lowest outline point, a negative value)
  221. """
  222. return self.font.ascent, self.font.descent
  223. def getlength(self, text, mode="", direction=None, features=None, language=None):
  224. """
  225. Returns length (in pixels with 1/64 precision) of given text when rendered
  226. in font with provided direction, features, and language.
  227. This is the amount by which following text should be offset.
  228. Text bounding box may extend past the length in some fonts,
  229. e.g. when using italics or accents.
  230. The result is returned as a float; it is a whole number if using basic layout.
  231. Note that the sum of two lengths may not equal the length of a concatenated
  232. string due to kerning. If you need to adjust for kerning, include the following
  233. character and subtract its length.
  234. For example, instead of ::
  235. hello = font.getlength("Hello")
  236. world = font.getlength("World")
  237. hello_world = hello + world # not adjusted for kerning
  238. assert hello_world == font.getlength("HelloWorld") # may fail
  239. use ::
  240. hello = font.getlength("HelloW") - font.getlength("W") # adjusted for kerning
  241. world = font.getlength("World")
  242. hello_world = hello + world # adjusted for kerning
  243. assert hello_world == font.getlength("HelloWorld") # True
  244. or disable kerning with (requires libraqm) ::
  245. hello = draw.textlength("Hello", font, features=["-kern"])
  246. world = draw.textlength("World", font, features=["-kern"])
  247. hello_world = hello + world # kerning is disabled, no need to adjust
  248. assert hello_world == draw.textlength("HelloWorld", font, features=["-kern"])
  249. .. versionadded:: 8.0.0
  250. :param text: Text to measure.
  251. :param mode: Used by some graphics drivers to indicate what mode the
  252. driver prefers; if empty, the renderer may return either
  253. mode. Note that the mode is always a string, to simplify
  254. C-level implementations.
  255. :param direction: Direction of the text. It can be 'rtl' (right to
  256. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  257. Requires libraqm.
  258. :param features: A list of OpenType font features to be used during text
  259. layout. This is usually used to turn on optional
  260. font features that are not enabled by default,
  261. for example 'dlig' or 'ss01', but can be also
  262. used to turn off default font features for
  263. example '-liga' to disable ligatures or '-kern'
  264. to disable kerning. To get all supported
  265. features, see
  266. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  267. Requires libraqm.
  268. :param language: Language of the text. Different languages may use
  269. different glyph shapes or ligatures. This parameter tells
  270. the font which language the text is in, and to apply the
  271. correct substitutions as appropriate, if available.
  272. It should be a `BCP 47 language code
  273. <https://www.w3.org/International/articles/language-tags/>`_
  274. Requires libraqm.
  275. :return: Width for horizontal, height for vertical text.
  276. """
  277. return self.font.getlength(text, mode, direction, features, language) / 64
  278. def getbbox(
  279. self,
  280. text,
  281. mode="",
  282. direction=None,
  283. features=None,
  284. language=None,
  285. stroke_width=0,
  286. anchor=None,
  287. ):
  288. """
  289. Returns bounding box (in pixels) of given text relative to given anchor
  290. when rendered in font with provided direction, features, and language.
  291. Use :py:meth:`getlength()` to get the offset of following text with
  292. 1/64 pixel precision. The bounding box includes extra margins for
  293. some fonts, e.g. italics or accents.
  294. .. versionadded:: 8.0.0
  295. :param text: Text to render.
  296. :param mode: Used by some graphics drivers to indicate what mode the
  297. driver prefers; if empty, the renderer may return either
  298. mode. Note that the mode is always a string, to simplify
  299. C-level implementations.
  300. :param direction: Direction of the text. It can be 'rtl' (right to
  301. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  302. Requires libraqm.
  303. :param features: A list of OpenType font features to be used during text
  304. layout. This is usually used to turn on optional
  305. font features that are not enabled by default,
  306. for example 'dlig' or 'ss01', but can be also
  307. used to turn off default font features for
  308. example '-liga' to disable ligatures or '-kern'
  309. to disable kerning. To get all supported
  310. features, see
  311. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  312. Requires libraqm.
  313. :param language: Language of the text. Different languages may use
  314. different glyph shapes or ligatures. This parameter tells
  315. the font which language the text is in, and to apply the
  316. correct substitutions as appropriate, if available.
  317. It should be a `BCP 47 language code
  318. <https://www.w3.org/International/articles/language-tags/>`_
  319. Requires libraqm.
  320. :param stroke_width: The width of the text stroke.
  321. :param anchor: The text anchor alignment. Determines the relative location of
  322. the anchor to the text. The default alignment is top left.
  323. See :ref:`text-anchors` for valid values.
  324. :return: ``(left, top, right, bottom)`` bounding box
  325. """
  326. size, offset = self.font.getsize(
  327. text, mode, direction, features, language, anchor
  328. )
  329. left, top = offset[0] - stroke_width, offset[1] - stroke_width
  330. width, height = size[0] + 2 * stroke_width, size[1] + 2 * stroke_width
  331. return left, top, left + width, top + height
  332. def getsize(
  333. self,
  334. text,
  335. direction=None,
  336. features=None,
  337. language=None,
  338. stroke_width=0,
  339. ):
  340. """
  341. .. deprecated:: 9.2.0
  342. Use :py:meth:`getlength()` to measure the offset of following text with
  343. 1/64 pixel precision.
  344. Use :py:meth:`getbbox()` to get the exact bounding box based on an anchor.
  345. See :ref:`deprecations <Font size and offset methods>` for more information.
  346. Returns width and height (in pixels) of given text if rendered in font with
  347. provided direction, features, and language.
  348. .. note:: For historical reasons this function measures text height from
  349. the ascender line instead of the top, see :ref:`text-anchors`.
  350. If you wish to measure text height from the top, it is recommended
  351. to use the bottom value of :meth:`getbbox` with ``anchor='lt'`` instead.
  352. :param text: Text to measure.
  353. :param direction: Direction of the text. It can be 'rtl' (right to
  354. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  355. Requires libraqm.
  356. .. versionadded:: 4.2.0
  357. :param features: A list of OpenType font features to be used during text
  358. layout. This is usually used to turn on optional
  359. font features that are not enabled by default,
  360. for example 'dlig' or 'ss01', but can be also
  361. used to turn off default font features for
  362. example '-liga' to disable ligatures or '-kern'
  363. to disable kerning. To get all supported
  364. features, see
  365. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  366. Requires libraqm.
  367. .. versionadded:: 4.2.0
  368. :param language: Language of the text. Different languages may use
  369. different glyph shapes or ligatures. This parameter tells
  370. the font which language the text is in, and to apply the
  371. correct substitutions as appropriate, if available.
  372. It should be a `BCP 47 language code
  373. <https://www.w3.org/International/articles/language-tags/>`_
  374. Requires libraqm.
  375. .. versionadded:: 6.0.0
  376. :param stroke_width: The width of the text stroke.
  377. .. versionadded:: 6.2.0
  378. :return: (width, height)
  379. """
  380. deprecate("getsize", 10, "getbbox or getlength")
  381. # vertical offset is added for historical reasons
  382. # see https://github.com/python-pillow/Pillow/pull/4910#discussion_r486682929
  383. size, offset = self.font.getsize(text, "L", direction, features, language)
  384. return (
  385. size[0] + stroke_width * 2,
  386. size[1] + stroke_width * 2 + offset[1],
  387. )
  388. def getsize_multiline(
  389. self,
  390. text,
  391. direction=None,
  392. spacing=4,
  393. features=None,
  394. language=None,
  395. stroke_width=0,
  396. ):
  397. """
  398. .. deprecated:: 9.2.0
  399. Use :py:meth:`.ImageDraw.multiline_textbbox` instead.
  400. See :ref:`deprecations <Font size and offset methods>` for more information.
  401. Returns width and height (in pixels) of given text if rendered in font
  402. with provided direction, features, and language, while respecting
  403. newline characters.
  404. :param text: Text to measure.
  405. :param direction: Direction of the text. It can be 'rtl' (right to
  406. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  407. Requires libraqm.
  408. :param spacing: The vertical gap between lines, defaulting to 4 pixels.
  409. :param features: A list of OpenType font features to be used during text
  410. layout. This is usually used to turn on optional
  411. font features that are not enabled by default,
  412. for example 'dlig' or 'ss01', but can be also
  413. used to turn off default font features for
  414. example '-liga' to disable ligatures or '-kern'
  415. to disable kerning. To get all supported
  416. features, see
  417. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  418. Requires libraqm.
  419. :param language: Language of the text. Different languages may use
  420. different glyph shapes or ligatures. This parameter tells
  421. the font which language the text is in, and to apply the
  422. correct substitutions as appropriate, if available.
  423. It should be a `BCP 47 language code
  424. <https://www.w3.org/International/articles/language-tags/>`_
  425. Requires libraqm.
  426. .. versionadded:: 6.0.0
  427. :param stroke_width: The width of the text stroke.
  428. .. versionadded:: 6.2.0
  429. :return: (width, height)
  430. """
  431. deprecate("getsize_multiline", 10, "ImageDraw.multiline_textbbox")
  432. max_width = 0
  433. lines = self._multiline_split(text)
  434. with warnings.catch_warnings():
  435. warnings.filterwarnings("ignore", category=DeprecationWarning)
  436. line_spacing = self.getsize("A", stroke_width=stroke_width)[1] + spacing
  437. for line in lines:
  438. line_width, line_height = self.getsize(
  439. line, direction, features, language, stroke_width
  440. )
  441. max_width = max(max_width, line_width)
  442. return max_width, len(lines) * line_spacing - spacing
  443. def getoffset(self, text):
  444. """
  445. .. deprecated:: 9.2.0
  446. Use :py:meth:`.getbbox` instead.
  447. See :ref:`deprecations <Font size and offset methods>` for more information.
  448. Returns the offset of given text. This is the gap between the
  449. starting coordinate and the first marking. Note that this gap is
  450. included in the result of :py:func:`~PIL.ImageFont.FreeTypeFont.getsize`.
  451. :param text: Text to measure.
  452. :return: A tuple of the x and y offset
  453. """
  454. deprecate("getoffset", 10, "getbbox")
  455. return self.font.getsize(text)[1]
  456. def getmask(
  457. self,
  458. text,
  459. mode="",
  460. direction=None,
  461. features=None,
  462. language=None,
  463. stroke_width=0,
  464. anchor=None,
  465. ink=0,
  466. start=None,
  467. ):
  468. """
  469. Create a bitmap for the text.
  470. If the font uses antialiasing, the bitmap should have mode ``L`` and use a
  471. maximum value of 255. If the font has embedded color data, the bitmap
  472. should have mode ``RGBA``. Otherwise, it should have mode ``1``.
  473. :param text: Text to render.
  474. :param mode: Used by some graphics drivers to indicate what mode the
  475. driver prefers; if empty, the renderer may return either
  476. mode. Note that the mode is always a string, to simplify
  477. C-level implementations.
  478. .. versionadded:: 1.1.5
  479. :param direction: Direction of the text. It can be 'rtl' (right to
  480. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  481. Requires libraqm.
  482. .. versionadded:: 4.2.0
  483. :param features: A list of OpenType font features to be used during text
  484. layout. This is usually used to turn on optional
  485. font features that are not enabled by default,
  486. for example 'dlig' or 'ss01', but can be also
  487. used to turn off default font features for
  488. example '-liga' to disable ligatures or '-kern'
  489. to disable kerning. To get all supported
  490. features, see
  491. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  492. Requires libraqm.
  493. .. versionadded:: 4.2.0
  494. :param language: Language of the text. Different languages may use
  495. different glyph shapes or ligatures. This parameter tells
  496. the font which language the text is in, and to apply the
  497. correct substitutions as appropriate, if available.
  498. It should be a `BCP 47 language code
  499. <https://www.w3.org/International/articles/language-tags/>`_
  500. Requires libraqm.
  501. .. versionadded:: 6.0.0
  502. :param stroke_width: The width of the text stroke.
  503. .. versionadded:: 6.2.0
  504. :param anchor: The text anchor alignment. Determines the relative location of
  505. the anchor to the text. The default alignment is top left.
  506. See :ref:`text-anchors` for valid values.
  507. .. versionadded:: 8.0.0
  508. :param ink: Foreground ink for rendering in RGBA mode.
  509. .. versionadded:: 8.0.0
  510. :param start: Tuple of horizontal and vertical offset, as text may render
  511. differently when starting at fractional coordinates.
  512. .. versionadded:: 9.4.0
  513. :return: An internal PIL storage memory instance as defined by the
  514. :py:mod:`PIL.Image.core` interface module.
  515. """
  516. return self.getmask2(
  517. text,
  518. mode,
  519. direction=direction,
  520. features=features,
  521. language=language,
  522. stroke_width=stroke_width,
  523. anchor=anchor,
  524. ink=ink,
  525. start=start,
  526. )[0]
  527. def getmask2(
  528. self,
  529. text,
  530. mode="",
  531. fill=_UNSPECIFIED,
  532. direction=None,
  533. features=None,
  534. language=None,
  535. stroke_width=0,
  536. anchor=None,
  537. ink=0,
  538. start=None,
  539. *args,
  540. **kwargs,
  541. ):
  542. """
  543. Create a bitmap for the text.
  544. If the font uses antialiasing, the bitmap should have mode ``L`` and use a
  545. maximum value of 255. If the font has embedded color data, the bitmap
  546. should have mode ``RGBA``. Otherwise, it should have mode ``1``.
  547. :param text: Text to render.
  548. :param mode: Used by some graphics drivers to indicate what mode the
  549. driver prefers; if empty, the renderer may return either
  550. mode. Note that the mode is always a string, to simplify
  551. C-level implementations.
  552. .. versionadded:: 1.1.5
  553. :param fill: Optional fill function. By default, an internal Pillow function
  554. will be used.
  555. Deprecated. This parameter will be removed in Pillow 10
  556. (2023-07-01).
  557. :param direction: Direction of the text. It can be 'rtl' (right to
  558. left), 'ltr' (left to right) or 'ttb' (top to bottom).
  559. Requires libraqm.
  560. .. versionadded:: 4.2.0
  561. :param features: A list of OpenType font features to be used during text
  562. layout. This is usually used to turn on optional
  563. font features that are not enabled by default,
  564. for example 'dlig' or 'ss01', but can be also
  565. used to turn off default font features for
  566. example '-liga' to disable ligatures or '-kern'
  567. to disable kerning. To get all supported
  568. features, see
  569. https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
  570. Requires libraqm.
  571. .. versionadded:: 4.2.0
  572. :param language: Language of the text. Different languages may use
  573. different glyph shapes or ligatures. This parameter tells
  574. the font which language the text is in, and to apply the
  575. correct substitutions as appropriate, if available.
  576. It should be a `BCP 47 language code
  577. <https://www.w3.org/International/articles/language-tags/>`_
  578. Requires libraqm.
  579. .. versionadded:: 6.0.0
  580. :param stroke_width: The width of the text stroke.
  581. .. versionadded:: 6.2.0
  582. :param anchor: The text anchor alignment. Determines the relative location of
  583. the anchor to the text. The default alignment is top left.
  584. See :ref:`text-anchors` for valid values.
  585. .. versionadded:: 8.0.0
  586. :param ink: Foreground ink for rendering in RGBA mode.
  587. .. versionadded:: 8.0.0
  588. :param start: Tuple of horizontal and vertical offset, as text may render
  589. differently when starting at fractional coordinates.
  590. .. versionadded:: 9.4.0
  591. :return: A tuple of an internal PIL storage memory instance as defined by the
  592. :py:mod:`PIL.Image.core` interface module, and the text offset, the
  593. gap between the starting coordinate and the first marking
  594. """
  595. if fill is _UNSPECIFIED:
  596. fill = Image.core.fill
  597. else:
  598. deprecate("fill", 10)
  599. size, offset = self.font.getsize(
  600. text, mode, direction, features, language, anchor
  601. )
  602. if start is None:
  603. start = (0, 0)
  604. size = tuple(math.ceil(size[i] + stroke_width * 2 + start[i]) for i in range(2))
  605. offset = offset[0] - stroke_width, offset[1] - stroke_width
  606. Image._decompression_bomb_check(size)
  607. im = fill("RGBA" if mode == "RGBA" else "L", size, 0)
  608. if min(size):
  609. self.font.render(
  610. text,
  611. im.id,
  612. mode,
  613. direction,
  614. features,
  615. language,
  616. stroke_width,
  617. ink,
  618. start[0],
  619. start[1],
  620. )
  621. return im, offset
  622. def font_variant(
  623. self, font=None, size=None, index=None, encoding=None, layout_engine=None
  624. ):
  625. """
  626. Create a copy of this FreeTypeFont object,
  627. using any specified arguments to override the settings.
  628. Parameters are identical to the parameters used to initialize this
  629. object.
  630. :return: A FreeTypeFont object.
  631. """
  632. if font is None:
  633. try:
  634. font = BytesIO(self.font_bytes)
  635. except AttributeError:
  636. font = self.path
  637. return FreeTypeFont(
  638. font=font,
  639. size=self.size if size is None else size,
  640. index=self.index if index is None else index,
  641. encoding=self.encoding if encoding is None else encoding,
  642. layout_engine=layout_engine or self.layout_engine,
  643. )
  644. def get_variation_names(self):
  645. """
  646. :returns: A list of the named styles in a variation font.
  647. :exception OSError: If the font is not a variation font.
  648. """
  649. try:
  650. names = self.font.getvarnames()
  651. except AttributeError as e:
  652. msg = "FreeType 2.9.1 or greater is required"
  653. raise NotImplementedError(msg) from e
  654. return [name.replace(b"\x00", b"") for name in names]
  655. def set_variation_by_name(self, name):
  656. """
  657. :param name: The name of the style.
  658. :exception OSError: If the font is not a variation font.
  659. """
  660. names = self.get_variation_names()
  661. if not isinstance(name, bytes):
  662. name = name.encode()
  663. index = names.index(name) + 1
  664. if index == getattr(self, "_last_variation_index", None):
  665. # When the same name is set twice in a row,
  666. # there is an 'unknown freetype error'
  667. # https://savannah.nongnu.org/bugs/?56186
  668. return
  669. self._last_variation_index = index
  670. self.font.setvarname(index)
  671. def get_variation_axes(self):
  672. """
  673. :returns: A list of the axes in a variation font.
  674. :exception OSError: If the font is not a variation font.
  675. """
  676. try:
  677. axes = self.font.getvaraxes()
  678. except AttributeError as e:
  679. msg = "FreeType 2.9.1 or greater is required"
  680. raise NotImplementedError(msg) from e
  681. for axis in axes:
  682. axis["name"] = axis["name"].replace(b"\x00", b"")
  683. return axes
  684. def set_variation_by_axes(self, axes):
  685. """
  686. :param axes: A list of values for each axis.
  687. :exception OSError: If the font is not a variation font.
  688. """
  689. try:
  690. self.font.setvaraxes(axes)
  691. except AttributeError as e:
  692. msg = "FreeType 2.9.1 or greater is required"
  693. raise NotImplementedError(msg) from e
  694. class TransposedFont:
  695. """Wrapper for writing rotated or mirrored text"""
  696. def __init__(self, font, orientation=None):
  697. """
  698. Wrapper that creates a transposed font from any existing font
  699. object.
  700. :param font: A font object.
  701. :param orientation: An optional orientation. If given, this should
  702. be one of Image.Transpose.FLIP_LEFT_RIGHT, Image.Transpose.FLIP_TOP_BOTTOM,
  703. Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_180, or
  704. Image.Transpose.ROTATE_270.
  705. """
  706. self.font = font
  707. self.orientation = orientation # any 'transpose' argument, or None
  708. def getsize(self, text, *args, **kwargs):
  709. """
  710. .. deprecated:: 9.2.0
  711. Use :py:meth:`.getbbox` or :py:meth:`.getlength` instead.
  712. See :ref:`deprecations <Font size and offset methods>` for more information.
  713. """
  714. deprecate("getsize", 10, "getbbox or getlength")
  715. with warnings.catch_warnings():
  716. warnings.filterwarnings("ignore", category=DeprecationWarning)
  717. w, h = self.font.getsize(text)
  718. if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
  719. return h, w
  720. return w, h
  721. def getmask(self, text, mode="", *args, **kwargs):
  722. im = self.font.getmask(text, mode, *args, **kwargs)
  723. if self.orientation is not None:
  724. return im.transpose(self.orientation)
  725. return im
  726. def getbbox(self, text, *args, **kwargs):
  727. # TransposedFont doesn't support getmask2, move top-left point to (0, 0)
  728. # this has no effect on ImageFont and simulates anchor="lt" for FreeTypeFont
  729. left, top, right, bottom = self.font.getbbox(text, *args, **kwargs)
  730. width = right - left
  731. height = bottom - top
  732. if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
  733. return 0, 0, height, width
  734. return 0, 0, width, height
  735. def getlength(self, text, *args, **kwargs):
  736. if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
  737. msg = "text length is undefined for text rotated by 90 or 270 degrees"
  738. raise ValueError(msg)
  739. return self.font.getlength(text, *args, **kwargs)
  740. def load(filename):
  741. """
  742. Load a font file. This function loads a font object from the given
  743. bitmap font file, and returns the corresponding font object.
  744. :param filename: Name of font file.
  745. :return: A font object.
  746. :exception OSError: If the file could not be read.
  747. """
  748. f = ImageFont()
  749. f._load_pilfont(filename)
  750. return f
  751. def truetype(font=None, size=10, index=0, encoding="", layout_engine=None):
  752. """
  753. Load a TrueType or OpenType font from a file or file-like object,
  754. and create a font object.
  755. This function loads a font object from the given file or file-like
  756. object, and creates a font object for a font of the given size.
  757. Pillow uses FreeType to open font files. On Windows, be aware that FreeType
  758. will keep the file open as long as the FreeTypeFont object exists. Windows
  759. limits the number of files that can be open in C at once to 512, so if many
  760. fonts are opened simultaneously and that limit is approached, an
  761. ``OSError`` may be thrown, reporting that FreeType "cannot open resource".
  762. A workaround would be to copy the file(s) into memory, and open that instead.
  763. This function requires the _imagingft service.
  764. :param font: A filename or file-like object containing a TrueType font.
  765. If the file is not found in this filename, the loader may also
  766. search in other directories, such as the :file:`fonts/`
  767. directory on Windows or :file:`/Library/Fonts/`,
  768. :file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on
  769. macOS.
  770. :param size: The requested size, in pixels.
  771. :param index: Which font face to load (default is first available face).
  772. :param encoding: Which font encoding to use (default is Unicode). Possible
  773. encodings include (see the FreeType documentation for more
  774. information):
  775. * "unic" (Unicode)
  776. * "symb" (Microsoft Symbol)
  777. * "ADOB" (Adobe Standard)
  778. * "ADBE" (Adobe Expert)
  779. * "ADBC" (Adobe Custom)
  780. * "armn" (Apple Roman)
  781. * "sjis" (Shift JIS)
  782. * "gb " (PRC)
  783. * "big5"
  784. * "wans" (Extended Wansung)
  785. * "joha" (Johab)
  786. * "lat1" (Latin-1)
  787. This specifies the character set to use. It does not alter the
  788. encoding of any text provided in subsequent operations.
  789. :param layout_engine: Which layout engine to use, if available:
  790. :data:`.ImageFont.Layout.BASIC` or :data:`.ImageFont.Layout.RAQM`.
  791. If it is available, Raqm layout will be used by default.
  792. Otherwise, basic layout will be used.
  793. Raqm layout is recommended for all non-English text. If Raqm layout
  794. is not required, basic layout will have better performance.
  795. You can check support for Raqm layout using
  796. :py:func:`PIL.features.check_feature` with ``feature="raqm"``.
  797. .. versionadded:: 4.2.0
  798. :return: A font object.
  799. :exception OSError: If the file could not be read.
  800. """
  801. def freetype(font):
  802. return FreeTypeFont(font, size, index, encoding, layout_engine)
  803. try:
  804. return freetype(font)
  805. except OSError:
  806. if not is_path(font):
  807. raise
  808. ttf_filename = os.path.basename(font)
  809. dirs = []
  810. if sys.platform == "win32":
  811. # check the windows font repository
  812. # NOTE: must use uppercase WINDIR, to work around bugs in
  813. # 1.5.2's os.environ.get()
  814. windir = os.environ.get("WINDIR")
  815. if windir:
  816. dirs.append(os.path.join(windir, "fonts"))
  817. elif sys.platform in ("linux", "linux2"):
  818. lindirs = os.environ.get("XDG_DATA_DIRS")
  819. if not lindirs:
  820. # According to the freedesktop spec, XDG_DATA_DIRS should
  821. # default to /usr/share
  822. lindirs = "/usr/share"
  823. dirs += [os.path.join(lindir, "fonts") for lindir in lindirs.split(":")]
  824. elif sys.platform == "darwin":
  825. dirs += [
  826. "/Library/Fonts",
  827. "/System/Library/Fonts",
  828. os.path.expanduser("~/Library/Fonts"),
  829. ]
  830. ext = os.path.splitext(ttf_filename)[1]
  831. first_font_with_a_different_extension = None
  832. for directory in dirs:
  833. for walkroot, walkdir, walkfilenames in os.walk(directory):
  834. for walkfilename in walkfilenames:
  835. if ext and walkfilename == ttf_filename:
  836. return freetype(os.path.join(walkroot, walkfilename))
  837. elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename:
  838. fontpath = os.path.join(walkroot, walkfilename)
  839. if os.path.splitext(fontpath)[1] == ".ttf":
  840. return freetype(fontpath)
  841. if not ext and first_font_with_a_different_extension is None:
  842. first_font_with_a_different_extension = fontpath
  843. if first_font_with_a_different_extension:
  844. return freetype(first_font_with_a_different_extension)
  845. raise
  846. def load_path(filename):
  847. """
  848. Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a
  849. bitmap font along the Python path.
  850. :param filename: Name of font file.
  851. :return: A font object.
  852. :exception OSError: If the file could not be read.
  853. """
  854. for directory in sys.path:
  855. if is_directory(directory):
  856. if not isinstance(filename, str):
  857. filename = filename.decode("utf-8")
  858. try:
  859. return load(os.path.join(directory, filename))
  860. except OSError:
  861. pass
  862. msg = "cannot find font file"
  863. raise OSError(msg)
  864. def load_default():
  865. """Load a "better than nothing" default font.
  866. .. versionadded:: 1.1.4
  867. :return: A font object.
  868. """
  869. f = ImageFont()
  870. f._load_pilfont_data(
  871. # courB08
  872. BytesIO(
  873. base64.b64decode(
  874. b"""
  875. UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  876. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  877. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  878. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  879. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  880. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  881. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  882. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  883. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  884. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  885. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  886. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA
  887. BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL
  888. AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA
  889. AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB
  890. ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A
  891. BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB
  892. //kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA
  893. AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH
  894. AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA
  895. ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv
  896. AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/
  897. /gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5
  898. AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA
  899. AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG
  900. AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA
  901. BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA
  902. AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA
  903. 2AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF
  904. AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA////
  905. +gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA
  906. ////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA
  907. BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv
  908. AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA
  909. AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA
  910. AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA
  911. BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP//
  912. //kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA
  913. AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF
  914. AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB
  915. mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn
  916. AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA
  917. AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7
  918. AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA
  919. Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA
  920. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  921. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  922. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  923. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  924. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  925. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  926. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  927. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  928. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  929. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  930. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  931. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB
  932. //sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA
  933. AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ
  934. AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC
  935. DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ
  936. AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/
  937. +wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5
  938. AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/
  939. ///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG
  940. AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA
  941. BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA
  942. Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC
  943. eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG
  944. AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA////
  945. +gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA
  946. ////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA
  947. BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT
  948. AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A
  949. AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA
  950. Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA
  951. Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP//
  952. //cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA
  953. AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ
  954. AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA
  955. LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5
  956. AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA
  957. AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5
  958. AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA
  959. AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG
  960. AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA
  961. EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK
  962. AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA
  963. pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG
  964. AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
  965. +QAGAAIAzgAKANUAEw==
  966. """
  967. )
  968. ),
  969. Image.open(
  970. BytesIO(
  971. base64.b64decode(
  972. b"""
  973. iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
  974. Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
  975. M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
  976. LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F
  977. IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA
  978. Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791
  979. NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx
  980. in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9
  981. SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY
  982. AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt
  983. y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG
  984. ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY
  985. lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H
  986. /Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3
  987. AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47
  988. c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/
  989. /yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw
  990. pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv
  991. oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR
  992. evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA
  993. AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v//
  994. Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
  995. w7IkEbzhVQAAAABJRU5ErkJggg==
  996. """
  997. )
  998. )
  999. ),
  1000. )
  1001. return f