From 5ce96659c2ddc395d6dda689573e2a441fd61cbf Mon Sep 17 00:00:00 2001 From: Joshua Thijssen Date: Mon, 6 Jan 2025 13:20:11 +0100 Subject: [PATCH] up --- Cargo.lock | 419 +++++++++++++++++++++++++++++++++++++++++----------- Cargo.toml | 6 +- src/main.rs | 171 ++++++++++++++++----- src/test.rs | 65 ++++++++ 4 files changed, 536 insertions(+), 125 deletions(-) create mode 100644 src/test.rs diff --git a/Cargo.lock b/Cargo.lock index 288bac3..bacba94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,7 +47,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -57,9 +57,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + [[package]] name = "bitflags" version = "1.3.2" @@ -87,27 +93,12 @@ dependencies = [ "shlex", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cmake" -version = "0.1.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" -dependencies = [ - "cc", -] - [[package]] name = "colog" version = "1.3.0" @@ -132,14 +123,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -147,27 +138,39 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.19.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation", + "core-graphics-types", "foreign-types", "libc", ] +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + [[package]] name = "core-text" -version = "15.0.0" +version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131b3fd1f8bd5db9f2b398fa4fdb6008c64afc04d447c306ac2c7e98fba2a61d" +checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ "core-foundation", "core-graphics", @@ -175,32 +178,83 @@ dependencies = [ "libc", ] +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "dirs" -version = "2.0.2" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "cfg-if 0.1.10", "dirs-sys", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", "winapi", ] +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dwrote" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdf488e3a52a7aa30a05732a3e58420e22acb4b2b75635a561fc6ffbcab59ef" +checksum = "70182709525a3632b2ba96b6569225467b18ecb4a77f46d255f713a6bebf05fd" dependencies = [ "lazy_static", "libc", @@ -208,6 +262,12 @@ dependencies = [ "wio", ] +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "env_filter" version = "0.1.3" @@ -231,29 +291,19 @@ dependencies = [ "log", ] -[[package]] -name = "expat-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] - [[package]] name = "float-ord" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" [[package]] name = "font-kit" -version = "0.6.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f953474ebbe3460775ed2da52435477cc029493284d6ceb635598586a2c6298" +checksum = "b64b34f4efd515f905952d91bc185039863705592c0c53ae6d979805dd154520" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "byteorder", "core-foundation", "core-graphics", @@ -261,48 +311,76 @@ dependencies = [ "dirs", "dwrote", "float-ord", - "freetype", + "freetype-sys", "lazy_static", "libc", "log", "pathfinder_geometry", "pathfinder_simd", - "servo-fontconfig", "walkdir", "winapi", + "yeslogic-fontconfig-sys", ] [[package]] name = "fontmanager" version = "0.1.0" dependencies = [ + "anyhow", "colog", "font-kit", + "freetype-rs", + "log", + "prettytable", ] [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ + "foreign-types-macros", "foreign-types-shared", ] +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "foreign-types-shared" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] -name = "freetype" -version = "0.4.1" +name = "freetype-rs" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11926b2b410b469d0e9399eca4cbbe237a9ef02176c485803b29216307e8e028" +checksum = "b1fad2be0bf06af23adddcf6cd143c94ff0ba3b329691f92d1a38dae5c5aeebf" dependencies = [ + "bitflags 2.6.0", + "freetype-sys", "libc", - "servo-freetype-sys", +] + +[[package]] +name = "freetype-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" +dependencies = [ + "cc", + "libc", + "pkg-config", ] [[package]] @@ -311,23 +389,46 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + [[package]] name = "lazy_static" version = "1.5.0" @@ -340,6 +441,16 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libredox" version = "0.1.3" @@ -362,6 +473,18 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "pathfinder_geometry" version = "0.5.1" @@ -387,6 +510,20 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "prettytable" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46480520d1b77c9a3482d39939fcf96831537a250ec62d4fd8fbdf8e0302e781" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -454,6 +591,18 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + [[package]] name = "same-file" version = "1.0.6" @@ -470,34 +619,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] -name = "servo-fontconfig" -version = "0.4.0" +name = "serde" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ - "libc", - "servo-fontconfig-sys", + "serde_derive", ] [[package]] -name = "servo-fontconfig-sys" -version = "4.0.6" +name = "serde_derive" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0aa080856db55f188aaf36f01cae8c03448a6056552adb77d461179e44e1a14" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ - "expat-sys", - "pkg-config", - "servo-freetype-sys", -] - -[[package]] -name = "servo-freetype-sys" -version = "4.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ccb6d0d32d277d3ef7dea86203d8210945eb7a45fba89dd445b3595dd0dfc" -dependencies = [ - "cmake", - "pkg-config", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -517,6 +655,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -543,6 +692,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "utf8parse" version = "0.2.2" @@ -587,7 +742,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -596,13 +751,46 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -611,28 +799,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -645,24 +851,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -677,3 +907,14 @@ checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" dependencies = [ "winapi", ] + +[[package]] +name = "yeslogic-fontconfig-sys" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503a066b4c037c440169d995b869046827dbc71263f6e8f3be6d77d4f3229dbd" +dependencies = [ + "dlib", + "once_cell", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index f6f7347..d4d3af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,8 @@ edition = "2021" [dependencies] colog = "1.3.0" -font-kit = "0.6.0" \ No newline at end of file +font-kit = "0.14.2" +freetype-rs = "0.35.0" +log = "0.4.22" +anyhow = "1.0.95" +prettytable = "0.10.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index d6a8624..dc7a207 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,58 @@ +use std::collections::HashMap; +use std::fmt::{Display, Formatter}; use std::path::PathBuf; +use std::sync::{Arc, Mutex}; +use anyhow::anyhow; use font_kit::family_name::FamilyName; use font_kit::handle::Handle; use font_kit::properties::Properties; use font_kit::source::SystemSource; +use freetype::{Face, Library}; +use log::info; +use prettytable::{Attr, Cell, Row, Table}; + +#[derive(Clone, Debug)] +enum FontStyle { + Normal, + Italic, + Oblique, +} + +impl Display for FontStyle { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + match self { + FontStyle::Normal => write!(f, "Normal"), + FontStyle::Italic => write!(f, "Italic"), + FontStyle::Oblique => write!(f, "Oblique"), + } + } +} #[derive(Clone, Debug)] struct FontInfo { - #[allow(unused)] pub family: String, - #[allow(unused)] - pub style: String, + pub style: FontStyle, + pub weight: f32, + pub stretch: f32, + pub monospaced: bool, + pub path: PathBuf, pub index: Option, } struct FontManager { source: SystemSource, + ft_library: Library, info: Vec, handles: Vec, + /// Cache of font faces that are loaded through freetype + face_cache: Arc>>, } impl FontManager { fn new() -> Self { + let library = Library::init().expect("unable to init freetype library"); + let source = SystemSource::new(); let handles = source.all_fonts().unwrap(); @@ -34,12 +65,14 @@ impl FontManager { FontManager { source, + ft_library: library, info: font_info, handles, + face_cache: Arc::new(Mutex::new(HashMap::new())), } } - fn find(&self, families: Vec<&str>, style: Option<&str>) -> Option { + pub fn find(&self, families: Vec<&str>, style: FontStyle) -> Option { let mut f = Vec::new(); for family in families { let family = family.replace('\'', ""); @@ -54,21 +87,59 @@ impl FontManager { }); } - dbg!(&f); + let mut properties = Properties::default(); + match style { + FontStyle::Italic => properties.style(font_kit::properties::Style::Italic), + FontStyle::Oblique => properties.style(font_kit::properties::Style::Oblique), + FontStyle::Normal => properties.style(font_kit::properties::Style::Normal), + }; - let properties = Properties::default(); match self.source.select_best_match(&f, &properties) { Ok(handle) => Some(Self::handle_to_info(&handle)), Err(_) => None, } } + pub fn load(&self, font_info: FontInfo) -> Result { + let cache_key = format!("{}:{}", font_info.family, font_info.style); + if let Some(font_face) = self.face_cache.lock().unwrap().get(&cache_key) { + info!(target: "font", "Font loaded from cache: {}", cache_key); + // @todo: Can we somehow return the face within the cache so we don't need to copy it? + return Ok(font_face.clone()); + } + + let face = match self.ft_library.new_face(font_info.path, font_info.index.unwrap_or(0) as isize) { + Ok(face) => face, + Err(e) => { + eprintln!("unable to load font: {}", e); + return Err(anyhow!("unable to load font")) + } + }; + + + info!(target: "font", + "Font loaded: {} (number of glyphs: {})", + face.family_name().unwrap_or("Unknown".parse()?), + face.num_glyphs() + ); + + // @todo: same here.. we use a clone to store into cache, but can we just use the data we loaded through freetype? + info!(target: "font", "Caching font face: {}", cache_key); + self.face_cache.lock().unwrap().insert(cache_key.clone(), face.clone()); + Ok(face) + } + fn handle_to_info(handle: &Handle) -> FontInfo { let font = handle.load().unwrap(); let family = font.family_name(); let props = font.properties(); - let style = props.style.to_string(); + + let style = match props.style { + font_kit::properties::Style::Normal => FontStyle::Normal, + font_kit::properties::Style::Italic => FontStyle::Italic, + font_kit::properties::Style::Oblique => FontStyle::Oblique, + }; let Handle::Path { ref path, @@ -80,48 +151,78 @@ impl FontManager { FontInfo { family, style, + weight: props.weight.0, + stretch: props.stretch.0, + monospaced: font.is_monospace(), path: path.clone(), index: Some(*font_index as i32), } } } +const TEST_STRING: &str = r"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 +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 +0 1 2 3 4 5 6 7 8 9 ( ) $ % @ & ¢ € [ \ ] ^ _ ` { | } ~ < > # = + - * / : ; , . ! ? +¡ ¿ ˆ ˜ ¨ ´ ` ˘ ˙ ˚ ˝ ˛ ˇ ˆ ˇ ˘ ˙ ˚ ˛ ˜ ˝ ˇ ˘ ˙ ˚ ˛ ˜ ˝ ˇ ˘ ˙ ˚ ˛ ˜ ˝ +À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß +à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ +Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ +Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ +Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ +Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž +ſ ƀ Ɓ Ƃ ƃ Ƅ ƅ Ɔ Ƈ ƈ Ɖ Ɗ Ƌ ƌ ƍ Ǝ Ə Ɛ Ƒ ƒ Ɠ Ɣ ƕ Ɩ Ɨ Ƙ ƙ ƚ ƛ Ɯ Ɲ ƞ Ɵ +Ơ ơ Ƣ ƣ Ƥ ƥ Ʀ Ƨ ƨ Ʃ ƪ ƫ Ƭ ƭ Ʈ Ư ư Ʊ Ʋ Ƴ ƴ Ƶ ƶ Ʒ Ƹ ƹ ƺ ƻ Ƽ ƽ ƾ ƿ +ǀ ǁ ǂ ǃ DŽ Dž dž LJ Lj lj NJ Nj nj Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ Ǘ ǘ Ǚ ǚ Ǜ ǜ ǝ +Ǟ ǟ Ǡ ǡ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ DZ Dz dz Ǵ ǵ Ƕ Ƿ Ǹ ǹ Ǻ ǻ +Ǽ ǽ Ǿ ǿ Ȁ ȁ Ȃ ȃ Ȅ ȅ Ȇ ȇ Ȉ ȉ Ȋ ȋ Ȍ ȍ Ȏ ȏ Ȑ ȑ Ȓ ȓ Ȕ ȕ Ȗ ȗ Ș ș Ț ț +Ȝ ȝ Ȟ ȟ Ƞ ȡ Ȣ ȣ Ȥ ȥ Ȧ ȧ Ȩ ȩ Ȫ ȫ Ȭ ȭ Ȯ ȯ Ȱ ȱ Ȳ ȳ ȴ ȵ ȶ ȷ ȸ ȹ Ⱥ +Ȼ ȼ Ƚ Ⱦ ȿ ɀ Ɂ ɂ Ƀ Ʉ Ʌ Ɇ ɇ Ɉ ɉ Ɋ ɋ Ɍ ɍ Ɏ ɏ ɐ ɑ ɒ ɓ ɔ ɕ ɖ ɗ ɘ ə ɚ +ɛ ɜ ɝ ɞ ɟ ɠ ɡ ɢ ɣ ɤ ɥ ɦ ɧ ɨ ɩ ɪ ɫ ɬ ɭ ɮ ɯ ɰ ɱ ɲ ɳ ɴ ɵ ɶ ɷ ɸ ɹ +Hello world from the Gosub FontManager system! +"; fn main() { colog::init(); let manager = FontManager::new(); - for handle in manager.handles.iter() { - if let Ok(font) = handle.load() { - - let Handle::Path { - ref path, - font_index - } = handle else { - panic!("Expected a path handle"); - }; - - println!("Family: {}", font.family_name()); - println!("Path: {} ({})", path.to_str().unwrap(), font_index); - println!("Style: {}", font.properties().style); - - // println!("--------------------------------------"); - // println!("Full : {}", font.full_name()); - // println!("PS Nam: {}", font.postscript_name().unwrap()); - // println!("Monosp: {}", font.is_monospace()); - // println!("Glyphs: {}", font.glyph_count()); - // println!("G4A : {}", font.glyph_for_char('a').unwrap_or(0)); - // println!("Metric: {:?}", font.metrics()); - } - } + print_font_table(&manager); - let info = manager.find(vec!["arial"], None); + let info = manager.find(vec!["arial"], FontStyle::Normal); dbg!(&info); - - let info = manager.find(vec!["serif"], None); + let info = manager.find(vec!["serif"], FontStyle::Normal); dbg!(&info); - - let info = manager.find(vec!["monospace"], None); + let info = manager.find(vec!["monospace"], FontStyle::Normal); dbg!(&info); + + char_to_svg(&manager, "Arial", "Regular", ''); +} + +fn print_font_table(manager: &FontManager) { + let mut table = Table::new(); + table.set_format(*prettytable::format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + table.set_titles(Row::new(vec![ + Cell::new("PostScript Name").with_style(Attr::Bold), + Cell::new("Name").with_style(Attr::Bold), + Cell::new("Family").with_style(Attr::Bold), + Cell::new("Path").with_style(Attr::Bold), + Cell::new("Monospaced").with_style(Attr::Bold), + Cell::new("Style").with_style(Attr::Bold), + Cell::new("Weight").with_style(Attr::Bold), + Cell::new("Stretch").with_style(Attr::Bold), + ])); + + for info in manager.info.iter() { + table.add_row(Row::new(vec![ + Cell::new(&info.family), + Cell::new(&format!("{}", &info.style)), + Cell::new(&info.weight.to_string()), + Cell::new(&info.stretch.to_string()), + Cell::new(&info.monospaced.to_string()), + Cell::new(&info.path.to_str().unwrap()), + Cell::new(&info.index.unwrap_or(0).to_string()), + ])); + } + + table.printstd(); } diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..7a1d238 --- /dev/null +++ b/src/test.rs @@ -0,0 +1,65 @@ +// We need to deal with the following: +// - fontconfig: what about Windows and MacOS, they use different systems +// - can we somehow not copy fontfaces but use references or something? +// - deal when font is not found (it now defaults to a certain font?) + +fn blaatmain() { + colog::init(); + + let fm = FontManager::new(); + let f = fm.find("Arial", Some("Regular")).expect("unable to find font"); + let face = fm.load(f).expect("unable to load font"); + let f = fm.find("Arial", Some("Regular")).expect("unable to find font"); + let _face = fm.load(f).expect("unable to load font"); + let f = fm.find("Arial", Some("Bold")).expect("unable to find font"); + let _face = fm.load(f).expect("unable to load font"); + let f = fm.find("Arial", Some("Regular")).expect("unable to find font"); + let _face = fm.load(f).expect("unable to load font"); + let f = fm.find("Monospace", Some("Bold")).expect("unable to find font"); + let face = fm.load(f).expect("unable to load font"); + + face.set_char_size(40 * 64, 0, 50, 0).unwrap(); + face.load_char('@' as usize, freetype::face::LoadFlag::NO_SCALE).unwrap(); + + let glyph = face.glyph(); + let metrics = glyph.metrics(); + let xmin = metrics.horiBearingX - 5; + let width = metrics.width + 10; + let ymin = -metrics.horiBearingY - 5; + let height = metrics.height + 10; + let outline = glyph.outline().unwrap(); + + println!(""); + println!(""); + println!( + "", + xmin, ymin, width, height + ); + + for contour in outline.contours_iter() { + let start = contour.start(); + println!( + ""); + } + println!(""); +} + +fn draw_curve(curve: freetype::outline::Curve) { + match curve { + freetype::outline::Curve::Line(pt) => println!("L {} {}", pt.x, -pt.y), + freetype::outline::Curve::Bezier2(pt1, pt2) => { + println!("Q {} {} {} {}", pt1.x, -pt1.y, pt2.x, -pt2.y) + } + freetype::outline::Curve::Bezier3(pt1, pt2, pt3) => println!( + "C {} {} {} {} {} {}", + pt1.x, -pt1.y, pt2.x, -pt2.y, pt3.x, -pt3.y + ), + } +} \ No newline at end of file