Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/ImageFont.py: 38%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

300 statements  

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 

28from __future__ import annotations 

29 

30__lazy_modules__ = {"base64", "io", "types", "warnings"} 

31 

32import abc 

33import base64 

34import os 

35import sys 

36import warnings 

37from enum import IntEnum 

38from io import BytesIO 

39from types import ModuleType 

40from typing import TypedDict, cast 

41 

42from . import Image 

43from ._util import DeferredError, is_path 

44 

45TYPE_CHECKING = False 

46if TYPE_CHECKING: 

47 from typing import IO, Any, BinaryIO, NotRequired 

48 

49 from . import ImageFile 

50 from ._imaging import ImagingFont 

51 from ._imagingft import Font 

52 from ._typing import StrOrBytesPath 

53 

54 

55class Axis(TypedDict): 

56 minimum: int | None 

57 default: int | None 

58 maximum: int | None 

59 name: NotRequired[bytes] 

60 

61 

62class Layout(IntEnum): 

63 BASIC = 0 

64 RAQM = 1 

65 

66 

67MAX_STRING_LENGTH = 1_000_000 

68 

69# From raqm.c's _raqm_is_paragraph_separator() 

70_separators = ( 

71 "\r\n", # Windows 

72 "\n", # 0x000A 

73 "\r", # 0x000D 

74 "\u001c", 

75 "\u001d", 

76 "\u001e", 

77 "\u0085", 

78 "\u2029", 

79) 

80 

81core: ModuleType | DeferredError 

82try: 

83 from . import _imagingft as core 

84except ImportError as ex: 

85 core = DeferredError.new(ex) 

86 

87 

88def _string_length_check(text: str | bytes | bytearray) -> None: 

89 if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH: 

90 msg = "too many characters in string" 

91 raise ValueError(msg) 

92 

93 

94# FIXME: add support for pilfont2 format (see FontFile.py) 

95 

96# -------------------------------------------------------------------- 

97# Font metrics format: 

98# "PILfont" LF 

99# fontdescriptor LF 

100# (optional) key=value... LF 

101# "DATA" LF 

102# binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox) 

103# 

104# To place a character, cut out srcbox and paste at dstbox, 

105# relative to the character position. Then move the character 

106# position according to dx, dy. 

107# -------------------------------------------------------------------- 

108 

109 

110class BaseImageFont(abc.ABC): 

111 """Used by ImageDraw and ImageText""" 

112 

113 @abc.abstractmethod 

114 def getbbox( 

115 self, text: str | bytes | bytearray, *args: Any, **kwargs: Any 

116 ) -> tuple[float, float, float, float]: 

117 pass 

118 

119 @abc.abstractmethod 

120 def getmask( 

121 self, text: str | bytes, mode: str = "", *args: Any, **kwargs: Any 

122 ) -> Image.core.ImagingCore: 

123 pass 

124 

125 @abc.abstractmethod 

126 def getlength(self, text: str | bytes, *args: Any, **kwargs: Any) -> float: 

127 pass 

128 

129 

130class ImageFont(BaseImageFont): 

131 """PIL font wrapper""" 

132 

133 font: ImagingFont 

134 

135 def _load_pilfont(self, filename: str | os.PathLike[str]) -> None: 

136 with open(filename, "rb") as fp: 

137 image: ImageFile.ImageFile | None = None 

138 root = os.path.splitext(filename)[0] 

139 

140 for ext in (".png", ".gif", ".pbm"): 

141 if image: 

142 image.close() 

143 try: 

144 fullname = root + ext 

145 image = Image.open(fullname) 

146 except Exception: 

147 pass 

148 else: 

149 if image.mode in ("1", "L"): 

150 break 

151 else: 

152 if image: 

153 image.close() 

154 

155 msg = f"cannot find glyph data file {root}.{{gif|pbm|png}}" 

156 raise OSError(msg) 

157 

158 self.file = fullname 

159 

160 self._load_pilfont_data(fp, image) 

161 image.close() 

162 

163 def _load_pilfont_data(self, file: IO[bytes], image: Image.Image) -> None: 

164 # check image 

165 if image.mode not in ("1", "L"): 

166 image.close() 

167 

168 msg = "invalid font image mode" 

169 raise TypeError(msg) 

170 

171 # read PILfont header 

172 if file.read(8) != b"PILfont\n": 

173 image.close() 

174 

175 msg = "Not a PILfont file" 

176 raise SyntaxError(msg) 

177 file.readline() 

178 self.info = [] # FIXME: should be a dictionary 

179 while True: 

180 s = file.readline() 

181 if not s or s == b"DATA\n": 

182 break 

183 self.info.append(s) 

184 

185 # read PILfont metrics 

186 data = file.read(256 * 20) 

187 

188 self._load(image, data) 

189 

190 def _load(self, image: Image.Image, data: bytes) -> None: 

191 image.load() 

192 

193 self.font = Image.core.font(image.im, data) 

194 

195 def getmask( 

196 self, text: str | bytes, mode: str = "", *args: Any, **kwargs: Any 

197 ) -> Image.core.ImagingCore: 

198 """ 

199 Create a bitmap for the text. 

200 

201 If the font uses antialiasing, the bitmap should have mode ``L`` and use a 

202 maximum value of 255. Otherwise, it should have mode ``1``. 

203 

204 :param text: Text to render. 

205 :param mode: Used by some graphics drivers to indicate what mode the 

206 driver prefers; if empty, the renderer may return either 

207 mode. Note that the mode is always a string, to simplify 

208 C-level implementations. 

209 

210 .. versionadded:: 1.1.5 

211 

212 :return: An internal PIL storage memory instance as defined by the 

213 :py:mod:`PIL.Image.core` interface module. 

214 """ 

215 _string_length_check(text) 

216 Image._decompression_bomb_check(self.font.getsize(text)) 

217 return self.font.getmask(text, mode) 

218 

219 def getbbox( 

220 self, text: str | bytes | bytearray, *args: Any, **kwargs: Any 

221 ) -> tuple[int, int, int, int]: 

222 """ 

223 Returns bounding box (in pixels) of given text. 

224 

225 .. versionadded:: 9.2.0 

226 

227 :param text: Text to render. 

228 

229 :return: ``(left, top, right, bottom)`` bounding box 

230 """ 

231 _string_length_check(text) 

232 width, height = self.font.getsize(text) 

233 return 0, 0, width, height 

234 

235 def getlength( 

236 self, text: str | bytes | bytearray, *args: Any, **kwargs: Any 

237 ) -> int: 

238 """ 

239 Returns length (in pixels) of given text. 

240 This is the amount by which following text should be offset. 

241 

242 .. versionadded:: 9.2.0 

243 """ 

244 _string_length_check(text) 

245 width, height = self.font.getsize(text) 

246 return width 

247 

248 

249## 

250# Wrapper for FreeType fonts. Application code should use the 

251# <b>truetype</b> factory function to create font objects. 

252 

253 

254class FreeTypeFont(BaseImageFont): 

255 """FreeType font wrapper (requires _imagingft service)""" 

256 

257 font: Font 

258 font_bytes: bytes 

259 

260 def __init__( 

261 self, 

262 font: StrOrBytesPath | BinaryIO, 

263 size: float = 10, 

264 index: int = 0, 

265 encoding: str = "", 

266 layout_engine: Layout | None = None, 

267 ) -> None: 

268 # FIXME: use service provider instead 

269 

270 if isinstance(core, DeferredError): 

271 raise core.ex 

272 

273 if size <= 0: 

274 msg = f"font size must be greater than 0, not {size}" 

275 raise ValueError(msg) 

276 

277 self.path = font 

278 self.size = size 

279 self.index = index 

280 self.encoding = encoding 

281 

282 if layout_engine not in (Layout.BASIC, Layout.RAQM): 

283 layout_engine = Layout.BASIC 

284 if core.HAVE_RAQM: 

285 layout_engine = Layout.RAQM 

286 elif layout_engine == Layout.RAQM and not core.HAVE_RAQM: 

287 warnings.warn( 

288 "Raqm layout was requested, but Raqm is not available. " 

289 "Falling back to basic layout." 

290 ) 

291 layout_engine = Layout.BASIC 

292 

293 self.layout_engine = layout_engine 

294 

295 def load_from_bytes(f: IO[bytes]) -> None: 

296 self.font_bytes = f.read() 

297 self.font = core.getfont( 

298 "", size, index, encoding, layout_engine, self.font_bytes 

299 ) 

300 

301 if is_path(font): 

302 font = os.fspath(font) 

303 if sys.platform == "win32": 

304 font_bytes_path = font if isinstance(font, bytes) else font.encode() 

305 try: 

306 font_bytes_path.decode("ascii") 

307 except UnicodeDecodeError: 

308 # FreeType cannot load fonts with non-ASCII characters on Windows 

309 # So load it into memory first 

310 with open(font, "rb") as f: 

311 load_from_bytes(f) 

312 return 

313 self.font = core.getfont(font, size, index, encoding, layout_engine) 

314 else: 

315 load_from_bytes(cast("IO[bytes]", font)) 

316 

317 def __getstate__(self) -> list[Any]: 

318 return [self.path, self.size, self.index, self.encoding, self.layout_engine] 

319 

320 def __setstate__(self, state: list[Any]) -> None: 

321 path, size, index, encoding, layout_engine = state 

322 FreeTypeFont.__init__(self, path, size, index, encoding, layout_engine) 

323 

324 def getname(self) -> tuple[str | None, str | None]: 

325 """ 

326 :return: A tuple of the font family (e.g. Helvetica) and the font style 

327 (e.g. Bold) 

328 """ 

329 return self.font.family, self.font.style 

330 

331 def getmetrics(self) -> tuple[int, int]: 

332 """ 

333 :return: A tuple of the font ascent (the distance from the baseline to 

334 the highest outline point) and descent (the distance from the 

335 baseline to the lowest outline point, a negative value) 

336 """ 

337 return self.font.ascent, self.font.descent 

338 

339 def _has_separator(self, text: str | bytes | bytearray) -> bool: 

340 if self.layout_engine != Layout.RAQM: 

341 return False 

342 if isinstance(text, str): 

343 return any(separator in text for separator in _separators) 

344 return any(separator.encode() in text for separator in _separators) 

345 

346 def getlength( 

347 self, 

348 text: str | bytes, 

349 mode: str = "", 

350 direction: str | None = None, 

351 features: list[str] | None = None, 

352 language: str | None = None, 

353 ) -> float: 

354 """ 

355 Returns length (in pixels with 1/64 precision) of given text when rendered 

356 in font with provided direction, features, and language. 

357 

358 This is the amount by which following text should be offset. 

359 Text bounding box may extend past the length in some fonts, 

360 e.g. when using italics or accents. 

361 

362 The result is returned as a float; it is a whole number if using basic layout. 

363 

364 Note that the sum of two lengths may not equal the length of a concatenated 

365 string due to kerning. If you need to adjust for kerning, include the following 

366 character and subtract its length. 

367 

368 For example, instead of :: 

369 

370 hello = font.getlength("Hello") 

371 world = font.getlength("World") 

372 hello_world = hello + world # not adjusted for kerning 

373 assert hello_world == font.getlength("HelloWorld") # may fail 

374 

375 use :: 

376 

377 hello = font.getlength("HelloW") - font.getlength("W") # adjusted for kerning 

378 world = font.getlength("World") 

379 hello_world = hello + world # adjusted for kerning 

380 assert hello_world == font.getlength("HelloWorld") # True 

381 

382 or disable kerning with (requires libraqm) :: 

383 

384 hello = draw.textlength("Hello", font, features=["-kern"]) 

385 world = draw.textlength("World", font, features=["-kern"]) 

386 hello_world = hello + world # kerning is disabled, no need to adjust 

387 assert hello_world == draw.textlength("HelloWorld", font, features=["-kern"]) 

388 

389 .. versionadded:: 8.0.0 

390 

391 :param text: Text to measure. Newlines raise an error with Raqm layout. 

392 :param mode: Used by some graphics drivers to indicate what mode the 

393 driver prefers; if empty, the renderer may return either 

394 mode. Note that the mode is always a string, to simplify 

395 C-level implementations. 

396 

397 :param direction: Direction of the text. It can be 'rtl' (right to 

398 left), 'ltr' (left to right) or 'ttb' (top to bottom). 

399 Requires libraqm. 

400 

401 :param features: A list of OpenType font features to be used during text 

402 layout. This is usually used to turn on optional 

403 font features that are not enabled by default, 

404 for example 'dlig' or 'ss01', but can be also 

405 used to turn off default font features for 

406 example '-liga' to disable ligatures or '-kern' 

407 to disable kerning. To get all supported 

408 features, see 

409 https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist 

410 Requires libraqm. 

411 

412 :param language: Language of the text. Different languages may use 

413 different glyph shapes or ligatures. This parameter tells 

414 the font which language the text is in, and to apply the 

415 correct substitutions as appropriate, if available. 

416 It should be a `BCP 47 language code 

417 <https://www.w3.org/International/articles/language-tags/>`_ 

418 Requires libraqm. 

419 

420 :return: Either width for horizontal text, or height for vertical text. 

421 """ 

422 _string_length_check(text) 

423 if self._has_separator(text): 

424 msg = "can't measure length of multiline text with Raqm" 

425 raise ValueError(msg) 

426 return self.font.getlength(text, mode, direction, features, language) / 64 

427 

428 def getbbox( 

429 self, 

430 text: str | bytes | bytearray, 

431 mode: str = "", 

432 direction: str | None = None, 

433 features: list[str] | None = None, 

434 language: str | None = None, 

435 stroke_width: float = 0, 

436 anchor: str | None = None, 

437 ) -> tuple[float, float, float, float]: 

438 """ 

439 Returns bounding box (in pixels) of given text relative to given anchor 

440 when rendered in font with provided direction, features, and language. 

441 

442 Use :py:meth:`getlength()` to get the offset of following text with 

443 1/64 pixel precision. The bounding box includes extra margins for 

444 some fonts, e.g. italics or accents. 

445 

446 .. versionadded:: 8.0.0 

447 

448 :param text: Text to render. Newlines will not cause a line break with 

449 Basic layout, and will raise an error with Raqm layout. 

450 :param mode: Used by some graphics drivers to indicate what mode the 

451 driver prefers; if empty, the renderer may return either 

452 mode. Note that the mode is always a string, to simplify 

453 C-level implementations. 

454 

455 :param direction: Direction of the text. It can be 'rtl' (right to 

456 left), 'ltr' (left to right) or 'ttb' (top to bottom). 

457 Requires libraqm. 

458 

459 :param features: A list of OpenType font features to be used during text 

460 layout. This is usually used to turn on optional 

461 font features that are not enabled by default, 

462 for example 'dlig' or 'ss01', but can be also 

463 used to turn off default font features for 

464 example '-liga' to disable ligatures or '-kern' 

465 to disable kerning. To get all supported 

466 features, see 

467 https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist 

468 Requires libraqm. 

469 

470 :param language: Language of the text. Different languages may use 

471 different glyph shapes or ligatures. This parameter tells 

472 the font which language the text is in, and to apply the 

473 correct substitutions as appropriate, if available. 

474 It should be a `BCP 47 language code 

475 <https://www.w3.org/International/articles/language-tags/>`_ 

476 Requires libraqm. 

477 

478 :param stroke_width: The width of the text stroke. 

479 

480 :param anchor: The text anchor alignment. Determines the relative location of 

481 the anchor to the text. The default alignment is top left, 

482 specifically ``la`` for horizontal text and ``lt`` for 

483 vertical text. See :ref:`text-anchors` for details. 

484 

485 :return: ``(left, top, right, bottom)`` bounding box 

486 """ 

487 _string_length_check(text) 

488 if self._has_separator(text): 

489 msg = "can't measure bounding box of multiline text with Raqm" 

490 raise ValueError(msg) 

491 size, offset = self.font.getsize( 

492 text, mode, direction, features, language, anchor 

493 ) 

494 left, top = offset[0] - stroke_width, offset[1] - stroke_width 

495 width, height = size[0] + 2 * stroke_width, size[1] + 2 * stroke_width 

496 return left, top, left + width, top + height 

497 

498 def getmask( 

499 self, 

500 text: str | bytes, 

501 mode: str = "", 

502 direction: str | None = None, 

503 features: list[str] | None = None, 

504 language: str | None = None, 

505 stroke_width: float = 0, 

506 anchor: str | None = None, 

507 ink: int = 0, 

508 start: tuple[float, float] | None = None, 

509 ) -> Image.core.ImagingCore: 

510 """ 

511 Create a bitmap for the text. 

512 

513 If the font uses antialiasing, the bitmap should have mode ``L`` and use a 

514 maximum value of 255. If the font has embedded color data, the bitmap 

515 should have mode ``RGBA``. Otherwise, it should have mode ``1``. 

516 

517 :param text: Text to render. 

518 :param mode: Used by some graphics drivers to indicate what mode the 

519 driver prefers; if empty, the renderer may return either 

520 mode. Note that the mode is always a string, to simplify 

521 C-level implementations. 

522 

523 .. versionadded:: 1.1.5 

524 

525 :param direction: Direction of the text. It can be 'rtl' (right to 

526 left), 'ltr' (left to right) or 'ttb' (top to bottom). 

527 Requires libraqm. 

528 

529 .. versionadded:: 4.2.0 

530 

531 :param features: A list of OpenType font features to be used during text 

532 layout. This is usually used to turn on optional 

533 font features that are not enabled by default, 

534 for example 'dlig' or 'ss01', but can be also 

535 used to turn off default font features for 

536 example '-liga' to disable ligatures or '-kern' 

537 to disable kerning. To get all supported 

538 features, see 

539 https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist 

540 Requires libraqm. 

541 

542 .. versionadded:: 4.2.0 

543 

544 :param language: Language of the text. Different languages may use 

545 different glyph shapes or ligatures. This parameter tells 

546 the font which language the text is in, and to apply the 

547 correct substitutions as appropriate, if available. 

548 It should be a `BCP 47 language code 

549 <https://www.w3.org/International/articles/language-tags/>`_ 

550 Requires libraqm. 

551 

552 .. versionadded:: 6.0.0 

553 

554 :param stroke_width: The width of the text stroke. 

555 

556 .. versionadded:: 6.2.0 

557 

558 :param anchor: The text anchor alignment. Determines the relative location of 

559 the anchor to the text. The default alignment is top left, 

560 specifically ``la`` for horizontal text and ``lt`` for 

561 vertical text. See :ref:`text-anchors` for details. 

562 

563 .. versionadded:: 8.0.0 

564 

565 :param ink: Foreground ink for rendering in RGBA mode. 

566 

567 .. versionadded:: 8.0.0 

568 

569 :param start: Tuple of horizontal and vertical offset, as text may render 

570 differently when starting at fractional coordinates. 

571 

572 .. versionadded:: 9.4.0 

573 

574 :return: An internal PIL storage memory instance as defined by the 

575 :py:mod:`PIL.Image.core` interface module. 

576 """ 

577 return self.getmask2( 

578 text, 

579 mode, 

580 direction=direction, 

581 features=features, 

582 language=language, 

583 stroke_width=stroke_width, 

584 anchor=anchor, 

585 ink=ink, 

586 start=start, 

587 )[0] 

588 

589 def getmask2( 

590 self, 

591 text: str | bytes, 

592 mode: str = "", 

593 direction: str | None = None, 

594 features: list[str] | None = None, 

595 language: str | None = None, 

596 stroke_width: float = 0, 

597 anchor: str | None = None, 

598 ink: int = 0, 

599 start: tuple[float, float] | None = None, 

600 *args: Any, 

601 **kwargs: Any, 

602 ) -> tuple[Image.core.ImagingCore, tuple[int, int]]: 

603 """ 

604 Create a bitmap for the text. 

605 

606 If the font uses antialiasing, the bitmap should have mode ``L`` and use a 

607 maximum value of 255. If the font has embedded color data, the bitmap 

608 should have mode ``RGBA``. Otherwise, it should have mode ``1``. 

609 

610 :param text: Text to render. 

611 :param mode: Used by some graphics drivers to indicate what mode the 

612 driver prefers; if empty, the renderer may return either 

613 mode. Note that the mode is always a string, to simplify 

614 C-level implementations. 

615 

616 .. versionadded:: 1.1.5 

617 

618 :param direction: Direction of the text. It can be 'rtl' (right to 

619 left), 'ltr' (left to right) or 'ttb' (top to bottom). 

620 Requires libraqm. 

621 

622 .. versionadded:: 4.2.0 

623 

624 :param features: A list of OpenType font features to be used during text 

625 layout. This is usually used to turn on optional 

626 font features that are not enabled by default, 

627 for example 'dlig' or 'ss01', but can be also 

628 used to turn off default font features for 

629 example '-liga' to disable ligatures or '-kern' 

630 to disable kerning. To get all supported 

631 features, see 

632 https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist 

633 Requires libraqm. 

634 

635 .. versionadded:: 4.2.0 

636 

637 :param language: Language of the text. Different languages may use 

638 different glyph shapes or ligatures. This parameter tells 

639 the font which language the text is in, and to apply the 

640 correct substitutions as appropriate, if available. 

641 It should be a `BCP 47 language code 

642 <https://www.w3.org/International/articles/language-tags/>`_ 

643 Requires libraqm. 

644 

645 .. versionadded:: 6.0.0 

646 

647 :param stroke_width: The width of the text stroke. 

648 

649 .. versionadded:: 6.2.0 

650 

651 :param anchor: The text anchor alignment. Determines the relative location of 

652 the anchor to the text. The default alignment is top left, 

653 specifically ``la`` for horizontal text and ``lt`` for 

654 vertical text. See :ref:`text-anchors` for details. 

655 

656 .. versionadded:: 8.0.0 

657 

658 :param ink: Foreground ink for rendering in RGBA mode. 

659 

660 .. versionadded:: 8.0.0 

661 

662 :param start: Tuple of horizontal and vertical offset, as text may render 

663 differently when starting at fractional coordinates. 

664 

665 .. versionadded:: 9.4.0 

666 

667 :return: A tuple of an internal PIL storage memory instance as defined by the 

668 :py:mod:`PIL.Image.core` interface module, and the text offset, the 

669 gap between the starting coordinate and the first marking 

670 """ 

671 _string_length_check(text) 

672 if start is None: 

673 start = (0, 0) 

674 

675 def fill(width: int, height: int) -> Image.core.ImagingCore: 

676 size = (width, height) 

677 Image._decompression_bomb_check(size) 

678 return Image.core.fill("RGBA" if mode == "RGBA" else "L", size) 

679 

680 return self.font.render( 

681 text, 

682 fill, 

683 mode, 

684 direction, 

685 features, 

686 language, 

687 stroke_width, 

688 kwargs.get("stroke_filled", False), 

689 anchor, 

690 ink, 

691 start, 

692 ) 

693 

694 def font_variant( 

695 self, 

696 font: StrOrBytesPath | BinaryIO | None = None, 

697 size: float | None = None, 

698 index: int | None = None, 

699 encoding: str | None = None, 

700 layout_engine: Layout | None = None, 

701 ) -> FreeTypeFont: 

702 """ 

703 Create a copy of this FreeTypeFont object, 

704 using any specified arguments to override the settings. 

705 

706 Parameters are identical to the parameters used to initialize this 

707 object. 

708 

709 :return: A FreeTypeFont object. 

710 """ 

711 if font is None: 

712 try: 

713 font = BytesIO(self.font_bytes) 

714 except AttributeError: 

715 font = self.path 

716 return FreeTypeFont( 

717 font=font, 

718 size=self.size if size is None else size, 

719 index=self.index if index is None else index, 

720 encoding=self.encoding if encoding is None else encoding, 

721 layout_engine=( 

722 layout_engine if layout_engine is not None else self.layout_engine 

723 ), 

724 ) 

725 

726 def get_variation_names(self) -> list[bytes]: 

727 """ 

728 :returns: A list of the named styles in a variation font. 

729 :exception OSError: If the font is not a variation font. 

730 """ 

731 names = [] 

732 for name in self.font.getvarnames(): 

733 name = name.replace(b"\x00", b"") 

734 if name not in names: 

735 names.append(name) 

736 return names 

737 

738 def set_variation_by_name(self, name: str | bytes) -> None: 

739 """ 

740 :param name: The name of the style. 

741 :exception OSError: If the font is not a variation font. 

742 """ 

743 names = self.get_variation_names() 

744 if not isinstance(name, bytes): 

745 name = name.encode() 

746 index = names.index(name) + 1 

747 

748 if index == getattr(self, "_last_variation_index", None): 

749 # When the same name is set twice in a row, 

750 # there is an 'unknown freetype error' 

751 # https://savannah.nongnu.org/bugs/?56186 

752 return 

753 self._last_variation_index = index 

754 

755 self.font.setvarname(index) 

756 

757 def get_variation_axes(self) -> list[Axis]: 

758 """ 

759 :returns: A list of the axes in a variation font. 

760 :exception OSError: If the font is not a variation font. 

761 """ 

762 axes = self.font.getvaraxes() 

763 for axis in axes: 

764 if "name" in axis: 

765 axis["name"] = axis["name"].replace(b"\x00", b"") 

766 return axes 

767 

768 def set_variation_by_axes(self, axes: list[float]) -> None: 

769 """ 

770 :param axes: A list of values for each axis. 

771 :exception OSError: If the font is not a variation font. 

772 """ 

773 self.font.setvaraxes(axes) 

774 

775 

776class TransposedFont(BaseImageFont): 

777 """Wrapper for writing rotated or mirrored text""" 

778 

779 def __init__( 

780 self, font: ImageFont | FreeTypeFont, orientation: Image.Transpose | None = None 

781 ): 

782 """ 

783 Wrapper that creates a transposed font from any existing font 

784 object. 

785 

786 :param font: A font object. 

787 :param orientation: An optional orientation. If given, this should 

788 be one of Image.Transpose.FLIP_LEFT_RIGHT, Image.Transpose.FLIP_TOP_BOTTOM, 

789 Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_180, or 

790 Image.Transpose.ROTATE_270. 

791 """ 

792 self.font = font 

793 self.orientation = orientation # any 'transpose' argument, or None 

794 

795 def getmask( 

796 self, text: str | bytes, mode: str = "", *args: Any, **kwargs: Any 

797 ) -> Image.core.ImagingCore: 

798 im = self.font.getmask(text, mode, *args, **kwargs) 

799 if self.orientation is not None: 

800 return im.transpose(self.orientation) 

801 return im 

802 

803 def getbbox( 

804 self, text: str | bytes | bytearray, *args: Any, **kwargs: Any 

805 ) -> tuple[int, int, float, float]: 

806 # TransposedFont doesn't support getmask2, move top-left point to (0, 0) 

807 # this has no effect on ImageFont and simulates anchor="lt" for FreeTypeFont 

808 left, top, right, bottom = self.font.getbbox(text, *args, **kwargs) 

809 width = right - left 

810 height = bottom - top 

811 if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): 

812 return 0, 0, height, width 

813 return 0, 0, width, height 

814 

815 def getlength(self, text: str | bytes, *args: Any, **kwargs: Any) -> float: 

816 if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270): 

817 msg = "text length is undefined for text rotated by 90 or 270 degrees" 

818 raise ValueError(msg) 

819 return self.font.getlength(text, *args, **kwargs) 

820 

821 

822def load(filename: str | os.PathLike[str]) -> ImageFont: 

823 """ 

824 Load a font file. This function loads a font object from the given 

825 bitmap font file, and returns the corresponding font object. For loading TrueType 

826 or OpenType fonts instead, see :py:func:`~PIL.ImageFont.truetype`. 

827 

828 :param filename: Name of font file. 

829 :return: A font object. 

830 :exception OSError: If the file could not be read. 

831 """ 

832 f = ImageFont() 

833 f._load_pilfont(filename) 

834 return f 

835 

836 

837def truetype( 

838 font: StrOrBytesPath | BinaryIO, 

839 size: float = 10, 

840 index: int = 0, 

841 encoding: str = "", 

842 layout_engine: Layout | None = None, 

843) -> FreeTypeFont: 

844 """ 

845 Load a TrueType or OpenType font from a file or file-like object, 

846 and create a font object. This function loads a font object from the given 

847 file or file-like object, and creates a font object for a font of the given 

848 size. For loading bitmap fonts instead, see :py:func:`~PIL.ImageFont.load` 

849 and :py:func:`~PIL.ImageFont.load_path`. 

850 

851 Pillow uses FreeType to open font files. On Windows, be aware that FreeType 

852 will keep the file open as long as the FreeTypeFont object exists. Windows 

853 limits the number of files that can be open in C at once to 512, so if many 

854 fonts are opened simultaneously and that limit is approached, an 

855 ``OSError`` may be thrown, reporting that FreeType "cannot open resource". 

856 A workaround would be to copy the file(s) into memory, and open that instead. 

857 

858 This function requires the _imagingft service. 

859 

860 :param font: A filename or file-like object containing a TrueType font. 

861 If the file is not found in this filename, the loader may also 

862 search in other directories, such as: 

863 

864 * The :file:`fonts/` directory on Windows, 

865 * :file:`/Library/Fonts/`, :file:`/System/Library/Fonts/` 

866 and :file:`~/Library/Fonts/` on macOS. 

867 * :file:`~/.local/share/fonts`, :file:`/usr/local/share/fonts`, 

868 and :file:`/usr/share/fonts` on Linux; or those specified by 

869 the ``XDG_DATA_HOME`` and ``XDG_DATA_DIRS`` environment variables 

870 for user-installed and system-wide fonts, respectively. 

871 

872 :param size: The requested size, in pixels. 

873 :param index: Which font face to load (default is first available face). 

874 :param encoding: Which font encoding to use (default is Unicode). Possible 

875 encodings include (see the FreeType documentation for more 

876 information): 

877 

878 * "unic" (Unicode) 

879 * "symb" (Microsoft Symbol) 

880 * "ADOB" (Adobe Standard) 

881 * "ADBE" (Adobe Expert) 

882 * "ADBC" (Adobe Custom) 

883 * "armn" (Apple Roman) 

884 * "sjis" (Shift JIS) 

885 * "gb " (PRC) 

886 * "big5" 

887 * "wans" (Extended Wansung) 

888 * "joha" (Johab) 

889 * "lat1" (Latin-1) 

890 

891 This specifies the character set to use. It does not alter the 

892 encoding of any text provided in subsequent operations. 

893 :param layout_engine: Which layout engine to use, if available: 

894 :attr:`.ImageFont.Layout.BASIC` or :attr:`.ImageFont.Layout.RAQM`. 

895 If it is available, Raqm layout will be used by default. 

896 Otherwise, basic layout will be used. 

897 

898 Raqm layout is recommended for all non-English text. If Raqm layout 

899 is not required, basic layout will have better performance. 

900 

901 You can check support for Raqm layout using 

902 :py:func:`PIL.features.check_feature` with ``feature="raqm"``. 

903 

904 .. versionadded:: 4.2.0 

905 :return: A font object. 

906 :exception OSError: If the file could not be read. 

907 :exception ValueError: If the font size is not greater than zero. 

908 """ 

909 

910 def freetype(font: StrOrBytesPath | BinaryIO) -> FreeTypeFont: 

911 return FreeTypeFont(font, size, index, encoding, layout_engine) 

912 

913 try: 

914 return freetype(font) 

915 except OSError: 

916 if not is_path(font): 

917 raise 

918 ttf_filename = os.path.basename(font) 

919 

920 dirs = [] 

921 if sys.platform == "win32": 

922 # check the windows font repository 

923 # NOTE: must use uppercase WINDIR, to work around bugs in 

924 # 1.5.2's os.environ.get() 

925 windir = os.environ.get("WINDIR") 

926 if windir: 

927 dirs.append(os.path.join(windir, "fonts")) 

928 elif sys.platform in ("linux", "linux2"): 

929 data_home = os.environ.get("XDG_DATA_HOME") 

930 if not data_home: 

931 # The freedesktop spec defines the following default directory for 

932 # when XDG_DATA_HOME is unset or empty. This user-level directory 

933 # takes precedence over system-level directories. 

934 data_home = os.path.expanduser("~/.local/share") 

935 xdg_dirs = [data_home] 

936 

937 data_dirs = os.environ.get("XDG_DATA_DIRS") 

938 if not data_dirs: 

939 # Similarly, defaults are defined for the system-level directories 

940 data_dirs = "/usr/local/share:/usr/share" 

941 xdg_dirs += data_dirs.split(":") 

942 

943 dirs += [os.path.join(xdg_dir, "fonts") for xdg_dir in xdg_dirs] 

944 elif sys.platform == "darwin": 

945 dirs += [ 

946 "/Library/Fonts", 

947 "/System/Library/Fonts", 

948 os.path.expanduser("~/Library/Fonts"), 

949 ] 

950 

951 ext = os.path.splitext(ttf_filename)[1] 

952 first_font_with_a_different_extension = None 

953 for directory in dirs: 

954 for walkroot, walkdir, walkfilenames in os.walk(directory): 

955 for walkfilename in walkfilenames: 

956 if ext and walkfilename == ttf_filename: 

957 return freetype(os.path.join(walkroot, walkfilename)) 

958 elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename: 

959 fontpath = os.path.join(walkroot, walkfilename) 

960 if os.path.splitext(fontpath)[1] == ".ttf": 

961 return freetype(fontpath) 

962 if not ext and first_font_with_a_different_extension is None: 

963 first_font_with_a_different_extension = fontpath 

964 if first_font_with_a_different_extension: 

965 return freetype(first_font_with_a_different_extension) 

966 raise 

967 

968 

969def load_path(filename: StrOrBytesPath) -> ImageFont: 

970 """ 

971 Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a 

972 bitmap font along the Python path. 

973 

974 :param filename: Name of font file. 

975 :return: A font object. 

976 :exception OSError: If the file could not be read. 

977 """ 

978 filename = os.fsdecode(filename) 

979 for directory in sys.path: 

980 try: 

981 return load(os.path.join(directory, filename)) 

982 except OSError: 

983 pass 

984 msg = f'cannot find font file "{filename}" in sys.path' 

985 if os.path.exists(filename): 

986 msg += f', did you mean ImageFont.load("{filename}") instead?' 

987 

988 raise OSError(msg) 

989 

990 

991def load_default_imagefont() -> ImageFont: 

992 f = ImageFont() 

993 f._load_pilfont_data( 

994 # courB08 

995 BytesIO(base64.b64decode(b""" 

996UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

997AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

998AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

999AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1001AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1002AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1003AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1004AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1005AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1006AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1007AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA 

1008BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL 

1009AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA 

1010AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB 

1011ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A 

1012BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB 

1013//kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA 

1014AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH 

1015AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA 

1016ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv 

1017AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/ 

1018/gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5 

1019AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA 

1020AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG 

1021AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA 

1022BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA 

1023AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA 

10242AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF 

1025AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA//// 

1026+gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA 

1027////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA 

1028BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv 

1029AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA 

1030AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA 

1031AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA 

1032BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP// 

1033//kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA 

1034AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF 

1035AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB 

1036mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn 

1037AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA 

1038AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7 

1039AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA 

1040Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA 

1041AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1042AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1043AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1044AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1045AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1046AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1047AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1048AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1049AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1050AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1051AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1052AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB 

1053//sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA 

1054AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ 

1055AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC 

1056DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ 

1057AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/ 

1058+wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5 

1059AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/ 

1060///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG 

1061AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA 

1062BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA 

1063Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC 

1064eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG 

1065AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA//// 

1066+gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA 

1067////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA 

1068BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT 

1069AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A 

1070AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA 

1071Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA 

1072Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP// 

1073//cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA 

1074AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ 

1075AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA 

1076LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5 

1077AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA 

1078AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5 

1079AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA 

1080AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG 

1081AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA 

1082EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK 

1083AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA 

1084pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG 

1085AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA//// 

1086+QAGAAIAzgAKANUAEw== 

1087""")), 

1088 Image.open(BytesIO(base64.b64decode(b""" 

1089iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u 

1090Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9 

1091M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g 

1092LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F 

1093IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA 

1094Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791 

1095NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx 

1096in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9 

1097SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY 

1098AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt 

1099y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG 

1100ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY 

1101lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H 

1102/Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3 

1103AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47 

1104c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/ 

1105/yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw 

1106pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv 

1107oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR 

1108evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA 

1109AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v// 

1110Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR 

1111w7IkEbzhVQAAAABJRU5ErkJggg== 

1112"""))), 

1113 ) 

1114 return f 

1115 

1116 

1117def load_default(size: float | None = None) -> FreeTypeFont | ImageFont: 

1118 """If FreeType support is available, load a version of Aileron Regular, 

1119 https://dotcolon.net/fonts/aileron, with a more limited character set. 

1120 

1121 Otherwise, load a "better than nothing" font. 

1122 

1123 .. versionadded:: 1.1.4 

1124 

1125 :param size: The font size of Aileron Regular. 

1126 

1127 .. versionadded:: 10.1.0 

1128 

1129 :return: A font object. 

1130 """ 

1131 if isinstance(core, ModuleType) or size is not None: 

1132 return truetype( 

1133 BytesIO(base64.b64decode(b""" 

1134AAEAAAAPAIAAAwBwRkZUTYwDlUAAADFoAAAAHEdERUYAqADnAAAo8AAAACRHUE9ThhmITwAAKfgAA 

1135AduR1NVQnHxefoAACkUAAAA4k9TLzJovoHLAAABeAAAAGBjbWFw5lFQMQAAA6gAAAGqZ2FzcP//AA 

1136MAACjoAAAACGdseWYmRXoPAAAGQAAAHfhoZWFkE18ayQAAAPwAAAA2aGhlYQboArEAAAE0AAAAJGh 

1137tdHjjERZ8AAAB2AAAAdBsb2NhuOexrgAABVQAAADqbWF4cAC7AEYAAAFYAAAAIG5hbWUr+h5lAAAk 

1138OAAAA6Jwb3N0D3oPTQAAJ9wAAAEKAAEAAAABGhxJDqIhXw889QALA+gAAAAA0Bqf2QAAAADhCh2h/ 

11392r/LgOxAyAAAAAIAAIAAAAAAAAAAQAAA8r/GgAAA7j/av9qA7EAAQAAAAAAAAAAAAAAAAAAAHQAAQ 

1140AAAHQAQwAFAAAAAAACAAAAAQABAAAAQAAAAAAAAAADAfoBkAAFAAgCigJYAAAASwKKAlgAAAFeADI 

1141BPgAAAAAFAAAAAAAAAAAAAAcAAAAAAAAAAAAAAABVS1dOAEAAIPsCAwL/GgDIA8oA5iAAAJMAAAAA 

1142AhICsgAAACAAAwH0AAAAAAAAAU0AAADYAAAA8gA5AVMAVgJEAEYCRAA1AuQAKQKOAEAAsAArATsAZ 

1143AE7AB4CMABVAkQAUADc/+EBEgAgANwAJQEv//sCRAApAkQAggJEADwCRAAtAkQAIQJEADkCRAArAk 

1144QAMgJEACwCRAAxANwAJQDc/+ECRABnAkQAUAJEAEQB8wAjA1QANgJ/AB0CcwBkArsALwLFAGQCSwB 

1145kAjcAZALGAC8C2gBkAQgAZAIgADcCYQBkAj8AZANiAGQCzgBkAuEALwJWAGQC3QAvAmsAZAJJADQC 

1146ZAAiAqoAXgJuACADuAAaAnEAGQJFABMCTwAuATMAYgEv//sBJwAiAkQAUAH0ADIBLAApAhMAJAJjA 

1147EoCEQAeAmcAHgIlAB4BIgAVAmcAHgJRAEoA7gA+AOn/8wIKAEoA9wBGA1cASgJRAEoCSgAeAmMASg 

1148JnAB4BSgBKAcsAGAE5ABQCUABCAgIAAQMRAAEB4v/6AgEAAQHOABQBLwBAAPoAYAEvACECRABNA0Y 

1149AJAItAHgBKgAcAkQAUAEsAHQAygAgAi0AOQD3ADYA9wAWAaEANgGhABYCbAAlAYMAeAGDADkA6/9q 

1150AhsAFAIKABUB/QAVAAAAAwAAAAMAAAAcAAEAAAAAAKQAAwABAAAAHAAEAIgAAAAeABAAAwAOAH4Aq 

1151QCrALEAtAC3ALsgGSAdICYgOiBEISL7Av//AAAAIACpAKsAsAC0ALcAuyAYIBwgJiA5IEQhIvsB// 

1152//4/+5/7j/tP+y/7D/reBR4E/gR+A14CzfTwVxAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1153AAAAAAAEGAAABAAAAAAAAAAECAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAMEBQYHCAkKCwwNDg8QERIT 

1154FBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMT 

1155U5PUFFSU1RVVldYWVpbXF1eX2BhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAA 

1156AAAAAAYnFmAAAAAABlAAAAAAAAAAAAAAAAAAAAAAAAAAAAY2htAAAAAAAAAABrbGlqAAAAAHAAbm9 

1157ycwBnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmACYAJgAmAD4AUgCCAMoBCgFO 

1158AVwBcgGIAaYBvAHKAdYB6AH2AgwCIAJKAogCpgLWAw4DIgNkA5wDugPUA+gD/AQQBEYEogS8BPoFJ 

1159gVSBWoFgAWwBcoF1gX6BhQGJAZMBmgGiga0BuIHGgdUB2YHkAeiB8AH3AfyCAoIHAgqCDoITghcCG 

1160oIogjSCPoJKglYCXwJwgnqCgIKKApACl4Klgq8CtwLDAs8C1YLjAuyC9oL7gwMDCYMSAxgDKAMrAz 

1161qDQoNTA1mDYQNoA2uDcAN2g3oDfYODA4iDkoOXA5sDnoOnA7EDvwAAAAFAAAAAAH0ArwAAwAGAAkA 

1162DAAPAAAxESERAxMhExcRASELARETAfT6qv6syKr+jgFUqsiqArz9RAGLAP/+1P8B/v3VAP8BLP4CA 

1163P8AAgA5//IAuQKyAAMACwAANyMDMwIyFhQGIiY0oE4MZk84JCQ4JLQB/v3AJDgkJDgAAgBWAeUBPA 

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 

1209vArIACwAAJRUhESEVIRUhFSEVAi/+NQHB/pUBTf6zRkYCskbwRvAAAAABAGQAAAIlArIACQAAExUh 

1210FSERIxEhFboBQ/69VgHBAmzwRv7KArJGAAAAAAEAL//yAo8CwAAfAAABMxEjNQcGIyImNTQ2MzIWH 

1211wEjJyYjIgYVFBYzMjY1IwGP90wfPnWTprSSf48LAVYCIqJofHllVG+hAU3+s3hARsicn8uAagoKpq 

1212N/gaN1XAAAAAEAZAAAAowCsgALAAABESMRIREjETMRIRECjFb+hFZWAXwCsv1OAS7+0gKy/sQBPAA 

1213AAAABAGQAAAC6ArIAAwAAMyMRM7pWVgKyAAABADf/8gHoArIAEwAAAREUBw4BIyImLwEzFxYzMjc2 

1214NREB6AIFcGpgbQIBVgIHfXQKAQKy/lYxIltob2EpKYyEFD0BpwAAAAABAGQAAAJ0ArIACwAACQEjA 

1215wcVIxEzEQEzATsBJ3ntQlZWAVVlAWH+nwEnR+ACsv6RAW8AAQBkAAACLwKyAAUAACUVIREzEQIv/j 

1216VWRkYCsv2UAAABAGQAAAMUArIAFAAAAREjETQ3BgcDIwMmJxYVESMRMxsBAxRWAiMxemx8NxsCVo7 

1217MywKy/U4BY7ZLco7+nAFmoFxLtP6dArL9lwJpAAAAAAEAZAAAAoACsgANAAAhIwEWFREjETMBJjUR 

1218MwKAhP67A1aEAUUDVAJeeov+pwKy/aJ5jAFZAAAAAgAv//ICuwLAAAkAEwAAEiAWFRQGICY1NBIyN 

1219jU0JiIGFRTbATSsrP7MrNrYenrYegLAxaKhxsahov47nIeIm5uIhwACAGQAAAJHArIADgAYAAABHg 

1220EVFAYHBisBESMRMzITNjQnJisBETMyAZRUX2VOHzuAVtY7GlxcGDWIiDUCrgtnVlVpCgT+5gKy/rU 

1221V1BUF/vgAAAACAC//zAK9AsAAEgAcAAAlFhcHJiMiBwYjIiY1NDYgFhUUJRQWMjY1NCYiBgI9PUMx 

1222UDcfKh8omqysATSs/dR62Hp62HpICTg7NgkHxqGixcWitbWHnJyHiJubAAIAZAAAAlgCsgAXACMAA 

1223CUWFyMmJyYnJisBESMRMzIXHgEVFAYHFiUzMjc+ATU0JyYrAQIqDCJfGQwNWhAhglbiOx9QXEY1Tv 

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 

1299gQAAwABBAkADAAuAkwATgBvACAAUgBpAGcAaAB0AHMAIABSAGUAcwBlAHIAdgBlAGQALgAATm8gUm 

1300lnaHRzIFJlc2VydmVkLgAAQQBpAGwAZQByAG8AbgAAQWlsZXJvbgAAUgBlAGcAdQBsAGEAcgAAUmV 

1301ndWxhcgAAMQAuADEAMAAyADsAVQBLAFcATgA7AEEAaQBsAGUAcgBvAG4ALQBSAGUAZwB1AGwAYQBy 

1302AAAxLjEwMjtVS1dOO0FpbGVyb24tUmVndWxhcgAAQQBpAGwAZQByAG8AbgAAQWlsZXJvbgAAVgBlA 

1303HIAcwBpAG8AbgAgADEALgAxADAAMgA7AFAAUwAgADAAMAAxAC4AMQAwADIAOwBoAG8AdABjAG8Abg 

1304B2ACAAMQAuADAALgA3ADAAOwBtAGEAawBlAG8AdABmAC4AbABpAGIAMgAuADUALgA1ADgAMwAyADk 

1305AAFZlcnNpb24gMS4xMDI7UFMgMDAxLjEwMjtob3Rjb252IDEuMC43MDttYWtlb3RmLmxpYjIuNS41 

1306ODMyOQAAQQBpAGwAZQByAG8AbgAtAFIAZQBnAHUAbABhAHIAAEFpbGVyb24tUmVndWxhcgAAUwBvA 

1307HIAYQAgAFMAYQBnAGEAbgBvAABTb3JhIFNhZ2FubwAAUwBvAHIAYQAgAFMAYQBnAGEAbgBvAABTb3 

1308JhIFNhZ2FubwAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBsAG8AbgAuAG4AZQB0AAB 

1309odHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBs 

1310AG8AbgAuAG4AZQB0AABodHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAAAACAAAAAAAA/4MAMgAAAAAAA 

1311AAAAAAAAAAAAAAAAAAAAHQAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATAB 

1312QAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAA 

1313xADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0A 

1314TgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAIsAqQCDAJMAjQDDAKoAtgC3A 

1315LQAtQCrAL4AvwC8AIwAwADBAAAAAAAB//8AAgABAAAADAAAABwAAAACAAIAAwBxAAEAcgBzAAIABA 

1316AAAAIAAAABAAAACgBMAGYAAkRGTFQADmxhdG4AGgAEAAAAAP//AAEAAAAWAANDQVQgAB5NT0wgABZ 

1317ST00gABYAAP//AAEAAAAA//8AAgAAAAEAAmxpZ2EADmxvY2wAFAAAAAEAAQAAAAEAAAACAAYAEAAG 

1318AAAAAgASADQABAAAAAEATAADAAAAAgAQABYAAQAcAAAAAQABAE8AAQABAGcAAQABAE8AAwAAAAIAE 

1319AAWAAEAHAAAAAEAAQAvAAEAAQBnAAEAAQAvAAEAGgABAAgAAgAGAAwAcwACAE8AcgACAEwAAQABAE 

1320kAAAABAAAACgBGAGAAAkRGTFQADmxhdG4AHAAEAAAAAP//AAIAAAABABYAA0NBVCAAFk1PTCAAFlJ 

1321PTSAAFgAA//8AAgAAAAEAAmNwc3AADmtlcm4AFAAAAAEAAAAAAAEAAQACAAYADgABAAAAAQASAAIA 

1322AAACAB4ANgABAAoABQAFAAoAAgABACQAPQAAAAEAEgAEAAAAAQAMAAEAOP/nAAEAAQAkAAIGigAEA 

1323AAFJAXKABoAGQAA//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1324AAAAD/sv+4/+z/7v/MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1325AAAAAAAD/xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9T/6AAAAAD/8QAA 

1326ABD/vQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7gAAAAAAAAAAAAAAAAAA//MAA 

1327AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAP/5AAAAAAAAAA 

1328AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAD/4AAAAAAAAAAAAAAAAAA 

1329AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//L/9AAAAAAAAAAAAAAAAAAAAAAA 

1330AAAAAAAAAAAA/+gAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1331AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/zAAAAAA 

1332AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/mAAAAAAAAAAAAAAAAAAD 

1333/4gAA//AAAAAA//YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+AAAAAAAAP/OAAAAAAAAAAAAAAAA 

1334AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/zv/qAAAAAP/0AAAACAAAAAAAAAAAAAAAAAAAAAAAA 

1335AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/ZAAD/egAA/1kAAAAA/5D/rgAAAAAAAAAAAA 

1336AAAAAAAAAAAAAAAAD/9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1337AAAAAAAAAAAAAAAAAAAD/8AAA/7b/8P+wAAD/8P/E/98AAAAA/8P/+P/0//oAAAAAAAAAAAAA//gA 

1338AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+AAAAAAAAAAAAAAA 

1339AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/w//C/9MAAP/SAAD/9wAAAAAAAA 

1340AAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yAAA/+kAAAAA//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1341AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9wAAAAD//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1342AAAAAAAAAAAAAAAAAAAAAP/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1343AAAAAAAAP/cAAAAAAAAAAAAAAAA/7YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1344AAAAAAAAAAAAAAAAAAAAAAAAAAAP/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/6AAAAAAAAAA 

1345AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAkAFAAEAAAAAQACwAAABcA 

1346BgAAAAAAAAAIAA4AAAAAAAsAEgAAAAAAAAATABkAAwANAAAAAQAJAAAAAAAAAAAAAAAAAAAAGAAAA 

1347AAABwAAAAAAAAAAAAAAFQAFAAAAAAAYABgAAAAUAAAACgAAAAwAAgAPABEAFgAAAAAAAAAAAAAAAA 

1348AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAEAEQBdAAYAAAAAAAAAAAAAAAAAAAAAAAA 

1349AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAAAAAABwAAAAAACAAAAAAAAAAAAAcAAAAHAAAAEwAJ 

1350ABUADgAPAAAACwAQAAAAAAAAAAAAAAAAAAUAGAACAAIAAgAAAAIAGAAXAAAAGAAAABYAFgACABYAA 

1351gAWAAAAEQADAAoAFAAMAA0ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAEgAGAAEAHgAkAC 

1352YAJwApACoALQAuAC8AMgAzADcAOAA5ADoAPAA9AEUASABOAE8AUgBTAFUAVwBZAFoAWwBcAF0AcwA 

1353AAAAAAQAAAADa3tfFAAAAANAan9kAAAAA4QodoQ== 

1354""")), 

1355 10 if size is None else size, 

1356 layout_engine=Layout.BASIC, 

1357 ) 

1358 return load_default_imagefont()