Start work on build scripts

This commit is contained in:
Slavfox 2020-02-03 22:46:08 +01:00
parent 708fdeadc7
commit e2c0edf539
11 changed files with 581 additions and 30 deletions

56
.gitignore vendored Normal file
View File

@ -0,0 +1,56 @@
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
docs/_build/
target/
.python-version
__pypackages__/
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.ropeproject
.mypy_cache/
.dmypy.json
dmypy.json
.idea
*.iml
.DS_Store
.AppleDouble
.LSOverride
._*

19
Pipfile Normal file
View File

@ -0,0 +1,19 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
black = "*"
mypy = "*"
[packages]
numpy = "*"
Pillow = "*"
fonttools = "*"
[requires]
python_version = "3.8"
[pipenv]
allow_prereleases = true

215
Pipfile.lock generated Normal file
View File

@ -0,0 +1,215 @@
{
"_meta": {
"hash": {
"sha256": "11679fbbfbfe6ca9cf64b908f74c67c912a0b96bff52aa6f34ff7528e5b9f449"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.8"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"fonttools": {
"hashes": [
"sha256:0c16d5da7846a92aedcb448277d13d3b729f7de48a917768d97ebd0d17067d7f",
"sha256:bd93818f304b7f0d087e8ca9b5b3ed0819a68fb6c1a4763134a92bb046c2c31b"
],
"index": "pypi",
"version": "==4.3.0"
},
"numpy": {
"hashes": [
"sha256:1786a08236f2c92ae0e70423c45e1e62788ed33028f94ca99c4df03f5be6b3c6",
"sha256:17aa7a81fe7599a10f2b7d95856dc5cf84a4eefa45bc96123cbbc3ebc568994e",
"sha256:20b26aaa5b3da029942cdcce719b363dbe58696ad182aff0e5dcb1687ec946dc",
"sha256:2d75908ab3ced4223ccba595b48e538afa5ecc37405923d1fea6906d7c3a50bc",
"sha256:39d2c685af15d3ce682c99ce5925cc66efc824652e10990d2462dfe9b8918c6a",
"sha256:56bc8ded6fcd9adea90f65377438f9fea8c05fcf7c5ba766bef258d0da1554aa",
"sha256:590355aeade1a2eaba17617c19edccb7db8d78760175256e3cf94590a1a964f3",
"sha256:70a840a26f4e61defa7bdf811d7498a284ced303dfbc35acb7be12a39b2aa121",
"sha256:77c3bfe65d8560487052ad55c6998a04b654c2fbc36d546aef2b2e511e760971",
"sha256:9537eecf179f566fd1c160a2e912ca0b8e02d773af0a7a1120ad4f7507cd0d26",
"sha256:9acdf933c1fd263c513a2df3dceecea6f3ff4419d80bf238510976bf9bcb26cd",
"sha256:ae0975f42ab1f28364dcda3dde3cf6c1ddab3e1d4b2909da0cb0191fa9ca0480",
"sha256:b3af02ecc999c8003e538e60c89a2b37646b39b688d4e44d7373e11c2debabec",
"sha256:b6ff59cee96b454516e47e7721098e6ceebef435e3e21ac2d6c3b8b02628eb77",
"sha256:b765ed3930b92812aa698a455847141869ef755a87e099fddd4ccf9d81fffb57",
"sha256:c98c5ffd7d41611407a1103ae11c8b634ad6a43606eca3e2a5a269e5d6e8eb07",
"sha256:cf7eb6b1025d3e169989416b1adcd676624c2dbed9e3bcb7137f51bfc8cc2572",
"sha256:d92350c22b150c1cae7ebb0ee8b5670cc84848f6359cf6b5d8f86617098a9b73",
"sha256:e422c3152921cece8b6a2fb6b0b4d73b6579bd20ae075e7d15143e711f3ca2ca",
"sha256:e840f552a509e3380b0f0ec977e8124d0dc34dc0e68289ca28f4d7c1d0d79474",
"sha256:f3d0a94ad151870978fb93538e95411c83899c9dc63e6fb65542f769568ecfa5"
],
"index": "pypi",
"version": "==1.18.1"
},
"pillow": {
"hashes": [
"sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be",
"sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946",
"sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837",
"sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f",
"sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00",
"sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d",
"sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533",
"sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a",
"sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358",
"sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda",
"sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435",
"sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2",
"sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313",
"sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff",
"sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317",
"sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2",
"sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614",
"sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0",
"sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386",
"sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9",
"sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636",
"sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"
],
"index": "pypi",
"version": "==7.0.0"
}
},
"develop": {
"appdirs": {
"hashes": [
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
],
"version": "==1.4.3"
},
"attrs": {
"hashes": [
"sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
"sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
],
"version": "==19.3.0"
},
"black": {
"hashes": [
"sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b",
"sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"
],
"index": "pypi",
"version": "==19.10b0"
},
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"version": "==7.0"
},
"mypy": {
"hashes": [
"sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a",
"sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7",
"sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2",
"sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474",
"sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0",
"sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217",
"sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749",
"sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6",
"sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf",
"sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36",
"sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b",
"sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72",
"sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1",
"sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1"
],
"index": "pypi",
"version": "==0.761"
},
"mypy-extensions": {
"hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
],
"version": "==0.4.3"
},
"pathspec": {
"hashes": [
"sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424",
"sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"
],
"version": "==0.7.0"
},
"regex": {
"hashes": [
"sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525",
"sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b",
"sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576",
"sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5",
"sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0",
"sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35",
"sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003",
"sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d",
"sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161",
"sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26",
"sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9",
"sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1",
"sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146",
"sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f",
"sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149",
"sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351",
"sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461",
"sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b",
"sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242",
"sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c",
"sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77"
],
"version": "==2020.1.8"
},
"toml": {
"hashes": [
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
],
"version": "==0.10.0"
},
"typed-ast": {
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"version": "==1.4.1"
},
"typing-extensions": {
"hashes": [
"sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2",
"sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d",
"sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"
],
"version": "==3.7.4.1"
}
}
}

51
build.py Normal file
View File

@ -0,0 +1,51 @@
from pathlib import Path
from cozette_builder.imagegen import save_sample, save_charlist
SAMPLE_TEXT = """
$BLUE$
$MAGENTA$$NC$ $FG$Cozette$NC$ $MAGENTA$$BLUE$
$WHITE$A B C D E F G H I J K L M $BLUE$
$WHITE$N O P Q R S T U V W X Y Z $BLUE$
1 2 3 4 5 6 7 8 9 0
$WHITE$a b c d e f g h i j k l m $BLUE$
$WHITE$n o p q r s t u v w x y z $BLUE$
$RED$() [] {} <> ? / \ : " ' ;$BLUE$ │
$RED$! @ # $ % ^ & * _ = + - |$BLUE$ │
, . ` ~$BLUE$
$YELLOW$
$BLUE$ $FG$
$BLUE$$FG$ $GREEN$ $YELLOW$ $MAGENTA$ $FG$ $BLUE$
$FG$ $BLUE$ $FG$$BLUE$
$FG$$BLUE$
$GREEN$Pchnąć w łódź jeża lub
ósm skrzyń fig.
Eĥoŝanĝo ĉiuĵaŭde.
Příliš žluťoučký kůň
úpěl ďábelské ódy.
$FG$ $MAGENTA$
"""
REPO_ROOT = Path(__file__).resolve().parent
def save_images():
bdfpath = REPO_ROOT / "Cozette8" / "Cozette-10.bdf"
save_charlist(bdfpath, REPO_ROOT / "img" / "characters.png")
save_sample(
"Clozette", SAMPLE_TEXT, REPO_ROOT / "img" / "sample.png",
)
if __name__ == "__main__":
save_images()

View File

View File

View File

@ -0,0 +1,88 @@
from __future__ import annotations
from typing import (
Iterable,
Union,
Literal,
NamedTuple,
Dict,
List,
TextIO,
Tuple,
)
import numpy as np
Bit = Union[Literal[1], Literal[0]]
class BBX(NamedTuple):
w: int
h: int
x: int
y: int
class BdfGlyph:
def __init__(self, bits: np.array, meta: Dict[str, str]):
self.bbx = bbx = BBX(*[int(s) for s in meta["BBX"].split()])
# this is probably wrong
self.bits: np.array = np.pad(bits, [[0, 0], [bbx.x, 0]])[
bbx.y : bbx.y + bbx.h, bbx.x : bbx.x + bbx.w
]
self.meta = meta
@classmethod
def from_str(cls, s: str, meta: Dict[str, str]) -> BdfGlyph:
return cls.from_iterable((int(l, 16) for l in s.splitlines()), meta)
@classmethod
def from_iterable(
cls, values: Iterable[int], meta: Dict[str, str]
) -> BdfGlyph:
return BdfGlyph(
np.unpackbits(
np.array([[v] for v in values], dtype=np.uint8), axis=1
),
meta=meta,
)
def __str__(self) -> str:
return "\n".join(
"".join("#" if ch else " " for ch in line) for line in self.bits
)
def parse_char(bdfstream: TextIO):
specs = {}
while not (line := bdfstream.readline()).startswith("BITMAP"):
parts = line.split(maxsplit=1)
specs[parts[0]] = parts[1]
bitmap = []
while not (line := bdfstream.readline()).startswith("ENDCHAR"):
bitmap.append(int(line.strip(), 16))
return specs, bitmap
class BdfFont:
def __init__(self, metadata: List[str], glyphs: Dict[int, BdfGlyph]):
self.metadata: List[str] = metadata
self.glyphs: Dict[int, BdfGlyph] = glyphs
@classmethod
def from_bdf(cls, bdfstream: TextIO):
metadata = []
while not (line := bdfstream.readline()).startswith("CHARS "):
metadata.append(line)
glyphs = {}
for i in range(int(line.split()[1])):
meta, char = parse_char(bdfstream)
glyphs[int(meta["ENCODING"])] = BdfGlyph.from_iterable(char, meta)
return cls(metadata, glyphs)
@property
def codepoints(self) -> Tuple[int, ...]:
return tuple(self.glyphs.keys())
@property
def str_codepoints(self) -> Tuple[str, ...]:
return tuple(f"U+{i:X}" for i in self.glyphs)

124
cozette_builder/imagegen.py Normal file
View File

@ -0,0 +1,124 @@
import subprocess
from typing import Tuple, Dict, Optional
from shlex import quote
from pathlib import Path
from cozette_builder.bdf.bdffont import BdfFont
import textwrap
import tempfile
Color = Tuple[int, int, int]
def hex_to_rgb(color: str) -> Color:
h = int(color, 16)
return h >> 16, (h >> 8) & 0x00FF, h & 0x0000FF
Palette = Dict[str, Optional[Color]]
default_palette: Palette = dict(
fg=hex_to_rgb("feffff"),
bg=hex_to_rgb("2d2b33"),
black=hex_to_rgb("383640"),
red=hex_to_rgb("a09ebb"),
green=hex_to_rgb("92b6b1"),
yellow=hex_to_rgb("edaf97"),
blue=hex_to_rgb("8789c0"),
magenta=hex_to_rgb("e47b66"),
cyan=hex_to_rgb("6b9080"),
white=hex_to_rgb("969a97"),
nc=None,
)
# Todo: rewrite this to use files instead of a string
def save_sample(
font: str,
sample: str,
output_path: Path,
fgcolor: str = "#abb2bf",
bgcolor: str = "#282c34",
palette: Palette = None,
):
if palette is None:
palette = default_palette
colored, stripped = colored_and_stripped_text(sample, palette)
lines = stripped.splitlines()
h, w = len(lines), max(len(line) for line in lines)
with tempfile.NamedTemporaryFile("w", delete=False) as f:
f.write(colored)
fp = f.name
cmd = quote(
f"tput civis &&"
f"cat {fp} && sleep 0 && "
f"import -window $WINDOWID {output_path}"
)
subprocess.run(
[
"xterm",
"-fg",
fgcolor,
"-bg",
bgcolor,
"-fa",
font,
"-geometry",
f"{w}x{h}",
"-dc",
"-e",
f"bash -c {cmd}",
],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
Path(fp).unlink()
def color_escape_seq(color: Color = None):
if color is None:
return f"\033[38;0m"
return f"\033[38;2;{color[0]};{color[1]};{color[2]}m"
def colored_and_stripped_text(text: str, palette: Palette) -> Tuple[str, str]:
colored_text = text
stripped_text = text
for color in palette.keys():
# The PyCharm MyPy plugin throws a fit at `palette.get(color)` because
# it doesn't know that palette.get returns an Optional[Color], PyCharm
# itself throws a fit here because of
# https://youtrack.jetbrains.com/issue/PY-40439, and it sometimes
# forgets that `palette` has a `.get` method, so ignore all those
# warnings:
# noinspection Mypy, PyTypedDict, PyUnresolvedReferences
colored_text = colored_text.replace(
f"${color.upper()}$", color_escape_seq(palette[color])
)
stripped_text = stripped_text.replace(f"${color.upper()}$", "")
return colored_text, stripped_text
# Todo: write a fill() that ignores character codes
def save_charlist(bdf_font: Path, output_path: Path):
with bdf_font.open() as f:
bdf = BdfFont.from_bdf(f)
save_sample(
"Clozette",
textwrap.fill(
"".join(
chr(c)
for c in bdf.codepoints
if c >= 32
and c
not in (
127,
# dumb as shit workaround for a weird bug
0x26A1,
)
)
),
output_path,
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,36 +1,34 @@
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ♡ Cozette ♡ ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ A B C D E F G H I J K L M │
│ N O P Q R S T U V W X Y Z │
╞═══════════════════════════╡
│ 1 2 3 4 5 6 7 8 9 0 │
╞═══════════════════════════╡
│ a b c d e f g h i j k l m │
│ n o p q r s t u v w x y z │
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
│ () [] {} <> ? / \ : " ' ; │
│ ! @ # $ % ^ & * _ = + - | │
│ , . ` ~ │
╰───────────────────────────╯
  
 
╔═══════════════╗
└──║ ✓ ✔ ✕ ✖ ✗ ✘  ║
║        ║
╚═══════════════╝▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
$BLUE$┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
$MAGENTA$$NC$ $FG$Cozette$NC$ $MAGENTA$$BLUE$
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
$WHITE$A B C D E F G H I J K L M $BLUE$
$WHITE$N O P Q R S T U V W X Y Z $BLUE$
╞═══════════════════════════╡
│ 1 2 3 4 5 6 7 8 9 0 │
╞═══════════════════════════╡
$WHITE$a b c d e f g h i j k l m $BLUE$
$WHITE$n o p q r s t u v w x y z $BLUE$
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┤
$RED$() [] {} <> ? / \ : " ' ;$BLUE$
$RED$! @ # $ % ^ & * _ = + - |$BLUE$
│ , . ` ~$BLUE$
╰───────────────────────────╯
$YELLOW$  
 
$BLUE$│ $FG$╔═══════════════╗
$BLUE$└──$FG$║ $GREEN$✓ ✔ $YELLOW$✕ ✖ $MAGENTA$✗ ✘ $FG$ ║$BLUE$
$FG$║ $BLUE$       $FG$║$BLUE$
$FG$╚═══════════════╝$BLUE$
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Pchnąć w tę łódź jeża lub
ósm skrzyń fig.
$GREEN$Pchnąć w tę łódź jeża lub
ósm skrzyń fig.
Eĥoŝanĝo ĉiuĵaŭde.
Příliš žluťoučký kůň
úpěl ďábelské ódy.
♠ ♣ ♥ ♦
Eĥoŝanĝo ĉiuĵaŭde.
Příliš žluťoučký kůň
úpěl ďábelské ódy.
$FG$♠ ♣ $MAGENTA$♥ ♦