Shofel2_T124_python/venv/lib/python3.10/site-packages/urwid/font.py

691 lines
31 KiB
Python

#!/usr/bin/python
#
# Urwid BigText fonts
# Copyright (C) 2004-2006 Ian Ward
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Urwid web site: https://urwid.org/
from __future__ import annotations
import typing
import warnings
from pprint import pformat
from urwid.canvas import CanvasError, TextCanvas
from urwid.escape import SAFE_ASCII_DEC_SPECIAL_RE
from urwid.util import apply_target_encoding, str_util
if typing.TYPE_CHECKING:
from collections.abc import Iterator, Sequence
from typing_extensions import Literal
def separate_glyphs(gdata: str, height: int) -> tuple[dict[str, tuple[int, list[str]]], bool]:
"""return (dictionary of glyphs, utf8 required)"""
gl: list[str] = gdata.split("\n")[1:-1]
if any("\t" in elem for elem in gl):
raise ValueError(f"Incorrect glyphs data:\n{gdata!r}")
if len(gl) != height + 1:
raise ValueError(f"Incorrect glyphs height (expected: {height}):\n{gdata}")
key_line: str = gl[0]
character: str | None = None # current character
key_index = 0 # index into character key line
end_col = 0 # column position at end of glyph
start_col = 0 # column position at start of glyph
jl: list[int] = [0] * height # indexes into lines of gdata (gl)
result: dict[str, tuple[int, list[str]]] = {}
utf8_required = False
while True:
if character is None:
if key_index >= len(key_line):
break
character = key_line[key_index]
if key_index < len(key_line) and key_line[key_index] == character:
end_col += str_util.get_width(ord(character))
key_index += 1
continue
out: list[str] = []
y = 0
fill = 0
for k, line in enumerate(gl[1:]):
j: int = jl[k]
y = 0
fill = 0
while y < end_col - start_col:
if j >= len(line):
fill = end_col - start_col - y
break
y += str_util.get_width(ord(line[j]))
j += 1
if y + fill != end_col - start_col:
raise ValueError(repr((y, fill, end_col)))
segment = line[jl[k] : j]
if not SAFE_ASCII_DEC_SPECIAL_RE.match(segment):
utf8_required = True
out.append(segment + " " * fill)
jl[k] = j
start_col = end_col
result[character] = (y + fill, out)
character = None
return result, utf8_required
def add_font(name: str, cls: FontRegistry) -> None:
warnings.warn(
"`add_font` is deprecated, please set 'name' attribute to the font class,"
" use metaclass keyword argument 'font_name'"
" or use `Font.register(<name>)`",
DeprecationWarning,
stacklevel=2,
)
cls.register(name)
class FontRegistryWarning(UserWarning):
"""FontRegistry warning."""
class FontRegistry(type):
"""Font registry.
Store all registered fonts, register during class creation if possible.
"""
__slots__ = ()
__registered: typing.ClassVar[dict[str, FontRegistry]] = {}
def __iter__(self) -> Iterator[str]:
"""Iterate over registered font names."""
return iter(self.__registered)
def __getitem__(self, item: str) -> FontRegistry | None:
"""Get font by name if registered."""
return self.__registered.get(item)
def __class_getitem__(cls, item: str) -> FontRegistry | None:
"""Get font by name if registered.
This method is needed to get access to font from registry class.
>>> repr(FontRegistry["a"])
'None'
>>> font = FontRegistry["Thin 3x3"]()
>>> font.height
3
>>> canvas: TextCanvas = font.render("+")
>>> b'\\n'.join(canvas.text).decode('utf-8') == " \\n ┼\\n "
True
"""
return cls.__registered.get(item)
@property
def registered(cls) -> Sequence[str]:
"""Registered font names in alphabetical order."""
return tuple(sorted(cls.__registered))
@classmethod
def as_list(mcs) -> list[tuple[str, FontRegistry]]:
"""List of (font name, font class) tuples."""
return list(mcs.__registered.items())
def __new__( # noqa: PYI034 # new can not return Self
cls: type[FontRegistry],
name: str,
bases: tuple[type, ...],
namespace: dict[str, typing.Any],
**kwds: typing.Any,
) -> FontRegistry:
font_name: str = namespace.setdefault("name", kwds.get("font_name", ""))
font_class = super().__new__(cls, name, bases, namespace)
if font_name:
if font_name not in cls.__registered:
cls.__registered[font_name] = font_class
if cls.__registered[font_name] != font_class:
warnings.warn(
f"{font_name!r} is already registered, please override explicit if required or change name",
FontRegistryWarning,
stacklevel=2,
)
return font_class
def register(cls, font_name: str) -> None:
"""Register font explicit.
:param font_name: Font name to use in registration.
"""
if not font_name:
raise ValueError('"font_name" is not set.')
cls.__registered[font_name] = cls
get_all_fonts = FontRegistry.as_list
class Font(metaclass=FontRegistry):
"""Font base class."""
__slots__ = ("char", "canvas", "utf8_required")
height: int
data: Sequence[str]
name: str
def __init__(self) -> None:
if not self.height:
raise ValueError(f'"height" is invalid: {self.height!r}')
if not self.data:
raise ValueError(f'"data" is empty: {self.data!r}')
self.char: dict[str, tuple[int, list[str]]] = {}
self.canvas: dict[str, TextCanvas] = {}
self.utf8_required = False
data: list[str] = [self._to_text(block) for block in self.data]
for gdata in data:
self.add_glyphs(gdata)
def __repr__(self) -> str:
return f"{self.__class__.__name__}()"
def __str__(self) -> str:
"""Font description."""
return f"{self.__class__.__name__}():\n {self.height!r}\n {pformat(self.data, indent=4)}"
@staticmethod
def _to_text(
obj: str | bytes,
encoding: str = "utf-8",
errors: Literal["strict", "ignore", "replace"] = "strict",
) -> str:
if isinstance(obj, str):
return obj
if isinstance(obj, bytes):
warnings.warn(
"Bytes based fonts are deprecated, please switch to the text one",
DeprecationWarning,
stacklevel=3,
)
return obj.decode(encoding, errors)
raise TypeError(f"{obj!r} is not str|bytes")
def add_glyphs(self, gdata: str) -> None:
d, utf8_required = separate_glyphs(gdata, self.height)
self.char.update(d)
self.utf8_required |= utf8_required
def characters(self) -> str:
return "".join(sorted(self.char))
def char_width(self, character: str) -> int:
if character in self.char:
return self.char[character][0]
return 0
def char_data(self, character: str) -> list[str]:
return self.char[character][1]
def render(self, character: str) -> TextCanvas:
if character in self.canvas:
return self.canvas[character]
width, line = self.char[character]
byte_lines = []
character_set_lines = []
for d in line:
t, cs = apply_target_encoding(d)
byte_lines.append(t)
character_set_lines.append(cs)
try:
canv = TextCanvas(byte_lines, None, character_set_lines, maxcol=width, check_width=False)
except CanvasError as exc:
raise CanvasError(f"Failed render of {character!r} from line {line!r}:\n{self}\n:{exc}").with_traceback(
exc.__traceback__
) from exc
self.canvas[character] = canv
return canv
# safe_palette = u"┘┐┌└┼─├┤┴┬│"
# more_palette = u"═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬○"
# block_palette = u"▄#█#▀#▌#▐#▖#▗#▘#▙#▚#▛#▜#▝#▞#▟"
class Thin3x3Font(Font):
name = "Thin 3x3"
height = 3
data = (
"""
000111222333444555666777888999 !
┌─┐ ┐ ┌─┐┌─┐ ┐┌─ ┌─ ┌─┐┌─┐┌─┐ │
│ │ │ ┌─┘ ─┤└─┼└─┐├─┐ ┼├─┤└─┤ │
└─┘ ┴ └─ └─┘ ┴ ─┘└─┘ ┴└─┘ ─┘ .
""",
r"""
"###$$$%%%'*++,--.///:;==???[[\\\]]^__`
" ┼┼┌┼┐O /' /.. _┌─┐┌ \ ┐^ `
┼┼└┼┐ / * ┼ ─ / ., _ ┌┘│ \
└┼┘/ O , ./ . └ \ ┘ ──
""",
)
class Thin4x3Font(Font):
name = "Thin 4x3"
height = 3
data = (
*Thin3x3Font.data,
"""
0000111122223333444455556666777788889999 ####$$$$
┌──┐ ┐ ┌──┐┌──┐ ┐┌── ┌── ┌──┐┌──┐┌──┐ ┼─┼┌┼┼┐
│ │ │ ┌──┘ ─┤└──┼└──┐├──┐ ┼├──┤└──┤ ┼─┼└┼┼┐
└──┘ ┴ └── └──┘ ┴ ──┘└──┘ ┴└──┘ ──┘ └┼┼┘
""",
)
class Sextant3x3Font(Font):
name = "Sextant 3x3"
height = 3
data = (
"""
!!!###$$$%%%&&&'''((()))***+++,,,---...///
▐ 🬞🬲🬲🬞🬍🬋🬉🬄🬖🬦🬧 🬉 🬞🬅 🬁🬢 🬞🬦🬞 🬦 🬖
🬉 🬇🬛🬛🬞🬰🬗🬞🬅🬭🬦🬈🬖 🬉🬏 🬘 🬇🬨🬈🬁🬨🬂 🬭 🬁🬂🬂 🬭 🬞🬅
🬁 🬀🬀 🬁 🬂 🬂🬁 🬁 🬁 🬅 🬂
""",
"""
000111222333444555666777888999
🬦🬂🬧🬞🬫 🬇🬂🬧🬁🬂🬧 🬞🬫▐🬂🬂🬞🬅🬀🬁🬂🬙🬦🬂🬧🬦🬂🬧
▐🬁▐ ▐ 🬞🬅🬀 🬂🬧🬇🬌🬫🬁🬂🬧▐🬂🬧 🬔 🬦🬂🬧 🬂🬙
🬂🬀 🬁 🬁🬂🬂🬁🬂🬀 🬁🬁🬂🬀 🬂🬀 🬀 🬂🬀 🬂
""",
"""
\"\"\"
🬄🬄
""",
"""
:::;;;<<<===>>>???@@@
🬭 🬭 🬖🬀 🬁🬢 🬇🬂🬧🬦🬂🬧
🬰 🬰 🬁🬢 🬠🬰🬰 🬖🬀 🬇🬀▐🬉🬅
🬂 🬅 🬀 🬁 🬁 🬂🬀
""",
"""
AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQ
🬞🬅🬢▐🬂🬧🬦🬂🬈▐🬂🬧▐🬂🬂▐🬂🬂🬦🬂🬈▐ ▐ 🬨🬀 ▐▐🬞🬅▐ ▐🬢🬫▐🬢▐🬦🬂🬧▐🬂🬧🬦🬂🬧
▐🬋🬫▐🬂🬧▐ 🬞▐ ▐▐🬂 ▐🬂 ▐ 🬨▐🬂🬨 ▐ 🬞 ▐▐🬈🬏▐ ▐🬁▐▐ 🬨▐ ▐▐🬂🬀▐🬇🬘
🬁 🬁🬁🬂🬀 🬂🬀🬁🬂🬀🬁🬂🬂🬁 🬂🬂🬁 🬁 🬂🬀 🬂🬀🬁 🬁🬁🬂🬂🬁 🬁🬁 🬁 🬂🬀🬁 🬂🬁
""",
"""
RRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[]]]^^^___```
▐🬂🬧🬦🬂🬈🬁🬨🬂▐ ▐▐ ▐▐ ▐🬉🬏🬘▐ ▐🬁🬂🬙 🬕🬀 🬂▌🬞🬅🬢 🬈🬏
▐🬊🬐🬞🬂🬧 ▐ ▐ ▐🬉🬏🬘▐🬖🬷🬞🬅🬢 🬧🬀🬞🬅 ▌ ▌
🬁 🬁 🬂🬀 🬁 🬂🬀 🬁 🬁 🬁🬁 🬁 🬁 🬁🬂🬂 🬂🬀 🬂🬀 🬂🬂🬂
""",
"""
\\\\\\
🬇🬏
🬁🬢
""",
)
class Sextant2x2Font(Font):
name = "Sextant 2x2"
height = 2
data = """
..,,%%00112233445566778899
🬁🬖▐🬨🬇▌🬁🬗🬠🬸🬦▐▐🬒▐🬭🬁🬙▐🬸▐🬸
🬇 🬇🬀🬁🬇🬉🬍 🬄🬉🬋🬇🬍🬁🬊🬇🬅🬉🬍 🬄🬉🬍 🬉
"""
class HalfBlock5x4Font(Font):
name = "Half Block 5x4"
height = 4
data = (
"""
00000111112222233333444445555566666777778888899999 !!
▄▀▀▄ ▄█ ▄▀▀▄ ▄▀▀▄ ▄ █ █▀▀▀ ▄▀▀ ▀▀▀█ ▄▀▀▄ ▄▀▀▄ █
█ █ █ ▄▀ ▄▀ █▄▄█ █▄▄ █▄▄ ▐▌ ▀▄▄▀ ▀▄▄█ █
█ █ █ ▄▀ ▄ █ █ █ █ █ █ █ █ █ ▀
▀▀ ▀▀▀ ▀▀▀▀ ▀▀ ▀ ▀▀▀ ▀▀ ▀ ▀▀ ▀▀ ▀
""",
'''
"""######$$$$$$%%%%%&&&&&((()))******++++++,,,-----..////::;;;
█▐▌ █ █ ▄▀█▀▄ ▐▌▐▌ ▄▀▄ █ █ ▄ ▄ ▄ ▐▌
▀█▀█▀ ▀▄█▄ █ ▀▄▀ ▐▌ ▐▌ ▄▄█▄▄ ▄▄█▄▄ ▄▄▄▄ █ ▀ ▀
▀█▀█▀ ▄ █ █ ▐▌▄ █ ▀▄▌▐▌ ▐▌ ▄▀▄ █ ▐▌ ▀ ▄▀
▀ ▀ ▀▀▀ ▀ ▀ ▀▀ ▀ ▀ ▄▀ ▀ ▀
''',
r"""
<<<<<=====>>>>>?????@@@@@@[[[[\\\\]]]]^^^^____```{{{{||}}}}~~~~''```
▄▀ ▀▄ ▄▀▀▄ ▄▀▀▀▄ █▀▀ ▐▌ ▀▀█ ▄▀▄ ▀▄ ▄▀ █ ▀▄ ▄ █ ▄▀
▄▀ ▀▀▀▀ ▀▄ ▄▀ █ █▀█ █ █ █ ▄▀ █ ▀▄ ▐▐▌▌
▀▄ ▀▀▀▀ ▄▀ ▀ █ ▀▀▀ █ ▐▌ █ █ █ █ ▀
▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀▀▀ ▀▀▀▀ ▀ ▀ ▀
""",
"""
AAAAABBBBBCCCCCDDDDDEEEEEFFFFFGGGGGHHHHHIIJJJJJKKKKK
▄▀▀▄ █▀▀▄ ▄▀▀▄ █▀▀▄ █▀▀▀ █▀▀▀ ▄▀▀▄ █ █ █ █ █ █
█▄▄█ █▄▄▀ █ █ █ █▄▄ █▄▄ █ █▄▄█ █ █ █▄▀
█ █ █ █ █ ▄ █ █ █ █ █ ▀█ █ █ █ ▄ █ █ ▀▄
▀ ▀ ▀▀▀ ▀▀ ▀▀▀ ▀▀▀▀ ▀ ▀▀ ▀ ▀ ▀ ▀▀ ▀ ▀
""",
"""
LLLLLMMMMMMNNNNNOOOOOPPPPPQQQQQRRRRRSSSSSTTTTT
█ █▄ ▄█ ██ █ ▄▀▀▄ █▀▀▄ ▄▀▀▄ █▀▀▄ ▄▀▀▄ ▀▀█▀▀
█ █ ▀ █ █▐▌█ █ █ █▄▄▀ █ █ █▄▄▀ ▀▄▄ █
█ █ █ █ ██ █ █ █ █ ▌█ █ █ ▄ █ █
▀▀▀▀ ▀ ▀ ▀ ▀ ▀▀ ▀ ▀▀▌ ▀ ▀ ▀▀ ▀
""",
"""
UUUUUVVVVVVWWWWWWXXXXXXYYYYYYZZZZZ
█ █ █ █ █ █ █ █ █ █ ▀▀▀█
█ █ ▐▌ ▐▌ █ ▄ █ ▀▄▀ ▀▄▀ ▄▀
█ █ █ █ ▐▌█▐▌ ▄▀ ▀▄ █ █
▀▀ ▀ ▀ ▀ ▀ ▀ ▀ ▀▀▀▀
""",
"""
aaaaabbbbbcccccdddddeeeeeffffggggghhhhhiijjjjkkkkk
█ █ ▄▀▀ █ ▄ ▄ █
▀▀▄ █▀▀▄ ▄▀▀▄ ▄▀▀█ ▄▀▀▄ ▀█▀ ▄▀▀▄ █▀▀▄ ▄ ▄ █ ▄▀
▄▀▀█ █ █ █ ▄ █ █ █▀▀ █ ▀▄▄█ █ █ █ █ █▀▄
▀▀▀ ▀▀▀ ▀▀ ▀▀▀ ▀▀ ▀ ▄▄▀ ▀ ▀ ▀ ▄▄▀ ▀ ▀
""",
"""
llmmmmmmnnnnnooooopppppqqqqqrrrrssssstttt
█ █
█ █▀▄▀▄ █▀▀▄ ▄▀▀▄ █▀▀▄ ▄▀▀█ █▀▀ ▄▀▀▀ ▀█▀
█ █ █ █ █ █ █ █ █ █ █ █ █ ▀▀▄ █
▀ ▀ ▀ ▀ ▀ ▀▀ █▀▀ ▀▀█ ▀ ▀▀▀ ▀
""",
"""
uuuuuvvvvvwwwwwwxxxxxxyyyyyzzzzz
█ █ █ █ █ ▄ █ ▀▄ ▄▀ █ █ ▀▀█▀
█ █ ▐▌▐▌ ▐▌█▐▌ ▄▀▄ ▀▄▄█ ▄▀
▀▀ ▀▀ ▀ ▀ ▀ ▀ ▄▄▀ ▀▀▀▀
""",
)
class HalfBlock6x5Font(Font):
name = "Half Block 6x5"
height = 5
data = """
000000111111222222333333444444555555666666777777888888999999 ..::////
▄▀▀▀▄ ▄█ ▄▀▀▀▄ ▄▀▀▀▄ ▄ █ █▀▀▀▀ ▄▀▀▀ ▀▀▀▀█ ▄▀▀▀▄ ▄▀▀▀▄ █
█ █ █ █ █ █ █ █ █ ▐▌ █ █ █ █ ▀ ▐▌
█ █ █ ▄▀ ▀▀▄ ▀▀▀█▀ ▀▀▀▀▄ █▀▀▀▄ █ ▄▀▀▀▄ ▀▀▀█ ▄ █
█ █ █ ▄▀ ▄ █ █ █ █ █ ▐▌ █ █ █ ▐▌
▀▀▀ ▀▀▀ ▀▀▀▀▀ ▀▀▀ ▀ ▀▀▀▀ ▀▀▀ ▀ ▀▀▀ ▀▀▀ ▀ ▀
"""
class HalfBlockHeavy6x5Font(Font):
name = "Half Block Heavy 6x5"
height = 5
data = """
000000111111222222333333444444555555666666777777888888999999 ..::////
▄███▄ ▐█▌ ▄███▄ ▄███▄ █▌ █████ ▄███▄ █████ ▄███▄ ▄███▄ █▌
█▌ ▐█ ▀█▌ ▀ ▐█ ▀ ▐█ █▌ █▌ █▌ █▌ █▌ █▌ ▐█ █▌ ▐█ █▌ ▐█
█▌ ▐█ █▌ ▄█▀ ██▌ █████ ████▄ ████▄ ▐█ ▐███▌ ▀████ █▌
█▌ ▐█ █▌ ▄█▀ ▄ ▐█ █▌ ▐█ █▌ ▐█ █▌ █▌ ▐█ ▐█ █▌▐█
▀███▀ ███▌ █████ ▀███▀ █▌ ████▀ ▀███▀ ▐█ ▀███▀ ▀███▀ █▌ █▌
"""
class Thin6x6Font(Font):
name = "Thin 6x6"
height = 6
data = (
"""
000000111111222222333333444444555555666666777777888888999999''
┌───┐ ┐ ┌───┐ ┌───┐ ┐ ┌─── ┌─── ┌───┐ ┌───┐ ┌───┐ │
│ │ │ │ │ ┌ │ │ │ │ │ │ │ │
│ / │ │ ┌───┘ ─┤ └──┼─ └───┐ ├───┐ ┼ ├───┤ └───┤
│ │ │ │ │ │ │ │ │ │ │ │ │
└───┘ ┴ └─── └───┘ ┴ ───┘ └───┘ ┴ └───┘ ───┘
""",
r'''
!! """######$$$$$$%%%%%%&&&&&&((()))******++++++
│ ││ ┌ ┌ ┌─┼─┐ ┌┐ / ┌─┐ / \
│ ─┼─┼─ │ │ └┘ / │ │ │ │ \ / │
│ │ │ └─┼─┐ / ┌─\┘ │ │ ──X── ──┼──
│ ─┼─┼─ │ │ / ┌┐ │ \, │ │ / \
. ┘ ┘ └─┼─┘ / └┘ └───\ \ /
''',
r"""
,,-----..//////::;;<<<<=====>>>>??????@@@@@@
/ ┌───┐ ┌───┐
/ . . / ──── \ │ │┌──┤
──── / / \ ┌─┘ ││ │
/ . , \ ──── / │ │└──┘
, . / \ / . └───┘
""",
r"""
[[\\\\\\]]^^^____``{{||}}~~~~~~
\ ┐ /\ \ ┌ │ ┐
\ │ │ │ │ ┌─┐
\ │ ┤ │ ├ └─┘
\ │ │ │ │
\ ┘ ──── └ │ ┘
""",
"""
AAAAAABBBBBBCCCCCCDDDDDDEEEEEEFFFFFFGGGGGGHHHHHHIIJJJJJJ
┌───┐ ┬───┐ ┌───┐ ┬───┐ ┬───┐ ┬───┐ ┌───┐ ┬ ┬ ┬ ┬
│ │ │ │ │ │ │ │ │ │ │ │ │ │
├───┤ ├───┤ │ │ │ ├── ├── │ ──┬ ├───┤ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ ┬ │
┴ ┴ ┴───┘ └───┘ ┴───┘ ┴───┘ ┴ └───┘ ┴ ┴ ┴ └───┘
""",
"""
KKKKKKLLLLLLMMMMMMNNNNNNOOOOOOPPPPPPQQQQQQRRRRRRSSSSSS
┬ ┬ ┬ ┌─┬─┐ ┬─┐ ┬ ┌───┐ ┬───┐ ┌───┐ ┬───┐ ┌───┐
│ ┌─┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
├─┴┐ │ │ │ │ │ │ │ │ │ ├───┘ │ │ ├─┬─┘ └───┐
│ └┐ │ │ │ │ │ │ │ │ │ │ ┐│ │ └─┐ │
┴ ┴ ┴───┘ ┴ ┴ ┴ └─┴ └───┘ ┴ └──┼┘ ┴ ┴ └───┘
""",
"""
TTTTTTUUUUUUVVVVVVWWWWWWXXXXXXYYYYYYZZZZZZ
┌─┬─┐ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┌───┐
│ │ │ │ │ │ │ └┐ ┌┘ │ │ ┌─┘
│ │ │ │ │ │ │ │ ├─┤ └─┬─┘ ┌┘
│ │ │ └┐ ┌┘ │ │ │ ┌┘ └┐ │ ┌┘
┴ └───┘ └─┘ └─┴─┘ ┴ ┴ ┴ └───┘
""",
"""
aaaaaabbbbbbccccccddddddeeeeeefffgggggghhhhhhiijjj
┌─┐
│ │ │ │ . .
┌───┐ ├───┐ ┌───┐ ┌───┤ ┌───┐ ┼ ┌───┐ ├───┐ ┐ ┐
┌───┤ │ │ │ │ │ ├───┘ │ │ │ │ │ │ │
└───┴ └───┘ └───┘ └───┘ └───┘ ┴ └───┤ ┴ ┴ ┴ │
└───┘ ─┘
""",
"""
kkkkkkllmmmmmmnnnnnnooooooppppppqqqqqqrrrrrssssss
│ │
│ ┌─ │ ┬─┬─┐ ┬───┐ ┌───┐ ┌───┐ ┌───┐ ┬──┐ ┌───┐
├─┴┐ │ │ │ │ │ │ │ │ │ │ │ │ │ └───┐
┴ └─ └ ┴ ┴ ┴ ┴ └───┘ ├───┘ └───┤ ┴ └───┘
│ │
""",
"""
ttttuuuuuuvvvvvvwwwwwwxxxxxxyyyyyyzzzzzz
─┼─ ┬ ┬ ┬ ┬ ┬ ┬ ─┐ ┌─ ┬ ┬ ────┬
│ │ │ └┐ ┌┘ │ │ │ ├─┤ │ │ ┌───┘
└─ └───┴ └─┘ └─┴─┘ ─┘ └─ └───┤ ┴────
└───┘
""",
)
class HalfBlock7x7Font(Font):
name = "Half Block 7x7"
height = 7
data = (
"""
0000000111111122222223333333444444455555556666666777777788888889999999'''
▄███▄ ▐█▌ ▄███▄ ▄███▄ █▌ ▐█████▌ ▄███▄ ▐█████▌ ▄███▄ ▄███▄ ▐█
▐█ █▌ ▀█▌ ▐█ █▌▐█ █▌▐█ █▌ ▐█ ▐█ ▐█ ▐█ █▌▐█ █▌▐█
▐█ ▐ █▌ █▌ █▌ ▐██ ▐█████▌▐████▄ ▐████▄ █▌ █████ ▀████▌
▐█ ▌ █▌ █▌ ▄█▀ █▌ █▌ █▌▐█ █▌ ▐█ ▐█ █▌ █▌
▐█ █▌ █▌ ▄█▀ ▐█ █▌ █▌ █▌▐█ █▌ █▌ ▐█ █▌ █▌
▀███▀ ███▌ ▐█████▌ ▀███▀ █▌ ▐████▀ ▀███▀ ▐█ ▀███▀ ▀███▀
""",
'''
!!! """""#######$$$$$$$%%%%%%%&&&&&&&(((())))*******++++++
▐█ ▐█ █▌ ▐█ █▌ █ ▄ █▌ ▄█▄ █▌▐█ ▄▄ ▄▄
▐█ ▐█ █▌▐█████▌ ▄███▄ ▐█▌▐█ ▐█ █▌ ▐█ █▌ ▀█▄█▀ ▐█
▐█ ▐█ █▌ ▐█▄█▄▄ ▀ █▌ ███ █▌ ▐█ ▐█████▌ ████▌
▐█ ▐█████▌ ▀▀█▀█▌ ▐█ ▄ ███▌▄ █▌ ▐█ ▄█▀█▄ ▐█
▐█ █▌ ▀███▀ █▌▐█▌▐█ █▌ ▐█ █▌ ▀▀ ▀▀
▐█ █ ▐█ ▀ ▀██▀█▌ █▌▐█
''',
"""
,,,------.../////:::;;;<<<<<<<======>>>>>>>???????@@@@@@@
█▌ ▄█▌ ▐█▄ ▄███▄ ▄███▄
▐█ ▐█ ▐█ ▄█▀ ▐████▌ ▀█▄ ▐█ █▌▐█ ▄▄█▌
▐████▌ █▌ ▐██ ██▌ █▌ ▐█▐█▀█▌
▐█ ▐█ ▐█ ▀█▄ ▐████▌ ▄█▀ █▌ ▐█▐█▄█▌
█▌ ▀ ▀█▌ ▐█▀ ▐█ ▀▀▀
▐█ ▐█ ▐█ █▌ ▀███▀
""",
r"""
[[[[\\\\\]]]]^^^^^^^_____```{{{{{|||}}}}}~~~~~~~```
▐██▌▐█ ▐██▌ ▐█▌ ▐█ █▌▐█ ▐█ █▌
▐█ █▌ █▌ ▐█ █▌ █▌ █▌ ▐█ ▐█ ▄▄ ▐█
▐█ ▐█ █▌▐█ █▌ ▄█▌ ▐█ ▐█▄ ▐▀▀█▄▄▌
▐█ █▌ █▌ ▀█▌ ▐█ ▐█▀ ▀▀
▐█ ▐█ █▌ █▌ ▐█ ▐█
▐██▌ █▌▐██▌ █████ █▌▐█ ▐█
""",
"""
AAAAAAABBBBBBBCCCCCCCDDDDDDDEEEEEEEFFFFFFFGGGGGGGHHHHHHHIIIIJJJJJJJ
▄███▄ ▐████▄ ▄███▄ ▐████▄ ▐█████▌▐█████▌ ▄███▄ ▐█ █▌ ██▌ █▌
▐█ █▌▐█ █▌▐█ ▐█ █▌▐█ ▐█ ▐█ ▐█ █▌ ▐█ █▌
▐█████▌▐█████ ▐█ ▐█ █▌▐████ ▐████ ▐█ ▐█████▌ ▐█ █▌
▐█ █▌▐█ █▌▐█ ▐█ █▌▐█ ▐█ ▐█ ██▌▐█ █▌ ▐█ █▌
▐█ █▌▐█ █▌▐█ ▐█ █▌▐█ ▐█ ▐█ █▌▐█ █▌ ▐█ ▐█ █▌
▐█ █▌▐████▀ ▀███▀ ▐████▀ ▐█████▌▐█ ▀███▀ ▐█ █▌ ██▌ ▀███▀
""",
"""
KKKKKKKLLLLLLLMMMMMMMMNNNNNNNOOOOOOOPPPPPPPQQQQQQQRRRRRRRSSSSSSS
▐█ █▌▐█ ▄█▌▐█▄ ▐██ █▌ ▄███▄ ▐████▄ ▄███▄ ▐████▄ ▄███▄
▐█ █▌ ▐█ ▐█ ▐▌ █▌▐██▌ █▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌▐█
▐█▄█▌ ▐█ ▐█ ▐▌ █▌▐█▐█ █▌▐█ █▌▐████▀ ▐█ █▌▐█████ ▀███▄
▐█▀█▌ ▐█ ▐█ █▌▐█ █▌█▌▐█ █▌▐█ ▐█ █▌▐█ █▌ █▌
▐█ █▌ ▐█ ▐█ █▌▐█ ▐██▌▐█ █▌▐█ ▐█ █▌█▌▐█ █▌ █▌
▐█ █▌▐█████▌▐█ █▌▐█ ██▌ ▀███▀ ▐█ ▀███▀ ▐█ █▌ ▀███▀
▀▀
""",
"""
TTTTTTTUUUUUUUVVVVVVVWWWWWWWWXXXXXXXYYYYYYYZZZZZZZ
█████▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌ █▌ █▌▐█████▌
█▌ ▐█ █▌ █▌ ▐█ ▐█ █▌ ▐█ █▌ ▐█ ▐█ █▌
█▌ ▐█ █▌ ▐█ █▌ ▐█ █▌ ▐█▌ ▐██ █▌
█▌ ▐█ █▌ ███ ▐█ ▐▌ █▌ ███ █▌ █▌
█▌ ▐█ █▌ ▐█▌ ▐█ ▐▌ █▌ █▌ ▐█ █▌ █▌
█▌ ▀███▀ █ ▀█▌▐█▀ ▐█ █▌ █▌ ▐█████▌
""",
"""
aaaaaaabbbbbbbcccccccdddddddeeeeeeefffffggggggghhhhhhhiiijjjj
▐█ █▌ ▄█▌ ▐█ █▌ █▌
▐█ █▌ ▐█ ▐█
▄███▄ ▐████▄ ▄███▄ ▄████▌ ▄███▄ ▐███ ▄███▄ ▐████▄ ▐█▌ ▐█▌
▄▄▄█▌▐█ █▌▐█ ▐█ █▌▐█▄▄▄█▌ ▐█ ▐█ █▌▐█ █▌ █▌ █▌
▐█▀▀▀█▌▐█ █▌▐█ ▐█ █▌▐█▀▀▀ ▐█ ▐█▄▄▄█▌▐█ █▌ █▌ █▌
▀████▌▐████▀ ▀███▀ ▀████▌ ▀███▀ ▐█ ▀▀▀█▌▐█ █▌ █▌ █▌
▀███▀ ▐██
""",
"""
kkkkkkkllllmmmmmmmmnnnnnnnooooooopppppppqqqqqqqrrrrrrsssssss
▐█ ██
▐█ ▐█
▐█ ▄█▌ ▐█ ▄█▌▐█▄ ▐████▄ ▄███▄ ▐████▄ ▄████▌ ▄███▌ ▄███▄
▐█▄█▀ ▐█ ▐█ ▐▌ █▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌▐█ ▐█▄▄▄
▐█▀▀█▄ ▐█ ▐█ ▐▌ █▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌▐█ ▀▀▀█▌
▐█ █▌ ▐█▌▐█ █▌▐█ █▌ ▀███▀ ▐████▀ ▀████▌▐█ ▀███▀
▐█ █▌
""",
"""
tttttuuuuuuuvvvvvvvwwwwwwwwxxxxxxxyyyyyyyzzzzzzz
█▌
█▌
███▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌▐█ █▌▐█████▌
█▌ ▐█ █▌ █▌ ▐█ ▐█ █▌ ▀█▄█▀ ▐█ █▌ ▄█▀
█▌ ▐█ █▌ ███ ▐█ ▐▌ █▌ ▄█▀█▄ ▐█▄▄▄█▌ ▄█▀
█▌ ▀███▀ ▐█▌ ▀█▌▐█▀ ▐█ █▌ ▀▀▀█▌▐█████▌
▀███▀
""",
)
if __name__ == "__main__":
all_ascii = frozenset(chr(x) for x in range(32, 127))
print("Available Fonts: (U) = UTF-8 required")
print("----------------")
for n, font_cls in get_all_fonts():
f = font_cls()
u = ""
if f.utf8_required:
u = "(U)"
print(f"{n:<20} {u:>3} ", end=" ")
chars = f.characters()
font_chars = frozenset(chars)
if font_chars == all_ascii:
print("Full ASCII")
elif font_chars & all_ascii == all_ascii:
print(f"Full ASCII + {''.join(font_chars^all_ascii)!r}")
else:
print(f"Characters: {chars!r}")