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

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

279 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 

30import base64 

31import os 

32import sys 

33import warnings 

34from enum import IntEnum 

35from io import BytesIO 

36from types import ModuleType 

37from typing import IO, Any, BinaryIO, TypedDict, cast 

38 

39from . import Image 

40from ._typing import StrOrBytesPath 

41from ._util import DeferredError, is_path 

42 

43TYPE_CHECKING = False 

44if TYPE_CHECKING: 

45 from . import ImageFile 

46 from ._imaging import ImagingFont 

47 from ._imagingft import Font 

48 

49 

50class Axis(TypedDict): 

51 minimum: int | None 

52 default: int | None 

53 maximum: int | None 

54 name: bytes | None 

55 

56 

57class Layout(IntEnum): 

58 BASIC = 0 

59 RAQM = 1 

60 

61 

62MAX_STRING_LENGTH = 1_000_000 

63 

64 

65core: ModuleType | DeferredError 

66try: 

67 from . import _imagingft as core 

68except ImportError as ex: 

69 core = DeferredError.new(ex) 

70 

71 

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

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

74 msg = "too many characters in string" 

75 raise ValueError(msg) 

76 

77 

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

79 

80# -------------------------------------------------------------------- 

81# Font metrics format: 

82# "PILfont" LF 

83# fontdescriptor LF 

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

85# "DATA" LF 

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

87# 

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

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

90# position according to dx, dy. 

91# -------------------------------------------------------------------- 

92 

93 

94class ImageFont: 

95 """PIL font wrapper""" 

96 

97 font: ImagingFont 

98 

99 def _load_pilfont(self, filename: str) -> None: 

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

101 image: ImageFile.ImageFile | None = None 

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

103 

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

105 if image: 

106 image.close() 

107 try: 

108 fullname = root + ext 

109 image = Image.open(fullname) 

110 except Exception: 

111 pass 

112 else: 

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

114 break 

115 else: 

116 if image: 

117 image.close() 

118 

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

120 raise OSError(msg) 

121 

122 self.file = fullname 

123 

124 self._load_pilfont_data(fp, image) 

125 image.close() 

126 

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

128 # read PILfont header 

129 if file.readline() != b"PILfont\n": 

130 msg = "Not a PILfont file" 

131 raise SyntaxError(msg) 

132 file.readline().split(b";") 

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

134 while True: 

135 s = file.readline() 

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

137 break 

138 self.info.append(s) 

139 

140 # read PILfont metrics 

141 data = file.read(256 * 20) 

142 

143 # check image 

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

145 msg = "invalid font image mode" 

146 raise TypeError(msg) 

147 

148 image.load() 

149 

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

151 

152 def getmask( 

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

154 ) -> Image.core.ImagingCore: 

155 """ 

156 Create a bitmap for the text. 

157 

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

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

160 

161 :param text: Text to render. 

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

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

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

165 C-level implementations. 

166 

167 .. versionadded:: 1.1.5 

168 

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

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

171 """ 

172 _string_length_check(text) 

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

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

175 

176 def getbbox( 

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

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

179 """ 

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

181 

182 .. versionadded:: 9.2.0 

183 

184 :param text: Text to render. 

185 

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

187 """ 

188 _string_length_check(text) 

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

190 return 0, 0, width, height 

191 

192 def getlength( 

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

194 ) -> int: 

195 """ 

196 Returns length (in pixels) of given text. 

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

198 

199 .. versionadded:: 9.2.0 

200 """ 

201 _string_length_check(text) 

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

203 return width 

204 

205 

206## 

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

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

209 

210 

211class FreeTypeFont: 

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

213 

214 font: Font 

215 font_bytes: bytes 

216 

217 def __init__( 

218 self, 

219 font: StrOrBytesPath | BinaryIO, 

220 size: float = 10, 

221 index: int = 0, 

222 encoding: str = "", 

223 layout_engine: Layout | None = None, 

224 ) -> None: 

225 # FIXME: use service provider instead 

226 

227 if isinstance(core, DeferredError): 

228 raise core.ex 

229 

230 if size <= 0: 

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

232 raise ValueError(msg) 

233 

234 self.path = font 

235 self.size = size 

236 self.index = index 

237 self.encoding = encoding 

238 

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

240 layout_engine = Layout.BASIC 

241 if core.HAVE_RAQM: 

242 layout_engine = Layout.RAQM 

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

244 warnings.warn( 

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

246 "Falling back to basic layout." 

247 ) 

248 layout_engine = Layout.BASIC 

249 

250 self.layout_engine = layout_engine 

251 

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

253 self.font_bytes = f.read() 

254 self.font = core.getfont( 

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

256 ) 

257 

258 if is_path(font): 

259 font = os.fspath(font) 

260 if sys.platform == "win32": 

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

262 try: 

263 font_bytes_path.decode("ascii") 

264 except UnicodeDecodeError: 

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

266 # So load it into memory first 

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

268 load_from_bytes(f) 

269 return 

270 self.font = core.getfont( 

271 font, size, index, encoding, layout_engine=layout_engine 

272 ) 

273 else: 

274 load_from_bytes(cast(IO[bytes], font)) 

275 

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

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

278 

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

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

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

282 

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

284 """ 

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

286 (e.g. Bold) 

287 """ 

288 return self.font.family, self.font.style 

289 

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

291 """ 

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

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

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

295 """ 

296 return self.font.ascent, self.font.descent 

297 

298 def getlength( 

299 self, 

300 text: str | bytes, 

301 mode: str = "", 

302 direction: str | None = None, 

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

304 language: str | None = None, 

305 ) -> float: 

306 """ 

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

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

309 

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

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

312 e.g. when using italics or accents. 

313 

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

315 

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

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

318 character and subtract its length. 

319 

320 For example, instead of :: 

321 

322 hello = font.getlength("Hello") 

323 world = font.getlength("World") 

324 hello_world = hello + world # not adjusted for kerning 

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

326 

327 use :: 

328 

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

330 world = font.getlength("World") 

331 hello_world = hello + world # adjusted for kerning 

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

333 

334 or disable kerning with (requires libraqm) :: 

335 

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

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

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

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

340 

341 .. versionadded:: 8.0.0 

342 

343 :param text: Text to measure. 

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

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

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

347 C-level implementations. 

348 

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

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

351 Requires libraqm. 

352 

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

354 layout. This is usually used to turn on optional 

355 font features that are not enabled by default, 

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

357 used to turn off default font features for 

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

359 to disable kerning. To get all supported 

360 features, see 

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

362 Requires libraqm. 

363 

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

365 different glyph shapes or ligatures. This parameter tells 

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

367 correct substitutions as appropriate, if available. 

368 It should be a `BCP 47 language code 

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

370 Requires libraqm. 

371 

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

373 """ 

374 _string_length_check(text) 

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

376 

377 def getbbox( 

378 self, 

379 text: str | bytes, 

380 mode: str = "", 

381 direction: str | None = None, 

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

383 language: str | None = None, 

384 stroke_width: float = 0, 

385 anchor: str | None = None, 

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

387 """ 

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

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

390 

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

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

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

394 

395 .. versionadded:: 8.0.0 

396 

397 :param text: Text to render. 

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

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

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

401 C-level implementations. 

402 

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

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

405 Requires libraqm. 

406 

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

408 layout. This is usually used to turn on optional 

409 font features that are not enabled by default, 

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

411 used to turn off default font features for 

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

413 to disable kerning. To get all supported 

414 features, see 

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

416 Requires libraqm. 

417 

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

419 different glyph shapes or ligatures. This parameter tells 

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

421 correct substitutions as appropriate, if available. 

422 It should be a `BCP 47 language code 

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

424 Requires libraqm. 

425 

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

427 

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

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

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

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

432 

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

434 """ 

435 _string_length_check(text) 

436 size, offset = self.font.getsize( 

437 text, mode, direction, features, language, anchor 

438 ) 

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

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

441 return left, top, left + width, top + height 

442 

443 def getmask( 

444 self, 

445 text: str | bytes, 

446 mode: str = "", 

447 direction: str | None = None, 

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

449 language: str | None = None, 

450 stroke_width: float = 0, 

451 anchor: str | None = None, 

452 ink: int = 0, 

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

454 ) -> Image.core.ImagingCore: 

455 """ 

456 Create a bitmap for the text. 

457 

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

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

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

461 

462 :param text: Text to render. 

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

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

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

466 C-level implementations. 

467 

468 .. versionadded:: 1.1.5 

469 

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

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

472 Requires libraqm. 

473 

474 .. versionadded:: 4.2.0 

475 

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

477 layout. This is usually used to turn on optional 

478 font features that are not enabled by default, 

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

480 used to turn off default font features for 

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

482 to disable kerning. To get all supported 

483 features, see 

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

485 Requires libraqm. 

486 

487 .. versionadded:: 4.2.0 

488 

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

490 different glyph shapes or ligatures. This parameter tells 

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

492 correct substitutions as appropriate, if available. 

493 It should be a `BCP 47 language code 

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

495 Requires libraqm. 

496 

497 .. versionadded:: 6.0.0 

498 

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

500 

501 .. versionadded:: 6.2.0 

502 

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

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

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

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

507 

508 .. versionadded:: 8.0.0 

509 

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

511 

512 .. versionadded:: 8.0.0 

513 

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

515 differently when starting at fractional coordinates. 

516 

517 .. versionadded:: 9.4.0 

518 

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

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

521 """ 

522 return self.getmask2( 

523 text, 

524 mode, 

525 direction=direction, 

526 features=features, 

527 language=language, 

528 stroke_width=stroke_width, 

529 anchor=anchor, 

530 ink=ink, 

531 start=start, 

532 )[0] 

533 

534 def getmask2( 

535 self, 

536 text: str | bytes, 

537 mode: str = "", 

538 direction: str | None = None, 

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

540 language: str | None = None, 

541 stroke_width: float = 0, 

542 anchor: str | None = None, 

543 ink: int = 0, 

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

545 *args: Any, 

546 **kwargs: Any, 

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

548 """ 

549 Create a bitmap for the text. 

550 

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

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

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

554 

555 :param text: Text to render. 

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

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

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

559 C-level implementations. 

560 

561 .. versionadded:: 1.1.5 

562 

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

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

565 Requires libraqm. 

566 

567 .. versionadded:: 4.2.0 

568 

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

570 layout. This is usually used to turn on optional 

571 font features that are not enabled by default, 

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

573 used to turn off default font features for 

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

575 to disable kerning. To get all supported 

576 features, see 

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

578 Requires libraqm. 

579 

580 .. versionadded:: 4.2.0 

581 

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

583 different glyph shapes or ligatures. This parameter tells 

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

585 correct substitutions as appropriate, if available. 

586 It should be a `BCP 47 language code 

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

588 Requires libraqm. 

589 

590 .. versionadded:: 6.0.0 

591 

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

593 

594 .. versionadded:: 6.2.0 

595 

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

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

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

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

600 

601 .. versionadded:: 8.0.0 

602 

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

604 

605 .. versionadded:: 8.0.0 

606 

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

608 differently when starting at fractional coordinates. 

609 

610 .. versionadded:: 9.4.0 

611 

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

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

614 gap between the starting coordinate and the first marking 

615 """ 

616 _string_length_check(text) 

617 if start is None: 

618 start = (0, 0) 

619 

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

621 size = (width, height) 

622 Image._decompression_bomb_check(size) 

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

624 

625 return self.font.render( 

626 text, 

627 fill, 

628 mode, 

629 direction, 

630 features, 

631 language, 

632 stroke_width, 

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

634 anchor, 

635 ink, 

636 start, 

637 ) 

638 

639 def font_variant( 

640 self, 

641 font: StrOrBytesPath | BinaryIO | None = None, 

642 size: float | None = None, 

643 index: int | None = None, 

644 encoding: str | None = None, 

645 layout_engine: Layout | None = None, 

646 ) -> FreeTypeFont: 

647 """ 

648 Create a copy of this FreeTypeFont object, 

649 using any specified arguments to override the settings. 

650 

651 Parameters are identical to the parameters used to initialize this 

652 object. 

653 

654 :return: A FreeTypeFont object. 

655 """ 

656 if font is None: 

657 try: 

658 font = BytesIO(self.font_bytes) 

659 except AttributeError: 

660 font = self.path 

661 return FreeTypeFont( 

662 font=font, 

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

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

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

666 layout_engine=layout_engine or self.layout_engine, 

667 ) 

668 

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

670 """ 

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

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

673 """ 

674 try: 

675 names = self.font.getvarnames() 

676 except AttributeError as e: 

677 msg = "FreeType 2.9.1 or greater is required" 

678 raise NotImplementedError(msg) from e 

679 return [name.replace(b"\x00", b"") for name in names] 

680 

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

682 """ 

683 :param name: The name of the style. 

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

685 """ 

686 names = self.get_variation_names() 

687 if not isinstance(name, bytes): 

688 name = name.encode() 

689 index = names.index(name) + 1 

690 

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

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

693 # there is an 'unknown freetype error' 

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

695 return 

696 self._last_variation_index = index 

697 

698 self.font.setvarname(index) 

699 

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

701 """ 

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

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

704 """ 

705 try: 

706 axes = self.font.getvaraxes() 

707 except AttributeError as e: 

708 msg = "FreeType 2.9.1 or greater is required" 

709 raise NotImplementedError(msg) from e 

710 for axis in axes: 

711 if axis["name"]: 

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

713 return axes 

714 

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

716 """ 

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

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

719 """ 

720 try: 

721 self.font.setvaraxes(axes) 

722 except AttributeError as e: 

723 msg = "FreeType 2.9.1 or greater is required" 

724 raise NotImplementedError(msg) from e 

725 

726 

727class TransposedFont: 

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

729 

730 def __init__( 

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

732 ): 

733 """ 

734 Wrapper that creates a transposed font from any existing font 

735 object. 

736 

737 :param font: A font object. 

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

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

740 Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_180, or 

741 Image.Transpose.ROTATE_270. 

742 """ 

743 self.font = font 

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

745 

746 def getmask( 

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

748 ) -> Image.core.ImagingCore: 

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

750 if self.orientation is not None: 

751 return im.transpose(self.orientation) 

752 return im 

753 

754 def getbbox( 

755 self, text: str | bytes, *args: Any, **kwargs: Any 

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

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

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

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

760 width = right - left 

761 height = bottom - top 

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

763 return 0, 0, height, width 

764 return 0, 0, width, height 

765 

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

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

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

769 raise ValueError(msg) 

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

771 

772 

773def load(filename: str) -> ImageFont: 

774 """ 

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

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

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

778 

779 :param filename: Name of font file. 

780 :return: A font object. 

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

782 """ 

783 f = ImageFont() 

784 f._load_pilfont(filename) 

785 return f 

786 

787 

788def truetype( 

789 font: StrOrBytesPath | BinaryIO, 

790 size: float = 10, 

791 index: int = 0, 

792 encoding: str = "", 

793 layout_engine: Layout | None = None, 

794) -> FreeTypeFont: 

795 """ 

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

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

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

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

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

801 

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

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

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

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

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

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

808 

809 This function requires the _imagingft service. 

810 

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

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

813 search in other directories, such as: 

814 

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

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

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

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

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

820 the ``XDG_DATA_HOME`` and ``XDG_DATA_DIRS`` environment variables 

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

822 

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

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

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

826 encodings include (see the FreeType documentation for more 

827 information): 

828 

829 * "unic" (Unicode) 

830 * "symb" (Microsoft Symbol) 

831 * "ADOB" (Adobe Standard) 

832 * "ADBE" (Adobe Expert) 

833 * "ADBC" (Adobe Custom) 

834 * "armn" (Apple Roman) 

835 * "sjis" (Shift JIS) 

836 * "gb " (PRC) 

837 * "big5" 

838 * "wans" (Extended Wansung) 

839 * "joha" (Johab) 

840 * "lat1" (Latin-1) 

841 

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

843 encoding of any text provided in subsequent operations. 

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

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

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

847 Otherwise, basic layout will be used. 

848 

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

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

851 

852 You can check support for Raqm layout using 

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

854 

855 .. versionadded:: 4.2.0 

856 :return: A font object. 

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

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

859 """ 

860 

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

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

863 

864 try: 

865 return freetype(font) 

866 except OSError: 

867 if not is_path(font): 

868 raise 

869 ttf_filename = os.path.basename(font) 

870 

871 dirs = [] 

872 if sys.platform == "win32": 

873 # check the windows font repository 

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

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

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

877 if windir: 

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

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

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

881 if not data_home: 

882 # The freedesktop spec defines the following default directory for 

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

884 # takes precedence over system-level directories. 

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

886 xdg_dirs = [data_home] 

887 

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

889 if not data_dirs: 

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

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

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

893 

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

895 elif sys.platform == "darwin": 

896 dirs += [ 

897 "/Library/Fonts", 

898 "/System/Library/Fonts", 

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

900 ] 

901 

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

903 first_font_with_a_different_extension = None 

904 for directory in dirs: 

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

906 for walkfilename in walkfilenames: 

907 if ext and walkfilename == ttf_filename: 

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

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

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

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

912 return freetype(fontpath) 

913 if not ext and first_font_with_a_different_extension is None: 

914 first_font_with_a_different_extension = fontpath 

915 if first_font_with_a_different_extension: 

916 return freetype(first_font_with_a_different_extension) 

917 raise 

918 

919 

920def load_path(filename: str | bytes) -> ImageFont: 

921 """ 

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

923 bitmap font along the Python path. 

924 

925 :param filename: Name of font file. 

926 :return: A font object. 

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

928 """ 

929 if not isinstance(filename, str): 

930 filename = filename.decode("utf-8") 

931 for directory in sys.path: 

932 try: 

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

934 except OSError: 

935 pass 

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

937 if os.path.exists(filename): 

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

939 

940 raise OSError(msg) 

941 

942 

943def load_default_imagefont() -> ImageFont: 

944 f = ImageFont() 

945 f._load_pilfont_data( 

946 # courB08 

947 BytesIO( 

948 base64.b64decode( 

949 b""" 

950UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

951AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

952AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

953AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

954AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

955AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

956AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

957AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

958AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

959AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

960AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

961AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA 

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

963AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA 

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

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

966BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB 

967//kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA 

968AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH 

969AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA 

970ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv 

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

972/gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5 

973AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA 

974AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG 

975AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA 

976BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA 

977AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA 

9782AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF 

979AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA//// 

980+gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA 

981////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA 

982BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv 

983AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA 

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

985AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA 

986BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP// 

987//kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA 

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

989AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB 

990mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn 

991AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA 

992AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7 

993AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA 

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

995AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

996AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

997AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

998AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

999AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1001AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1002AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1003AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1004AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1005AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1006AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB 

1007//sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA 

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

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

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

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

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

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

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

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

1016BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA 

1017Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC 

1018eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG 

1019AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA//// 

1020+gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA 

1021////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA 

1022BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT 

1023AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A 

1024AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA 

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

1026Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP// 

1027//cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA 

1028AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ 

1029AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA 

1030LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5 

1031AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA 

1032AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5 

1033AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA 

1034AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG 

1035AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA 

1036EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK 

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

1038pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG 

1039AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA//// 

1040+QAGAAIAzgAKANUAEw== 

1041""" 

1042 ) 

1043 ), 

1044 Image.open( 

1045 BytesIO( 

1046 base64.b64decode( 

1047 b""" 

1048iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u 

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

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

1051LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F 

1052IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA 

1053Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791 

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

1055in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9 

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

1057AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt 

1058y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG 

1059ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY 

1060lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H 

1061/Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3 

1062AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47 

1063c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/ 

1064/yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw 

1065pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv 

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

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

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

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

1070w7IkEbzhVQAAAABJRU5ErkJggg== 

1071""" 

1072 ) 

1073 ) 

1074 ), 

1075 ) 

1076 return f 

1077 

1078 

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

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

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

1082 

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

1084 

1085 .. versionadded:: 1.1.4 

1086 

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

1088 

1089 .. versionadded:: 10.1.0 

1090 

1091 :return: A font object. 

1092 """ 

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

1094 return truetype( 

1095 BytesIO( 

1096 base64.b64decode( 

1097 b""" 

1098AAEAAAAPAIAAAwBwRkZUTYwDlUAAADFoAAAAHEdERUYAqADnAAAo8AAAACRHUE9ThhmITwAAKfgAA 

1099AduR1NVQnHxefoAACkUAAAA4k9TLzJovoHLAAABeAAAAGBjbWFw5lFQMQAAA6gAAAGqZ2FzcP//AA 

1100MAACjoAAAACGdseWYmRXoPAAAGQAAAHfhoZWFkE18ayQAAAPwAAAA2aGhlYQboArEAAAE0AAAAJGh 

1101tdHjjERZ8AAAB2AAAAdBsb2NhuOexrgAABVQAAADqbWF4cAC7AEYAAAFYAAAAIG5hbWUr+h5lAAAk 

1102OAAAA6Jwb3N0D3oPTQAAJ9wAAAEKAAEAAAABGhxJDqIhXw889QALA+gAAAAA0Bqf2QAAAADhCh2h/ 

11032r/LgOxAyAAAAAIAAIAAAAAAAAAAQAAA8r/GgAAA7j/av9qA7EAAQAAAAAAAAAAAAAAAAAAAHQAAQ 

1104AAAHQAQwAFAAAAAAACAAAAAQABAAAAQAAAAAAAAAADAfoBkAAFAAgCigJYAAAASwKKAlgAAAFeADI 

1105BPgAAAAAFAAAAAAAAAAAAAAcAAAAAAAAAAAAAAABVS1dOAEAAIPsCAwL/GgDIA8oA5iAAAJMAAAAA 

1106AhICsgAAACAAAwH0AAAAAAAAAU0AAADYAAAA8gA5AVMAVgJEAEYCRAA1AuQAKQKOAEAAsAArATsAZ 

1107AE7AB4CMABVAkQAUADc/+EBEgAgANwAJQEv//sCRAApAkQAggJEADwCRAAtAkQAIQJEADkCRAArAk 

1108QAMgJEACwCRAAxANwAJQDc/+ECRABnAkQAUAJEAEQB8wAjA1QANgJ/AB0CcwBkArsALwLFAGQCSwB 

1109kAjcAZALGAC8C2gBkAQgAZAIgADcCYQBkAj8AZANiAGQCzgBkAuEALwJWAGQC3QAvAmsAZAJJADQC 

1110ZAAiAqoAXgJuACADuAAaAnEAGQJFABMCTwAuATMAYgEv//sBJwAiAkQAUAH0ADIBLAApAhMAJAJjA 

1111EoCEQAeAmcAHgIlAB4BIgAVAmcAHgJRAEoA7gA+AOn/8wIKAEoA9wBGA1cASgJRAEoCSgAeAmMASg 

1112JnAB4BSgBKAcsAGAE5ABQCUABCAgIAAQMRAAEB4v/6AgEAAQHOABQBLwBAAPoAYAEvACECRABNA0Y 

1113AJAItAHgBKgAcAkQAUAEsAHQAygAgAi0AOQD3ADYA9wAWAaEANgGhABYCbAAlAYMAeAGDADkA6/9q 

1114AhsAFAIKABUB/QAVAAAAAwAAAAMAAAAcAAEAAAAAAKQAAwABAAAAHAAEAIgAAAAeABAAAwAOAH4Aq 

1115QCrALEAtAC3ALsgGSAdICYgOiBEISL7Av//AAAAIACpAKsAsAC0ALcAuyAYIBwgJiA5IEQhIvsB// 

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

1117AAAAAAAEGAAABAAAAAAAAAAECAAAAAgAAAAAAAAAAAAAAAAAAAAEAAAMEBQYHCAkKCwwNDg8QERIT 

1118FBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMT 

1119U5PUFFSU1RVVldYWVpbXF1eX2BhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAA 

1120AAAAAAYnFmAAAAAABlAAAAAAAAAAAAAAAAAAAAAAAAAAAAY2htAAAAAAAAAABrbGlqAAAAAHAAbm9 

1121ycwBnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmACYAJgAmAD4AUgCCAMoBCgFO 

1122AVwBcgGIAaYBvAHKAdYB6AH2AgwCIAJKAogCpgLWAw4DIgNkA5wDugPUA+gD/AQQBEYEogS8BPoFJ 

1123gVSBWoFgAWwBcoF1gX6BhQGJAZMBmgGiga0BuIHGgdUB2YHkAeiB8AH3AfyCAoIHAgqCDoITghcCG 

1124oIogjSCPoJKglYCXwJwgnqCgIKKApACl4Klgq8CtwLDAs8C1YLjAuyC9oL7gwMDCYMSAxgDKAMrAz 

1125qDQoNTA1mDYQNoA2uDcAN2g3oDfYODA4iDkoOXA5sDnoOnA7EDvwAAAAFAAAAAAH0ArwAAwAGAAkA 

1126DAAPAAAxESERAxMhExcRASELARETAfT6qv6syKr+jgFUqsiqArz9RAGLAP/+1P8B/v3VAP8BLP4CA 

1127P8AAgA5//IAuQKyAAMACwAANyMDMwIyFhQGIiY0oE4MZk84JCQ4JLQB/v3AJDgkJDgAAgBWAeUBPA 

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 

1173vArIACwAAJRUhESEVIRUhFSEVAi/+NQHB/pUBTf6zRkYCskbwRvAAAAABAGQAAAIlArIACQAAExUh 

1174FSERIxEhFboBQ/69VgHBAmzwRv7KArJGAAAAAAEAL//yAo8CwAAfAAABMxEjNQcGIyImNTQ2MzIWH 

1175wEjJyYjIgYVFBYzMjY1IwGP90wfPnWTprSSf48LAVYCIqJofHllVG+hAU3+s3hARsicn8uAagoKpq 

1176N/gaN1XAAAAAEAZAAAAowCsgALAAABESMRIREjETMRIRECjFb+hFZWAXwCsv1OAS7+0gKy/sQBPAA 

1177AAAABAGQAAAC6ArIAAwAAMyMRM7pWVgKyAAABADf/8gHoArIAEwAAAREUBw4BIyImLwEzFxYzMjc2 

1178NREB6AIFcGpgbQIBVgIHfXQKAQKy/lYxIltob2EpKYyEFD0BpwAAAAABAGQAAAJ0ArIACwAACQEjA 

1179wcVIxEzEQEzATsBJ3ntQlZWAVVlAWH+nwEnR+ACsv6RAW8AAQBkAAACLwKyAAUAACUVIREzEQIv/j 

1180VWRkYCsv2UAAABAGQAAAMUArIAFAAAAREjETQ3BgcDIwMmJxYVESMRMxsBAxRWAiMxemx8NxsCVo7 

1181MywKy/U4BY7ZLco7+nAFmoFxLtP6dArL9lwJpAAAAAAEAZAAAAoACsgANAAAhIwEWFREjETMBJjUR 

1182MwKAhP67A1aEAUUDVAJeeov+pwKy/aJ5jAFZAAAAAgAv//ICuwLAAAkAEwAAEiAWFRQGICY1NBIyN 

1183jU0JiIGFRTbATSsrP7MrNrYenrYegLAxaKhxsahov47nIeIm5uIhwACAGQAAAJHArIADgAYAAABHg 

1184EVFAYHBisBESMRMzITNjQnJisBETMyAZRUX2VOHzuAVtY7GlxcGDWIiDUCrgtnVlVpCgT+5gKy/rU 

1185V1BUF/vgAAAACAC//zAK9AsAAEgAcAAAlFhcHJiMiBwYjIiY1NDYgFhUUJRQWMjY1NCYiBgI9PUMx 

1186UDcfKh8omqysATSs/dR62Hp62HpICTg7NgkHxqGixcWitbWHnJyHiJubAAIAZAAAAlgCsgAXACMAA 

1187CUWFyMmJyYnJisBESMRMzIXHgEVFAYHFiUzMjc+ATU0JyYrAQIqDCJfGQwNWhAhglbiOx9QXEY1Tv 

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 

1263gQAAwABBAkADAAuAkwATgBvACAAUgBpAGcAaAB0AHMAIABSAGUAcwBlAHIAdgBlAGQALgAATm8gUm 

1264lnaHRzIFJlc2VydmVkLgAAQQBpAGwAZQByAG8AbgAAQWlsZXJvbgAAUgBlAGcAdQBsAGEAcgAAUmV 

1265ndWxhcgAAMQAuADEAMAAyADsAVQBLAFcATgA7AEEAaQBsAGUAcgBvAG4ALQBSAGUAZwB1AGwAYQBy 

1266AAAxLjEwMjtVS1dOO0FpbGVyb24tUmVndWxhcgAAQQBpAGwAZQByAG8AbgAAQWlsZXJvbgAAVgBlA 

1267HIAcwBpAG8AbgAgADEALgAxADAAMgA7AFAAUwAgADAAMAAxAC4AMQAwADIAOwBoAG8AdABjAG8Abg 

1268B2ACAAMQAuADAALgA3ADAAOwBtAGEAawBlAG8AdABmAC4AbABpAGIAMgAuADUALgA1ADgAMwAyADk 

1269AAFZlcnNpb24gMS4xMDI7UFMgMDAxLjEwMjtob3Rjb252IDEuMC43MDttYWtlb3RmLmxpYjIuNS41 

1270ODMyOQAAQQBpAGwAZQByAG8AbgAtAFIAZQBnAHUAbABhAHIAAEFpbGVyb24tUmVndWxhcgAAUwBvA 

1271HIAYQAgAFMAYQBnAGEAbgBvAABTb3JhIFNhZ2FubwAAUwBvAHIAYQAgAFMAYQBnAGEAbgBvAABTb3 

1272JhIFNhZ2FubwAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBsAG8AbgAuAG4AZQB0AAB 

1273odHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGQAbwB0AGMAbwBs 

1274AG8AbgAuAG4AZQB0AABodHRwOi8vd3d3LmRvdGNvbG9uLm5ldAAAAAACAAAAAAAA/4MAMgAAAAAAA 

1275AAAAAAAAAAAAAAAAAAAAHQAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATAB 

1276QAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAA 

1277xADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0A 

1278TgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAIsAqQCDAJMAjQDDAKoAtgC3A 

1279LQAtQCrAL4AvwC8AIwAwADBAAAAAAAB//8AAgABAAAADAAAABwAAAACAAIAAwBxAAEAcgBzAAIABA 

1280AAAAIAAAABAAAACgBMAGYAAkRGTFQADmxhdG4AGgAEAAAAAP//AAEAAAAWAANDQVQgAB5NT0wgABZ 

1281ST00gABYAAP//AAEAAAAA//8AAgAAAAEAAmxpZ2EADmxvY2wAFAAAAAEAAQAAAAEAAAACAAYAEAAG 

1282AAAAAgASADQABAAAAAEATAADAAAAAgAQABYAAQAcAAAAAQABAE8AAQABAGcAAQABAE8AAwAAAAIAE 

1283AAWAAEAHAAAAAEAAQAvAAEAAQBnAAEAAQAvAAEAGgABAAgAAgAGAAwAcwACAE8AcgACAEwAAQABAE 

1284kAAAABAAAACgBGAGAAAkRGTFQADmxhdG4AHAAEAAAAAP//AAIAAAABABYAA0NBVCAAFk1PTCAAFlJ 

1285PTSAAFgAA//8AAgAAAAEAAmNwc3AADmtlcm4AFAAAAAEAAAAAAAEAAQACAAYADgABAAAAAQASAAIA 

1286AAACAB4ANgABAAoABQAFAAoAAgABACQAPQAAAAEAEgAEAAAAAQAMAAEAOP/nAAEAAQAkAAIGigAEA 

1287AAFJAXKABoAGQAA//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

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

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

1290ABD/vQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7gAAAAAAAAAAAAAAAAAA//MAA 

1291AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAP/5AAAAAAAAAA 

1292AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAD/4AAAAAAAAAAAAAAAAAA 

1293AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//L/9AAAAAAAAAAAAAAAAAAAAAAA 

1294AAAAAAAAAAAA/+gAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1295AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/zAAAAAA 

1296AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/mAAAAAAAAAAAAAAAAAAD 

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

1298AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/zv/qAAAAAP/0AAAACAAAAAAAAAAAAAAAAAAAAAAAA 

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

1300AAAAAAAAAAAAAAAAD/9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

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

1302AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+AAAAAAAAAAAAAAA 

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

1304AAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yAAA/+kAAAAA//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1305AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9wAAAAD//QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1306AAAAAAAAAAAAAAAAAAAAAP/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1307AAAAAAAAP/cAAAAAAAAAAAAAAAA/7YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

1308AAAAAAAAAAAAAAAAAAAAAAAAAAAP/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/6AAAAAAAAAA 

1309AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAkAFAAEAAAAAQACwAAABcA 

1310BgAAAAAAAAAIAA4AAAAAAAsAEgAAAAAAAAATABkAAwANAAAAAQAJAAAAAAAAAAAAAAAAAAAAGAAAA 

1311AAABwAAAAAAAAAAAAAAFQAFAAAAAAAYABgAAAAUAAAACgAAAAwAAgAPABEAFgAAAAAAAAAAAAAAAA 

1312AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAEAEQBdAAYAAAAAAAAAAAAAAAAAAAAAAAA 

1313AAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAcAAAAAAAAABwAAAAAACAAAAAAAAAAAAAcAAAAHAAAAEwAJ 

1314ABUADgAPAAAACwAQAAAAAAAAAAAAAAAAAAUAGAACAAIAAgAAAAIAGAAXAAAAGAAAABYAFgACABYAA 

1315gAWAAAAEQADAAoAFAAMAA0ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAEgAGAAEAHgAkAC 

1316YAJwApACoALQAuAC8AMgAzADcAOAA5ADoAPAA9AEUASABOAE8AUgBTAFUAVwBZAFoAWwBcAF0AcwA 

1317AAAAAAQAAAADa3tfFAAAAANAan9kAAAAA4QodoQ== 

1318""" 

1319 ) 

1320 ), 

1321 10 if size is None else size, 

1322 layout_engine=Layout.BASIC, 

1323 ) 

1324 return load_default_imagefont()