diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ea7bc9..dfb5947 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: pacman -Syyu --noconfirm - name: Install dependencies run: | - pacman -S --noconfirm base git tar which zip libffi + pacman -S --noconfirm base git tar which zip libffi jre17-openjdk wget - name: Install python run: | pacman -S --noconfirm python python-pipenv python-setuptools diff --git a/.gitignore b/.gitignore index 774c748..cbd71e5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__/ build/ develop-eggs/ dist/ +deps/ downloads/ eggs/ .eggs/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 53b497e..bb57519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning]. +## [1.19.2-hidpi] + +### Added + +- Bold and HiDpi variants + +### Changed + +- TTF fonts should work slightly better now. +- Rewrote the build system to use [monobit](https://github.com/robhagemans/monobit) and [bitsnpicas](https://github.com/kreativekorp/bitsnpicas/releases/download/v2.0/BitsNPicas.jar). + ## [1.19.2] GitHub Copilot CLI update. @@ -2087,9 +2098,11 @@ Still broken on Windows. [keep a changelog]: https://keepachangelog.com/en/1.0.0/ [semantic versioning]: https://semver.org/spec/v2.0.0.html -[unreleased]: https://github.com/slavfox/Cozette/compare/v.1.19.1...HEAD -[1.19.1]: https://github.com/slavfox/Cozette/compare/v.1.19.0...1.19.1 -[1.19.0]: https://github.com/slavfox/Cozette/compare/v.1.18.1...1.19.0 +[unreleased]: https://github.com/slavfox/Cozette/compare/v.1.19.2-hidpi...HEAD +[1.19.2-hidpi]: https://github.com/slavfox/Cozette/compare/v.1.19.2...v.1.19.2-hidpi +[1.19.2]: https://github.com/slavfox/Cozette/compare/v.1.19.1...v.1.19.2 +[1.19.1]: https://github.com/slavfox/Cozette/compare/v.1.19.0...v.1.19.1 +[1.19.0]: https://github.com/slavfox/Cozette/compare/v.1.18.1...v.1.19.0 [1.18.1]: https://github.com/slavfox/Cozette/compare/v.1.18.0...v.1.18.1 [1.18.0]: https://github.com/slavfox/Cozette/compare/v.1.17.2...v.1.18.0 [1.17.2]: https://github.com/slavfox/Cozette/compare/v.1.17.1...v.1.17.2 diff --git a/Pipfile b/Pipfile index 911355b..4f73421 100644 --- a/Pipfile +++ b/Pipfile @@ -18,7 +18,7 @@ setuptools = "*" pip = "*" [requires] -python_version = "3.10" +python_version = ">=3.10" [pipenv] allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock index b2a5d62..b4de8d7 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,296 +1,308 @@ { - "_meta": { - "hash": { - "sha256": "d9ae6b5214a7df96080a597497b5a387714b75c3c6df7819fc3f8fbf6a3cf1a4" + "_meta": { + "hash": { + "sha256": "76b77df64095b616dbd9abb16e3ba36fd6d047b8b6856c0de254570811c76f02" + }, + "pipfile-spec": 6, + "requires": { + "python_version": ">=3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.10" + "default": { + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" + }, + "crayons": { + "hashes": [ + "sha256:bd33b7547800f2cfbd26b38431f9e64b487a7de74a947b0fafc89b45a601813f", + "sha256:e73ad105c78935d71fe454dd4b85c5c437ba199294e7ffd3341842bc683654b1" + ], + "index": "pypi", + "version": "==0.4.0" + }, + "fonttools": { + "hashes": [ + "sha256:106caf6167c4597556b31a8d9175a3fdc0356fdcd70ab19973c3b0d4c893c461", + "sha256:dba8d7cdb8e2bac1b3da28c5ed5960de09e59a2fe7e63bb73f5a59e57b0430d2" + ], + "index": "pypi", + "version": "==4.39.4" + }, + "gitdb": { + "hashes": [ + "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a", + "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.10" + }, + "gitpython": { + "hashes": [ + "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573", + "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d" + ], + "index": "pypi", + "version": "==3.1.31" + }, + "numpy": { + "hashes": [ + "sha256:04847257662eef90599a1beca30c757d8e562aa8c7d64e91ea465f299469075d", + "sha256:06bae17a3629416eb5bae3a429655dc075561206b6d3c1ddfa38b51f273bae5c", + "sha256:1365157813810cfda2be9518806bf32f6b5f56e5e501d8299e3b681d53e405e2", + "sha256:165b0fb4d5b6349eef7b909be2d61a673bc6e75e0eec43776eea3222385a9d11", + "sha256:1bed69508b3b97dd3fb8c439352881c1bd232a0c8dd1e11d8df4e68046d434cf", + "sha256:20dd2352806eb229bc79c4fa308431eaf1721c66f7928950ee0381df98a2d269", + "sha256:224e8862a1cd357eede831b270b9e6c51d2cbc2bb5cc2e2b8d0c76d52cbd1edc", + "sha256:236c8ff573c02677b873e0934419c8e9873bd2b35aaba885170b7b43cb26d5da", + "sha256:416da35914d2fecc3afd31127b1eb1a283df33292cfcb453e1c8fb46d52611a1", + "sha256:472bdc3ade289d3efa331738b1daa5a529eef0550650f5d5d2eadb936a2f83a5", + "sha256:48e33b46b7db13de75dd0c1c919b8b297b5d7a4dc50b181066977ee17bed7cc3", + "sha256:5e7ba92ad63ffded03400d5038af89f7788843794c77ad1a37522fa69762b06f", + "sha256:7261d100c9bf722057fd5b9cd5b48f2973b17792b41e689eeaf9b55843cd1afd", + "sha256:763fca81a8d8beb6bf4b9a9bbf4045b0c134c15ea66c81d26e5b8683b1861293", + "sha256:7cf92c2bfbaf7bd52df1a21e56e8d34cff711594498ecbd02a39df3aaada763b", + "sha256:8aad2f86d2036622af1e1eb9db94e26618f42a571e02583fa72d5b1983782bf8", + "sha256:9a18d2c173a44e48e72614748df5624875439af2d352a416b9f3840583ad9efb", + "sha256:a0dab69ef25ccabf6f066a4902e238767cbbe52bc5ff90aa99514f87812ba76a", + "sha256:a4a9f1eaa63b5e35e23e5465ed59746b0a680eb5b5da06f2d432f828d32b26c1", + "sha256:b1a22ae597ee1d0e2336044854b33965fd92e731efe3c2ab965826e02cca2a8c", + "sha256:bd1de5d7ab75cdf56f2247aace7940dfd0a8fd048e07808358d8fca604f1d102", + "sha256:dfe2e3845c3b630f6617f9e8a15c8a1cbaf452c9fa32c71ec0a77d09548cd662", + "sha256:f59080829bbfe46660a201fc17315a4e8ec6e4499ee745bab3df61866f63e771", + "sha256:f64b730004e500f836f6405ad5cd36d309b6ac065366a0855860155f23eb2ad5", + "sha256:f8cbdb428d848f03a4f6f534284cf7fb168a6ec0e742357bf65ad268316906ea" + ], + "index": "pypi", + "version": "==1.25.0rc1" + }, + "pillow": { + "hashes": [ + "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1", + "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba", + "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a", + "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799", + "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51", + "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb", + "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5", + "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270", + "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6", + "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47", + "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf", + "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e", + "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b", + "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66", + "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865", + "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec", + "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c", + "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1", + "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38", + "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906", + "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705", + "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef", + "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc", + "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f", + "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf", + "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392", + "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d", + "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe", + "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32", + "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5", + "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7", + "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44", + "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d", + "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3", + "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625", + "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e", + "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829", + "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089", + "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3", + "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78", + "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96", + "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964", + "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597", + "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99", + "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a", + "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140", + "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7", + "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16", + "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903", + "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1", + "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296", + "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572", + "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115", + "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a", + "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd", + "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4", + "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1", + "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb", + "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa", + "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a", + "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569", + "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c", + "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf", + "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082", + "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062", + "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579" + ], + "index": "pypi", + "version": "==9.5.0" + }, + "pip": { + "hashes": [ + "sha256:0e7c86f486935893c708287b30bd050a36ac827ec7fe5e43fe7cb198dd835fba", + "sha256:3ef6ac33239e4027d9a5598a381b9d30880a1477e50039db2eac6e8a8f6d1b18" + ], + "index": "pypi", + "version": "==23.1.2" + }, + "setuptools": { + "hashes": [ + "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f", + "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102" + ], + "index": "pypi", + "version": "==67.8.0" + }, + "smmap": { + "hashes": [ + "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", + "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + } }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "colorama": { - "hashes": [ - "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", - "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.4.5" - }, - "crayons": { - "hashes": [ - "sha256:bd33b7547800f2cfbd26b38431f9e64b487a7de74a947b0fafc89b45a601813f", - "sha256:e73ad105c78935d71fe454dd4b85c5c437ba199294e7ffd3341842bc683654b1" - ], - "index": "pypi", - "version": "==0.4.0" - }, - "fonttools": { - "hashes": [ - "sha256:4606e1a88ee1f6699d182fea9511bd9a8a915d913eab4584e5226da1180fcce7", - "sha256:fff6b752e326c15756c819fe2fe7ceab69f96a1dbcfe8911d0941cdb49905007" - ], - "index": "pypi", - "version": "==4.37.1" - }, - "gitdb": { - "hashes": [ - "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", - "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" - ], - "markers": "python_version >= '3.6'", - "version": "==4.0.9" - }, - "gitpython": { - "hashes": [ - "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704", - "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d" - ], - "index": "pypi", - "version": "==3.1.27" - }, - "numpy": { - "hashes": [ - "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0", - "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f", - "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0", - "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde", - "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913", - "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8", - "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38", - "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6", - "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842", - "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414", - "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e", - "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074", - "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f", - "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d", - "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418", - "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01", - "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215", - "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66", - "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5", - "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389", - "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77", - "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c", - "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722", - "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c", - "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d", - "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450", - "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5", - "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524" - ], - "index": "pypi", - "version": "==1.23.2" - }, - "pillow": { - "hashes": [ - "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927", - "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14", - "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc", - "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58", - "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60", - "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76", - "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c", - "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac", - "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490", - "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1", - "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f", - "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d", - "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f", - "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069", - "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402", - "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885", - "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e", - "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be", - "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8", - "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff", - "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da", - "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004", - "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f", - "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20", - "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d", - "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c", - "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544", - "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9", - "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3", - "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04", - "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c", - "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5", - "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4", - "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb", - "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4", - "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c", - "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467", - "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e", - "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421", - "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b", - "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8", - "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb", - "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3", - "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf", - "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1", - "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a", - "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28", - "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0", - "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1", - "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8", - "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd", - "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4", - "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8", - "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f", - "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013", - "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59", - "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc", - "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4" - ], - "index": "pypi", - "version": "==9.2.0" - }, - "pip": { - "hashes": [ - "sha256:3fd1929db052f056d7a998439176d3333fa1b3f6c1ad881de1885c0717608a4b", - "sha256:b61a374b5bc40a6e982426aede40c9b5a08ff20e640f5b56977f4f91fed1e39a" - ], - "index": "pypi", - "version": "==22.2.2" - }, - "setuptools": { - "hashes": [ - "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82", - "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57" - ], - "index": "pypi", - "version": "==65.3.0" - }, - "smmap": { - "hashes": [ - "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", - "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" - ], - "markers": "python_version >= '3.6'", - "version": "==5.0.0" + "develop": { + "black": { + "hashes": [ + "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5", + "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915", + "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326", + "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940", + "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b", + "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30", + "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c", + "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c", + "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab", + "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27", + "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2", + "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961", + "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9", + "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb", + "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70", + "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331", + "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2", + "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266", + "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d", + "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6", + "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b", + "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925", + "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8", + "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4", + "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3" + ], + "index": "pypi", + "version": "==23.3.0" + }, + "click": { + "hashes": [ + "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.3" + }, + "isort": { + "hashes": [ + "sha256:0ec8b74806e80fec33e6e7ba89d35e17b3eb1c4c74316ea44cf877cc26e8b118", + "sha256:cde11e804641edbe1b6b95d56582eb541f27eebc77864c6015545944bb0e9c76" + ], + "index": "pypi", + "version": "==6.0.0b2" + }, + "mypy": { + "hashes": [ + "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703", + "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf", + "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4", + "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85", + "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd", + "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae", + "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd", + "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca", + "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305", + "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409", + "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c", + "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb", + "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee", + "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a", + "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228", + "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897", + "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d", + "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f", + "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152", + "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf", + "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8", + "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11", + "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017", + "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929", + "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e", + "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a" + ], + "index": "pypi", + "version": "==1.3.0" + }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "pathspec": { + "hashes": [ + "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", + "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.1" + }, + "platformdirs": { + "hashes": [ + "sha256:0ade98a4895e87dc51d47151f7d2ec290365a585151d97b4d8d6312ed6132fed", + "sha256:e48fabd87db8f3a7df7150a4a5ea22c546ee8bc39bc2473244730d4b56d2cc4e" + ], + "markers": "python_version >= '3.7'", + "version": "==3.5.3" + }, + "typing-extensions": { + "hashes": [ + "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26", + "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5" + ], + "markers": "python_version >= '3.7'", + "version": "==4.6.3" + } } - }, - "develop": { - "black": { - "hashes": [ - "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90", - "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c", - "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78", - "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4", - "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee", - "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e", - "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e", - "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6", - "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9", - "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c", - "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256", - "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f", - "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2", - "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c", - "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b", - "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807", - "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf", - "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def", - "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad", - "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d", - "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849", - "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69", - "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666" - ], - "index": "pypi", - "version": "==22.6.0" - }, - "click": { - "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.3" - }, - "isort": { - "hashes": [ - "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", - "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" - ], - "index": "pypi", - "version": "==5.10.1" - }, - "mypy": { - "hashes": [ - "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655", - "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9", - "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3", - "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6", - "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0", - "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58", - "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103", - "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09", - "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417", - "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56", - "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2", - "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856", - "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0", - "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8", - "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27", - "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5", - "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71", - "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27", - "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe", - "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca", - "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf", - "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9", - "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c" - ], - "index": "pypi", - "version": "==0.971" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "pathspec": { - "hashes": [ - "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", - "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" - ], - "version": "==0.9.0" - }, - "platformdirs": { - "hashes": [ - "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", - "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" - ], - "markers": "python_version >= '3.7'", - "version": "==2.5.2" - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "markers": "python_full_version < '3.11.0a7'", - "version": "==2.0.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" - ], - "markers": "python_version >= '3.7'", - "version": "==4.3.0" - } - } } diff --git a/README.md b/README.md index 02af9ca..45f868a 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ A bitmap programming font optimized for coziness. - [Dmenu](#dmenu) - [VSCode, general GUI applications](#vscode-general-gui-applications) - [Kitty](#kitty) + - [Variants](#variants) - [Roadmap](#roadmap) - [Recommended alternatives](#recommended-alternatives) - [Character map](#character-map) @@ -53,31 +54,40 @@ A nicer character map that includes the codepoints can be found at ### [You can get Cozette over at the Releases tab]! -Cozette is distributed in two main variants: bitmap and vector. +## Variants and Sizes + +Cozette is distributed in three main variants: normal and hi-dpi (upscaled 2x) bitmaps +(`.bdf`, `.otb`, `.psf`, and `.fnt`), and vectors (`.ttf`). + +Font scaling varies wildly from system to system, and sometimes even from +program to program and font format to format. On my system (Linux), `cozette.otb` +looks right at 13pts; `cozette_hidpi.otb` looks right at 26pts and downscales +quite elegantly to 10pts; `CozetteVector` doesn't look right at any size (technically, +it will look right specifically at 9.4pts on a 100dpi screen on Linux, but pixel-perfect +bitmap fonts are a massive headache, treated differently by every OS, that I'm not quite sure how to solve) Bitmap fonts are, effectively, just that - bitmaps. They scale terribly, but look nice and sharp (and pixel-perfect) at one specific point size. Vector fonts scale well, but in this case, might look ugly at smaller point sizes because of antialiasing issues and the like. -

-The vector formats (CozetteVector) are provided as a compatibility feature. -They look hideous. They don't contain any glyphs past U+FFFF. +

NOTE:

+The vector formats (`CozetteVector`) are provided as a compatibility feature. Rendering of vectorized bitmap-like fonts is terrible on virtually all operating systems. If Cozette looks awful on your system, you probably have a vector version. -Please use the bitmap formats (.otb) if you can. +Please use the bitmap formats (`.otb`) if you can. -Issues with vector formats will not be fixed or addressed. -Cozette is a bitmap font first and foremost. - +Issues with vector formats will almost certainly not be fixed or +addressed; Cozette is a bitmap font first and foremost, and building a +bitmap font that builds from a single source and looks good both in its intended, +bitmap font as well as as the auto-vectorized format, on every OS, seems to be an unsolved problem. ### Linux The preferred format is `.otb` (for bitmaps) or `.ttf` (for CozetteVector). To install the font, just throw it in your fonts directory -(you probably want to follow your distro's instructions). On Ubuntu, if you -don't want to reconsider your distro choice, you might need to +(you probably want to follow your distro's instructions). On Ubuntu you might need to [specifically enable bitmap fonts]. **If you're on Arch**, [ifreund] made [an AUR package] for the .otb! Install it @@ -183,12 +193,14 @@ implemented: many other CLI tools! - [x] Charmap including the code points (to make it easier for users to report issues/request additions) -- [ ] Codepoints above U+FFFF in vector fonts +- [x] Codepoints above U+FFFF in vector fonts +- [x] Upscaled hi-dpi variant # Recommended alternatives -Cozette is, intentionally, a very small font. If you're looking for other -bitmap fonts with extra glyphs, a couple of my favorites are +Cozette is, intentionally, a very small font. If neither the base nor the +[HiDpi](#variants) version fit your needs, you might want to look at some +other bitmap fonts with extra glyphs. A couple of my favorites are [Tamzen](https://github.com/sunaku/tamzen-font/) and [Envypn](https://github.com/Sorixelle/envypn-powerline). You might also find the [Tecate/bitmap-fonts repo](https://github.com/Tecate/bitmap-fonts) @@ -204,30 +216,30 @@ look in Cozette, here is a screenshot of it: # Building -If you want to build Cozette yourself, you'll need [FontForge]. Once you +If you want to build Cozette yourself, you'll need [FontForge] and Java. Once you have that, just clone this repo, open `Cozette/Cozette.sfd` in FontForge, and go to _File → Generate Fonts..._. -To run the build scripts I use to prepare releases, first install Python 3.8 +To run the build scripts I use to prepare releases, first install Python (at least 3.8) and [pipenv]. For generating the images, you will also need `xorg-mkfontscale` and `xterm`. Then, install the dependencies and run `build.py fonts`: ```console $ pipenv install -$ pipenv run python3.8 build.py fonts +$ pipenv run python build.py fonts ``` Then install the generated fonts, and run ```console -$ pipenv run python3.8 build.py images +$ pipenv run python build.py images ``` Running ```console -$ pipenv run python3.8 build.py changelog +$ pipenv run python build.py changelog ``` will output the changelog between your local version and the last tag. @@ -238,10 +250,13 @@ Massive thanks to [ym1234] for helping me figure out how to make the font tables Thanks to [autumn], [cpkio], [yoshiyoshyosh], and [klinegareth] for contributing characters! -# License +# License & Acknowledgements Cozette is licensed [MIT] 💜 +Cozette's builds use [bdfscale](https://github.com/philj56/bdfscale) by [philj56](https://github.com/philj56) and +[Bits'N'Picas](https://github.com/kreativekorp/bitsnpicas) by [Kreative Software](https://github.com/kreativekorp). + [dina]: https://www.dcmembers.com/jibsen/download/61/ [proggy]: https://github.com/bluescan/proggyfonts [creep]: https://github.com/romeovs/creep diff --git a/bitsnpicas.sh b/bitsnpicas.sh new file mode 100755 index 0000000..ccfcd0c --- /dev/null +++ b/bitsnpicas.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +BITSNPICAS_URL="https://github.com/kreativekorp/bitsnpicas/releases/download/v2.0/BitsNPicas.jar" +mkdir -p deps +if [ ! -f deps/BitsNPicas.jar ]; then + echo "Downloading BitsNPicas.jar..." + wget -O deps/BitsNPicas.jar $BITSNPICAS_URL + echo "Done." +fi +java -jar deps/BitsNPicas.jar $@ diff --git a/build.py b/build.py index 3062801..0f97a73 100644 --- a/build.py +++ b/build.py @@ -1,16 +1,15 @@ import argparse -import os import subprocess -import tempfile from dataclasses import dataclass from pathlib import Path from shlex import quote -from shutil import copy, rmtree +from shutil import rmtree from typing import Optional, Sequence, cast import crayons # type: ignore from cozette_builder.changeloggen import get_changelog +from cozette_builder.hidpi import double_size from cozette_builder.imagegen import ( add_margins, read_sample, @@ -22,7 +21,6 @@ from cozette_builder.scanner import ( print_codepoints_for_changelog, scan_for_codepoints, ) -from cozette_builder.ttfbuilder import TTFBuilder REPO_ROOT = Path(__file__).resolve().parent BUILD_DIR = REPO_ROOT / "build" @@ -43,7 +41,7 @@ class Generate: ) -def save_images(otbpath): +def save_images(): print(crayons.yellow("Saving character map")) save_charlist(FONTNAME, SFDPATH, REPO_ROOT / "img") @@ -82,43 +80,119 @@ def gen_bitmap_formats() -> Path: generate=[ Generate("cozette.", bitmap_fmt="bdf"), Generate("cozette.", "otb"), + Generate("cozette.", "psf"), Generate("cozette.", "fnt"), - Generate("cozette_bitmap.ttf", "otb"), - Generate("cozette_bitmap.dfont", "sbit"), + Generate("cozette.dfont", "sbit"), ], ) rename_single(BUILD_DIR, "*.fnt", "cozette.fnt") - bdfpath = rename_single(BUILD_DIR, "*.bdf", "cozette.bdf") - return bdfpath + return rename_single(BUILD_DIR, "*.bdf", "cozette.bdf") -def fix_ttf(ttfpath: Path): - outname = "CozetteVector" +def fix_ttf(ttfpath: Path, name: str): + print(crayons.yellow(f"Generating TTF for {name}...")) script = "; ".join( [ f'Open("{ttfpath}")', "SelectWorthOutputting()", "RemoveOverlap()", "CorrectDirection()", - "Simplify()", - "Simplify(-1, 1.02)", + "ScaleToEm(2048)", 'RenameGlyphs("AGL with PUA")', 'Reencode("unicode")', - f'Generate("{outname}.dfont")', - f'Generate("{outname}.otf.dfont")', - f'Generate("{outname}.otf")', - "ScaleToEm(1024)", - f'Generate("{outname}.ttf")', + f'SetTTFName(0x409, 3, "{name}")', + f'SetTTFName(0x409, 11, "")', + 'SetTTFName(0x409, 13, "MIT")', + 'SetTTFName(0x409, 14, "https://opensource.org/licenses/MIT")', + f'Generate("{name}.dfont")', + f'Generate("{name}.otf")', + f'Generate("{name}.ttf")', ] ) # No idea why this doesn't work without shell=True subprocess.run( - [f"fontforge -lang ff -c {quote(script)}"], cwd=BUILD_DIR, shell=True + [f"fontforge -lang ff -c {quote(script)}"], + cwd=BUILD_DIR, + shell=True, + check=True, ) ttfpath.unlink() +def make_hidpi(bdf_path: Path, out_path: Path): + print(crayons.yellow("Generating hidpi font...")) + with bdf_path.open() as i: + with out_path.open("w") as o: + double_size(i, o) + print(crayons.green("Done!")) + + +def gen_variants(bdf_path: Path): + hidpi_path = BUILD_DIR / "cozette_hidpi.bdf" + + def bnp_invoc_ttf(name: str, format: str): + return [ + REPO_ROOT / "bitsnpicas.sh", + "convertbitmap", + "-f", + format, + "-o", + BUILD_DIR / f"{name}_tmp.{format}", + "-s", + "Cozette", + "-r", + name, + "-T", + ] + + subprocess.run( + [ + BUILD_DIR.parent / "bitsnpicas.sh", + "convertbitmap", + "-f", + "psf", + "-o", + BUILD_DIR / f"cozette.psf", + bdf_path, + ], + check=True, + ) + subprocess.run( + bnp_invoc_ttf("CozetteVector", "ttf") + [bdf_path], check=True + ) + subprocess.run( + bnp_invoc_ttf("CozetteVectorBold", "ttf") + ["-b", bdf_path], + check=True, + ) + print(crayons.yellow("Fixing TTF variants...")) + fix_ttf(BUILD_DIR / "CozetteVector_tmp.ttf", "CozetteVector") + fix_ttf(BUILD_DIR / "CozetteVectorBold_tmp.ttf", "CozetteVectorBold") + print(crayons.green("Done!")) + make_hidpi(bdf_path, hidpi_path) + fontforge( + open=hidpi_path, + generate=[ + Generate(f"{hidpi_path.stem}.", "otb"), + Generate(f"{hidpi_path.stem}.", "fnt"), + Generate(f"{hidpi_path.stem}.dfont", "sbit"), + ], + ) + rename_single(BUILD_DIR, "*-26.fnt", "cozette_hidpi.fnt") + subprocess.run( + [ + BUILD_DIR.parent / "bitsnpicas.sh", + "convertbitmap", + "-f", + "psf", + "-o", + hidpi_path.with_suffix(".psf"), + hidpi_path, + ], + check=True, + ) + + if __name__ == "__main__": parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest="action") @@ -151,21 +225,16 @@ if __name__ == "__main__": ) if args.action == "images": print(crayons.blue("Saving sample images...")) - save_images(BUILD_DIR / "cozette.otb") + save_images() print(crayons.green("Done!", bold=True)) elif args.action == "fonts": rmtree(BUILD_DIR, ignore_errors=True) BUILD_DIR.mkdir(exist_ok=True) - os.chdir(BUILD_DIR) print(crayons.blue("Building bitmap formats...")) - bdfpath = gen_bitmap_formats() + bdf_path = gen_bitmap_formats() print(crayons.green("Done!", bold=True)) - print(crayons.blue("Generating TTF...")) - ttfbuilder = TTFBuilder.from_bdf_path(bdfpath) - ttfbuilder.build("cozette-tmp.ttf") - print(crayons.green("Done!", bold=True)) - print(crayons.blue("Fixing TTF...")) - fix_ttf(Path("cozette-tmp.ttf")) + print(crayons.blue("Building variants...")) + gen_variants(bdf_path) print(crayons.green("Done!", bold=True)) elif args.action == "changelog": get_changelog() diff --git a/cozette_builder/bdffont.py b/cozette_builder/bdffont.py deleted file mode 100644 index aba5343..0000000 --- a/cozette_builder/bdffont.py +++ /dev/null @@ -1,125 +0,0 @@ -from __future__ import annotations - -from typing import ( - Dict, - Iterable, - List, - Literal, - NamedTuple, - TextIO, - Tuple, - Union, -) - -import numpy as np # type: ignore -from fontTools.pens.ttGlyphPen import TTGlyphPen # type: ignore - -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 = bits[0 : bbx.h, 0 : bbx.w] - self.metadata = 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 draw(self, ppp: float): - pen = TTGlyphPen(None) - for y, row in enumerate(reversed(self.bits)): - for x, col in enumerate(row): - if col: - pen.moveTo( - ((x + self.bbx.x) * ppp, (y + self.bbx.y) * ppp) - ) - pen.lineTo( - ((x + self.bbx.x + 1) * ppp, (y + self.bbx.y) * ppp) - ) - pen.lineTo( - ( - (x + self.bbx.x + 1) * ppp, - (y + self.bbx.y + 1) * ppp, - ) - ) - pen.lineTo( - ((x + self.bbx.x) * ppp, (y + self.bbx.y + 1) * ppp) - ) - pen.lineTo( - ((x + self.bbx.x) * ppp, (y + self.bbx.y) * ppp) - ) - pen.closePath() - return pen.glyph() - - def meta(self, k) -> List[str]: - return self.metadata[k].strip('"').strip().split() - - -def parse_char(bdfstream: TextIO) -> Tuple[Dict[str, str], List[int]]: - specs = {} - while not (line := bdfstream.readline()).startswith("BITMAP"): - parts = line.split(maxsplit=1) - specs[parts[0]] = parts[1].strip() - bitmap = [] - while not (line := bdfstream.readline()).startswith("ENDCHAR"): - bitmap.append(int(line.strip(), 16)) - return specs, bitmap - - -class BdfFont: - def __init__(self, metadata: Dict[str, str], glyphs: Dict[int, BdfGlyph]): - self.metadata: Dict[str, str] = metadata - self.glyphs: Dict[int, BdfGlyph] = glyphs - - @classmethod - def from_bdf(cls, bdfstream: TextIO): - metadata = {} - while not (line := bdfstream.readline()).startswith("CHARS "): - try: - k, val = line.split(maxsplit=1) - metadata[k] = val.strip() - except ValueError: - pass - 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) - - def meta(self, k) -> List[str]: - return self.metadata[k].strip('"').strip().split() diff --git a/cozette_builder/hidpi.py b/cozette_builder/hidpi.py new file mode 100644 index 0000000..50c7557 --- /dev/null +++ b/cozette_builder/hidpi.py @@ -0,0 +1,93 @@ +# Based on bdfscale by Philip Jones (https://github.com/philj56/bdfscale) under the MIT License; original license +# included below: +# +# MIT License +# +# Copyright (c) 2019 Philip Jones +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +from io import StringIO +from typing import TextIO + +# Lines that need all numbers scaled +scale_lines = [ + "SIZE", + "FONTBOUNDINGBOX", + "PIXEL_SIZE", + "POINT_SIZE", + "AVERAGE_WIDTH", + "FONT_ASCENT", + "FONT_DESCENT", + "UNDERLINE_POSITION", + "UNDERLINE_THICKNESS", + "X_HEIGHT", + "CAP_HEIGHT", + "RAW_ASCENT", + "RAW_DESCENT", + "NORM_SPACE", + "SUPERSCRIPT_", + "SUBSCRIPT_", + "FIGURE_WIDTH", + "AVG_LOWERCASE_WIDTH", + "AVG_UPPERCASE_WIDTH" "DWIDTH", + # "SWIDTH", + "BBX", + "QUAD_WIDTH", +] + + +def double_size(src: TextIO, out: TextIO): + bitmap = False + for line in src.readlines(): + if line.startswith("ENDCHAR"): + bitmap = False + elif bitmap: + line = line.strip() + pad = len(line) % 2 + line = line + "0" * pad + size = len(line) * 2 + + # Do the actual scaling + binary = bin(int(line.strip(), 16))[2:] + rescaled = "".join([x * 2 for x in binary]) + res = hex(int(rescaled, 2))[2:].upper() + + line = "0" * (size - len(res)) + res # Pad out to desired length + line = (line + "\n") * 2 # And correct number of lines + elif any([line.startswith(x) for x in scale_lines]): + words = line.split() + for i, num in enumerate(words[1:]): + words[i + 1] = str(int(num) * 2) + line = " ".join(words) + "\n" + elif line.startswith("SIZE "): + words = line.strip().split() + words[1] = str(int(words[1]) * 2) + line = " ".join(words) + "\n" + elif line.startswith("FONT "): + xlfd = line[len("FONT ") :].strip().split("-") + # PIXEL_SIZE + xlfd[7] = f"{int(xlfd[7]) * 2}" + # POINT_SIZE + xlfd[8] = f"{int(xlfd[8]) * 2}" + # AVERAGE_WIDTH + xlfd[12] = f"{int(xlfd[12]) * 2}" + line = "FONT " + "-".join(xlfd) + "\n" + elif line.startswith("BITMAP"): + bitmap = True + out.write(line.replace("Cozette", "CozetteHiDpi")) diff --git a/cozette_builder/hidpi_prefix.txt b/cozette_builder/hidpi_prefix.txt new file mode 100644 index 0000000..afd9d61 --- /dev/null +++ b/cozette_builder/hidpi_prefix.txt @@ -0,0 +1,48 @@ +STARTFONT 2.1 +FONT -slavfox-CozetteHiDpi-Medium-R-Normal--26-240-75-75-M-120-ISO10646-1 +SIZE 24 75 75 +FONTBOUNDINGBOX 17 28 -5 -3 +COMMENT "Generated by fontforge, http://fontforge.sourceforge.net" +COMMENT "(c) 2020-2023 Slavfox" +STARTPROPERTIES 40 +FOUNDRY "slavfox" +FAMILY_NAME "Cozette" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 13 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "M" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONTNAME_REGISTRY "" +FONT_NAME "Cozette" +FACE_NAME "Cozette" +COPYRIGHT "(c) 2020-2023 Slavfox" +FONT_VERSION "1.192" +FONT_ASCENT 10 +FONT_DESCENT 3 +UNDERLINE_POSITION -19 +UNDERLINE_THICKNESS 13 +X_HEIGHT 5 +CAP_HEIGHT 7 +DEFAULT_CHAR 0 +RAW_ASCENT 769 +RAW_DESCENT 230 +NORM_SPACE 6 +RELATIVE_WEIGHT 50 +RELATIVE_SETWIDTH 50 +SUPERSCRIPT_X 0 +SUPERSCRIPT_Y 2 +SUPERSCRIPT_SIZE 2 +SUBSCRIPT_X 0 +SUBSCRIPT_Y 2 +SUBSCRIPT_SIZE 2 +FIGURE_WIDTH 6 +AVG_LOWERCASE_WIDTH 60 +AVG_UPPERCASE_WIDTH 60 +ENDPROPERTIES diff --git a/cozette_builder/scanner.py b/cozette_builder/scanner.py index 7776969..af325f9 100644 --- a/cozette_builder/scanner.py +++ b/cozette_builder/scanner.py @@ -1,6 +1,6 @@ import re from pathlib import Path -from typing import Dict, Iterable, List, Set +from typing import Dict, List, Set from unicodedata import name as uniname, east_asian_width as eaw UESCAPE = re.compile(r"\\[uU]([0-9A-Fa-f]{4,5})") diff --git a/cozette_builder/ttfbuilder.py b/cozette_builder/ttfbuilder.py deleted file mode 100644 index 50a269f..0000000 --- a/cozette_builder/ttfbuilder.py +++ /dev/null @@ -1,103 +0,0 @@ -from pathlib import Path - -from fontTools.fontBuilder import FontBuilder, _panoseDefaults # type: ignore - -from cozette_builder.bdffont import BdfFont - -with (Path(__file__).resolve().parent.parent / "LICENSE").open() as f: - LICENSE_TEXT = f.read() - - -def get_version(): - cozette_path = ( - Path(__file__).resolve().parent.parent / "Cozette" / "Cozette.sfd" - ) - with cozette_path.open() as f: - for line in f: - if line.startswith("Version:"): - _, v = line.split() - return v - - -class TTFBuilder: - @classmethod - def from_bdf_path(cls, path: Path): - with path.open() as f: - bdf = BdfFont.from_bdf(f) - return cls(bdf) - - def __init__(self, bdf: BdfFont): - self.bdf = bdf - upm = 1000 - self.fb = FontBuilder(unitsPerEm=upm) - self.ppp = upm / int(self.bdf.meta("SIZE")[0]) - w, h, startx, starty = self.bdf.meta("FONTBOUNDINGBOX") - self.ascent = int(self.bdf.meta("FONT_ASCENT")[0]) - self.descent = int(self.bdf.meta("FONT_DESCENT")[0]) - self.w = int(w) - self.h = int(h) - self.startx = int(startx) - self.starty = int(starty) - - def build(self, output_path: str): - glyph_names = { - k: glyph.meta("STARTCHAR")[0] - for k, glyph in self.bdf.glyphs.items() - if k >= 0 - } - ascent = round(self.ascent * self.ppp) - descent = round(self.descent * self.ppp) - - self.fb.setupGlyphOrder(list(glyph_names.values())) - self.fb.setupCharacterMap(glyph_names) - advance_widths = { - name: int(self.bdf.glyphs[k].meta("SWIDTH")[0]) - for k, name in glyph_names.items() - } - family_name = "CozetteVector" - style_name = "Regular" - version = get_version() - - # scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=IWS-Chapter08 - namestrings = { - "familyName": {"en": family_name}, - "styleName": {"en": style_name}, - "uniqueFontIdentifier": f"fontBuilder: {family_name}.{style_name}", - "fullName": family_name, - "psName": f"{family_name}-{style_name}", - "version": f"Version {version}", - "copyright": "(c) 2020 Slavfox", - "manufacturer": "Slavfox", - "designer": "Slavfox", - "description": "Programming bitmap font optimized for coziness", - "vendorURL": "https://github.com/slavfox", - "designerURL": "https://github.com/slavfox", - "licenseDescription": LICENSE_TEXT, - "licenseInfoURL": "https://opensource.org/licenses/MIT", - "sampleText": "A wizard’s job is to vex chumps quickly in fog.", - } - self.fb.setupGlyf( - { - name: self.bdf.glyphs[k].draw(self.ppp) - for k, name in glyph_names.items() - } - ) - metrics = { - name: (w, self.fb.font["glyf"][name].xMin) - for name, w in advance_widths.items() - } - self.fb.setupHorizontalMetrics(metrics) - self.fb.setupHorizontalHeader(ascent=ascent, descent=-descent) - self.fb.setupNameTable(namestrings) - self.fb.setupOS2( - sTypoAscender=ascent, - usWinAscent=ascent, - usWinDescent=descent, - panose={ - **_panoseDefaults, - "bFamilyType": 2, # Text and display - "bProportion": 9, # Monospace - }, - ) - self.fb.setupPost(isFixedPitch=1) - self.fb.save(output_path) diff --git a/img/characters.png b/img/characters.png index 5a5ac80..3c75177 100644 Binary files a/img/characters.png and b/img/characters.png differ diff --git a/img/charmap.png b/img/charmap.png index 4b4ca95..e713d4e 100644 Binary files a/img/charmap.png and b/img/charmap.png differ