From 6b37be51406bf4872738a6f26e56f042bffbc1b8 Mon Sep 17 00:00:00 2001 From: StarArawn <toasterthegamer@gmail.com> Date: Sat, 11 Dec 2021 09:33:24 -0500 Subject: [PATCH] Split more stuff into kayak_font crate. --- Cargo.lock | 265 +-- bevy_kayak_ui/Cargo.toml | 1 + .../src/render/unified/font/extract.rs | 3 +- bevy_kayak_ui/src/render/unified/font/font.rs | 34 - .../src/render/unified/font/font_mapping.rs | 3 +- bevy_kayak_ui/src/render/unified/font/mod.rs | 14 +- .../src/render/unified/font/sdf/mod.rs | 62 - bevy_kayak_ui/src/render/unified/pipeline.rs | 10 +- kayak_font/Cargo.toml | 13 +- kayak_font/assets/roboto.json | 1529 +++++++++++++++++ kayak_font/examples/main.rs | 54 - kayak_font/examples/simple.rs | 30 - kayak_font/resources/Roboto-Regular.ttf | Bin 171272 -> 0 bytes .../font/sdf => kayak_font/src}/atlas.rs | 0 kayak_font/src/color_flags.rs | 62 - kayak_font/src/contour.rs | 107 -- kayak_font/src/font.rs | 275 +-- .../font/sdf => kayak_font/src}/glyph.rs | 0 kayak_font/src/lib.rs | 34 +- .../font/sdf => kayak_font/src}/metrics.rs | 0 kayak_font/src/msdf.rs | 171 -- kayak_font/src/path_collector.rs | 134 -- kayak_font/src/path_element.rs | 191 -- kayak_font/src/recolor.rs | 124 -- .../src/renderer}/font_texture_cache.rs | 28 +- kayak_font/src/renderer/mod.rs | 2 + kayak_font/src/sdf.rs | 140 +- kayak_font/src/ttf_parser.rs | 69 - kayak_font/src/utils.rs | 61 - 29 files changed, 1741 insertions(+), 1675 deletions(-) delete mode 100644 bevy_kayak_ui/src/render/unified/font/font.rs delete mode 100644 bevy_kayak_ui/src/render/unified/font/sdf/mod.rs create mode 100644 kayak_font/assets/roboto.json delete mode 100644 kayak_font/examples/main.rs delete mode 100644 kayak_font/examples/simple.rs delete mode 100644 kayak_font/resources/Roboto-Regular.ttf rename {bevy_kayak_ui/src/render/unified/font/sdf => kayak_font/src}/atlas.rs (100%) delete mode 100644 kayak_font/src/color_flags.rs delete mode 100644 kayak_font/src/contour.rs rename {bevy_kayak_ui/src/render/unified/font/sdf => kayak_font/src}/glyph.rs (100%) rename {bevy_kayak_ui/src/render/unified/font/sdf => kayak_font/src}/metrics.rs (100%) delete mode 100644 kayak_font/src/msdf.rs delete mode 100644 kayak_font/src/path_collector.rs delete mode 100644 kayak_font/src/path_element.rs delete mode 100644 kayak_font/src/recolor.rs rename {bevy_kayak_ui/src/render/unified/font => kayak_font/src/renderer}/font_texture_cache.rs (94%) create mode 100644 kayak_font/src/renderer/mod.rs delete mode 100644 kayak_font/src/ttf_parser.rs delete mode 100644 kayak_font/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index e9ff38d..d3b708d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,15 +120,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - [[package]] name = "arrayvec" version = "0.7.2" @@ -302,8 +293,8 @@ source = "git+https://github.com/bevyengine/bevy?rev=38c7d5eb9e81ab8e1aec0367359 dependencies = [ "Inflector", "bevy_macro_utils", - "quote 1.0.10", - "syn 1.0.81", + "quote", + "syn", ] [[package]] @@ -341,9 +332,9 @@ version = "0.5.0" source = "git+https://github.com/bevyengine/bevy?rev=38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c#38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" dependencies = [ "bevy_macro_utils", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -440,6 +431,7 @@ dependencies = [ "crevice", "kayak_components", "kayak_core", + "kayak_font", "kayak_render_macros", "serde", "serde_json", @@ -466,8 +458,8 @@ version = "0.5.0" source = "git+https://github.com/bevyengine/bevy?rev=38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c#38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" dependencies = [ "cargo-manifest", - "quote 1.0.10", - "syn 1.0.81", + "quote", + "syn", ] [[package]] @@ -538,9 +530,9 @@ version = "0.5.0" source = "git+https://github.com/bevyengine/bevy?rev=38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c#38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" dependencies = [ "bevy_macro_utils", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", "uuid", ] @@ -820,8 +812,8 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2", + "quote", "regex", "rustc-hash", "shlex", @@ -875,9 +867,9 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1221,9 +1213,9 @@ name = "crevice-derive" version = "0.8.0" source = "git+https://github.com/bevyengine/bevy?rev=38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c#38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1323,10 +1315,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2", + "quote", "strsim", - "syn 1.0.81", + "syn", ] [[package]] @@ -1336,8 +1328,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core", - "quote 1.0.10", - "syn 1.0.81", + "quote", + "syn", ] [[package]] @@ -1356,9 +1348,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1377,9 +1369,9 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f9c37d395456d9c1785499421c6288931b6e3dbc2500acb95b8adaa0e69db3" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1425,16 +1417,6 @@ dependencies = [ "serde", ] -[[package]] -name = "euclid" -version = "0.19.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1" -dependencies = [ - "euclid_macros", - "num-traits", -] - [[package]] name = "euclid" version = "0.22.6" @@ -1444,17 +1426,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "euclid_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", -] - [[package]] name = "event-listener" version = "2.5.1" @@ -1656,9 +1627,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f2a9333e0f9c7bca94dfc20bcf44fa12a61eeec662d6e007563ff748aa59c70" dependencies = [ "inflections", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1729,7 +1700,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" dependencies = [ - "euclid 0.22.6", + "euclid", "svg_fmt", ] @@ -1927,13 +1898,10 @@ dependencies = [ name = "kayak_font" version = "0.1.0" dependencies = [ - "arrayvec 0.7.2", - "bitflags", - "fontdue", - "lyon_geom", - "lyon_path", - "png", - "ttf-parser 0.13.3", + "bevy", + "serde", + "serde_json", + "serde_path_to_error", ] [[package]] @@ -1943,9 +1911,9 @@ dependencies = [ "kayak_core", "pretty_assertions", "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2050,26 +2018,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "lyon_geom" -version = "0.12.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb9bf1f1d43be9a9cc2343a7a096dc113cc25337a13e8f99721b01d1d548b60" -dependencies = [ - "arrayvec 0.4.12", - "euclid 0.19.9", - "num-traits", -] - -[[package]] -name = "lyon_path" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dc8e0746b7cca11960b602f7fe037bb067746a01eab4aa502fed1494544843" -dependencies = [ - "lyon_geom", -] - [[package]] name = "mach" version = "0.2.3" @@ -2295,9 +2243,9 @@ checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" dependencies = [ "darling", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2318,12 +2266,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nom" version = "5.1.2" @@ -2367,9 +2309,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2440,9 +2382,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" dependencies = [ "proc-macro-crate 1.1.0", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -2585,7 +2527,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" dependencies = [ - "unicode-xid 0.2.2", + "unicode-xid", ] [[package]] @@ -2630,9 +2572,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", "version_check", ] @@ -2642,27 +2584,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2", + "quote", "version_check", ] -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - [[package]] name = "proc-macro2" version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ - "unicode-xid 0.2.2", + "unicode-xid", ] [[package]] @@ -2671,22 +2604,13 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9926767b8b8244d7b6b64546585121d193c3d0b4856ccd656b7bfa9deb91ab6a" -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.32", + "proc-macro2", ] [[package]] @@ -2906,9 +2830,9 @@ version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3069,11 +2993,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2", + "quote", "serde", "serde_derive", - "syn 1.0.81", + "syn", ] [[package]] @@ -3083,13 +3007,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2", + "quote", "serde", "serde_derive", "serde_json", "sha1", - "syn 1.0.81", + "syn", ] [[package]] @@ -3120,26 +3044,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - [[package]] name = "syn" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] @@ -3166,9 +3079,9 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3208,9 +3121,9 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3280,12 +3193,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -3356,9 +3263,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] @@ -3380,7 +3287,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ - "quote 1.0.10", + "quote", "wasm-bindgen-macro-support", ] @@ -3390,9 +3297,9 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3419,7 +3326,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1577ecc4f6992b9e965878ac594efb24eed2bdf089c11f45b3d1c5f216e2e30" dependencies = [ - "arrayvec 0.7.2", + "arrayvec", "js-sys", "log", "naga", @@ -3440,7 +3347,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bdcbfa4885b32c2b1feb2faeb8b6a76065b752b8f08751b82f994e937687f46" dependencies = [ - "arrayvec 0.7.2", + "arrayvec", "bitflags", "cfg_aliases", "copyless", @@ -3462,7 +3369,7 @@ version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e493835d9edb153d5c8a9d8d016e1811dbe32ddb707a110be1453c7b051d3ec" dependencies = [ - "arrayvec 0.7.2", + "arrayvec", "ash", "bit-set", "bitflags", diff --git a/bevy_kayak_ui/Cargo.toml b/bevy_kayak_ui/Cargo.toml index 074e9d3..3e9f474 100644 --- a/bevy_kayak_ui/Cargo.toml +++ b/bevy_kayak_ui/Cargo.toml @@ -9,6 +9,7 @@ bevy = { git = "https://github.com/bevyengine/bevy", rev = "38c7d5eb9e81ab8e1aec kayak_core = { path = "../kayak_core" } kayak_components = { path = "../kayak_components" } kayak_render_macros = { path = "../kayak_render_macros" } +kayak_font = { path = "../kayak_font" } #kayak_font = { path = "../kayak_font" } crevice = { git = "https://github.com/bevyengine/bevy", rev = "38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" } serde = "1.0" diff --git a/bevy_kayak_ui/src/render/unified/font/extract.rs b/bevy_kayak_ui/src/render/unified/font/extract.rs index be26bc8..6bc4a3a 100644 --- a/bevy_kayak_ui/src/render/unified/font/extract.rs +++ b/bevy_kayak_ui/src/render/unified/font/extract.rs @@ -4,13 +4,14 @@ use bevy::{ sprite2::Rect, }; use kayak_core::render_primitive::RenderPrimitive; +use kayak_font::KayakFont; use crate::{ render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType}, to_bevy_color, BevyContext, }; -use super::{font::KayakFont, font_mapping::FontMapping}; +use super::font_mapping::FontMapping; pub fn extract_texts( mut commands: Commands, diff --git a/bevy_kayak_ui/src/render/unified/font/font.rs b/bevy_kayak_ui/src/render/unified/font/font.rs deleted file mode 100644 index e081b89..0000000 --- a/bevy_kayak_ui/src/render/unified/font/font.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::collections::HashMap; - -use super::sdf::Sdf; -use bevy::{prelude::Handle, reflect::TypeUuid, render2::texture::Image}; - -#[derive(Debug, Clone, TypeUuid)] -#[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"] -pub struct KayakFont { - pub sdf: Sdf, - pub atlas_image: Handle<Image>, - char_ids: HashMap<char, u32>, -} - -impl KayakFont { - pub fn new(sdf: Sdf, atlas_image: Handle<Image>) -> Self { - Self { - sdf, - atlas_image, - char_ids: HashMap::default(), - } - } - - pub fn generate_char_ids(&mut self) { - let mut count = 0; - for glyph in self.sdf.glyphs.iter() { - self.char_ids.insert(glyph.unicode, count); - count += 1; - } - } - - pub fn get_char_id(&self, c: char) -> Option<u32> { - self.char_ids.get(&c).and_then(|id| Some(*id)) - } -} diff --git a/bevy_kayak_ui/src/render/unified/font/font_mapping.rs b/bevy_kayak_ui/src/render/unified/font/font_mapping.rs index eeb405a..743eedd 100644 --- a/bevy_kayak_ui/src/render/unified/font/font_mapping.rs +++ b/bevy_kayak_ui/src/render/unified/font/font_mapping.rs @@ -1,6 +1,5 @@ use bevy::{prelude::Handle, utils::HashMap}; - -use super::font::KayakFont; +use kayak_font::KayakFont; pub struct FontMapping { count: u16, diff --git a/bevy_kayak_ui/src/render/unified/font/mod.rs b/bevy_kayak_ui/src/render/unified/font/mod.rs index 9728e44..5ea79d0 100644 --- a/bevy_kayak_ui/src/render/unified/font/mod.rs +++ b/bevy_kayak_ui/src/render/unified/font/mod.rs @@ -12,20 +12,14 @@ use bevy::{ }, utils::HashSet, }; - -use self::{extract::extract_texts, sdf::Sdf}; - -use super::pipeline::UnifiedPipeline; +use kayak_font::{KayakFont, Sdf, FontTextureCache}; mod extract; -mod font; mod font_mapping; -mod font_texture_cache; -mod sdf; -pub use font::*; +use self::extract::extract_texts; +use super::pipeline::UnifiedPipeline; pub use font_mapping::*; -pub(crate) use font_texture_cache::FontTextureCache; #[derive(Default)] pub struct TextRendererPlugin; @@ -169,5 +163,5 @@ fn create_and_update_font_cache_texture( mut font_texture_cache: ResMut<FontTextureCache>, images: Res<RenderAssets<Image>>, ) { - font_texture_cache.process_new(&device, &queue, &pipeline, &images); + font_texture_cache.process_new(&device, &queue, pipeline.into_inner(), &images); } diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs b/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs deleted file mode 100644 index 07f9b9a..0000000 --- a/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -use self::{atlas::Atlas, glyph::Glyph, metrics::Metrics}; -use bevy::math::Vec2; -use serde::Deserialize; - -mod atlas; -mod glyph; -mod metrics; - -#[derive(Deserialize, Debug, Clone)] -pub struct Sdf { - pub atlas: Atlas, - metrics: Metrics, - pub glyphs: Vec<Glyph>, - kerning: Vec<KerningData>, -} - -#[derive(serde::Deserialize, Debug, Clone, Copy)] -pub struct KerningData { - pub unicode1: u32, - pub unicode2: u32, - pub advance: f32, -} - -impl Sdf { - pub fn from_string(data: String) -> Sdf { - let value: Sdf = match serde_path_to_error::deserialize( - &mut serde_json::Deserializer::from_str(&data), - ) { - Ok(v) => v, - Err(err) => { - let path = err.path().to_string(); - dbg!(err); - panic!("failed to deserialize json! path: {}", path); - } - }; - - value - } - - pub fn max_glyph_size(&self) -> Vec2 { - let mut size = Vec2::new(0.0, 0.0); - self.glyphs.iter().for_each(|glyph| { - if let Some(atlas_bounds) = glyph.atlas_bounds { - let atlas_size = atlas_bounds.size(); - if atlas_size.x > size.x { - size.x = atlas_size.x; - } - if atlas_size.y > size.y { - size.y = atlas_size.y; - } - } - }); - - size - } -} - -#[test] -fn test_sdf_loader() { - let sdf = Sdf::from_string(include_str!("../../../../../../msdfgen/test.json").to_string()); - dbg!(sdf.max_glyph_size()); -} diff --git a/bevy_kayak_ui/src/render/unified/pipeline.rs b/bevy_kayak_ui/src/render/unified/pipeline.rs index c2d1819..5bf1121 100644 --- a/bevy_kayak_ui/src/render/unified/pipeline.rs +++ b/bevy_kayak_ui/src/render/unified/pipeline.rs @@ -31,8 +31,8 @@ use bevy::{ }; use bytemuck::{Pod, Zeroable}; use crevice::std140::AsStd140; +use kayak_font::{FontRenderingPipeline, FontTextureCache, KayakFont}; -use super::font::{FontTextureCache, KayakFont}; use super::UNIFIED_SHADER_HANDLE; use crate::render::ui_pass::TransparentUI; @@ -55,6 +55,12 @@ const QUAD_VERTEX_POSITIONS: &[Vec3] = &[ const_vec3!([1.0, 1.0, 0.0]), ]; +impl FontRenderingPipeline for UnifiedPipeline { + fn get_font_image_layout(&self) -> &BindGroupLayout { + &self.font_image_layout + } +} + impl FromWorld for UnifiedPipeline { fn from_world(world: &mut World) -> Self { let world = world.cell(); @@ -586,7 +592,7 @@ impl Draw<TransparentUI> for DrawUI { let unified_pipeline = unified_pipeline.into_inner(); if let Some(font_handle) = extracted_quad.font_handle.as_ref() { if let Some(image_bindings) = - font_texture_cache.into_inner().bind_groups.get(font_handle) + font_texture_cache.into_inner().get_binding(font_handle) { pass.set_bind_group(1, image_bindings, &[]); } else { diff --git a/kayak_font/Cargo.toml b/kayak_font/Cargo.toml index 79436b7..f5ded9a 100644 --- a/kayak_font/Cargo.toml +++ b/kayak_font/Cargo.toml @@ -6,12 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -arrayvec = "0.7" -bitflags = "1.0" -lyon_path = "0.12" -lyon_geom = "0.12" -fontdue = "0.6" -ttf-parser = "0.13" - -[dev-dependencies] -png = "0.16.3" +bevy = { git = "https://github.com/bevyengine/bevy", rev = "38c7d5eb9e81ab8e1aec03673599b25a9aa0c69c" } +serde = "1.0" +serde_json = "1.0" +serde_path_to_error = "0.1" diff --git a/kayak_font/assets/roboto.json b/kayak_font/assets/roboto.json new file mode 100644 index 0000000..6000877 --- /dev/null +++ b/kayak_font/assets/roboto.json @@ -0,0 +1,1529 @@ +{ + "atlas": { + "type": "msdf", + "distanceRange": 2, + "size": 32.875, + "width": 212, + "height": 212, + "yOrigin": "bottom" + }, + "metrics": { + "emSize": 1, + "lineHeight": 1.171875, + "ascender": 0.927734375, + "descender": -0.244140625, + "underlineY": -0.09765625, + "underlineThickness": 0.048828125 + }, + "glyphs": [ + { + "unicode": 32, + "advance": 0.24755859375 + }, + { + "unicode": 33, + "advance": 0.25732421875, + "planeBounds": { + "left": 0.040337044023288991, + "bottom": -0.042654059232414394, + "right": 0.22284654972671103, + "top": 0.7482204654824145 + }, + "atlasBounds": { + "left": 112.5, + "bottom": 120.5, + "right": 118.5, + "top": 146.5 + } + }, + { + "unicode": 34, + "advance": 0.31982421875, + "planeBounds": { + "left": 0.029865917597433435, + "bottom": 0.47730327649714832, + "right": 0.30363017615256649, + "top": 0.78148578600285168 + }, + "atlasBounds": { + "left": 57.5, + "bottom": 6.5, + "right": 66.5, + "top": 16.5 + } + }, + { + "unicode": 35, + "advance": 0.61572265625, + "planeBounds": { + "left": 0.026383896744296635, + "bottom": -0.039968512357414394, + "right": 0.63474891575570347, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 119.5, + "bottom": 120.5, + "right": 139.5, + "top": 146.5 + } + }, + { + "unicode": 36, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.022450726295152143, + "bottom": -0.13959645318441066, + "right": 0.53956099245484801, + "top": 0.86420582818441072 + }, + "atlasBounds": { + "left": 70.5, + "bottom": 178.5, + "right": 87.5, + "top": 211.5 + } + }, + { + "unicode": 37, + "advance": 0.732421875, + "planeBounds": { + "left": 0.02030730156844112, + "bottom": -0.055177637832699571, + "right": 0.71992707343155904, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 188.5, + "bottom": 184.5, + "right": 211.5, + "top": 211.5 + } + }, + { + "unicode": 38, + "advance": 0.62158203125, + "planeBounds": { + "left": 0.014592740019011461, + "bottom": -0.055177637832699571, + "right": 0.65337600998098866, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 36.5, + "bottom": 147.5, + "right": 57.5, + "top": 174.5 + } + }, + { + "unicode": 39, + "advance": 0.17431640625, + "planeBounds": { + "left": 0.010868435123574159, + "bottom": 0.48096538587214832, + "right": 0.16295968987642587, + "top": 0.78514789537785168 + }, + "atlasBounds": { + "left": 67.5, + "bottom": 6.5, + "right": 72.5, + "top": 16.5 + } + }, + { + "unicode": 40, + "advance": 0.341796875, + "planeBounds": { + "left": 0.026547276021863096, + "bottom": -0.26115156398526612, + "right": 0.36114803647813687, + "top": 0.83390547023526618 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 175.5, + "right": 11.5, + "top": 211.5 + } + }, + { + "unicode": 41, + "advance": 0.34765625, + "planeBounds": { + "left": -0.019595302103136911, + "bottom": -0.26115156398526612, + "right": 0.31500545835313687, + "top": 0.83390547023526618 + }, + "atlasBounds": { + "left": 12.5, + "bottom": 175.5, + "right": 23.5, + "top": 211.5 + } + }, + { + "unicode": 42, + "advance": 0.4306640625, + "planeBounds": { + "left": -0.028258116979562771, + "bottom": 0.26080438302043729, + "right": 0.45843389822956265, + "top": 0.74749639822956271 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 0.5, + "right": 16.5, + "top": 16.5 + } + }, + { + "unicode": 43, + "advance": 0.56689453125, + "planeBounds": { + "left": -0.0072351027804181973, + "bottom": 0.025895615494296635, + "right": 0.57071166528041828, + "top": 0.63426063450570347 + }, + "atlasBounds": { + "left": 154.5, + "bottom": 17.5, + "right": 173.5, + "top": 37.5 + } + }, + { + "unicode": 44, + "advance": 0.1962890625, + "planeBounds": { + "left": -0.024188487701996185, + "bottom": -0.1846343646031369, + "right": 0.18873926895199622, + "top": 0.14996639585313687 + }, + "atlasBounds": { + "left": 49.5, + "bottom": 5.5, + "right": 56.5, + "top": 16.5 + } + }, + { + "unicode": 45, + "advance": 0.27587890625, + "planeBounds": { + "left": -0.01488422350285174, + "bottom": 0.22595632574857413, + "right": 0.28929828600285168, + "top": 0.37804758050142584 + }, + "atlasBounds": { + "left": 201.5, + "bottom": 86.5, + "right": 211.5, + "top": 91.5 + } + }, + { + "unicode": 46, + "advance": 0.26318359375, + "planeBounds": { + "left": 0.035210090898288991, + "bottom": -0.042914909101711009, + "right": 0.21771959660171103, + "top": 0.13959459660171103 + }, + "atlasBounds": { + "left": 105.5, + "bottom": 10.5, + "right": 111.5, + "top": 16.5 + } + }, + { + "unicode": 47, + "advance": 0.412109375, + "planeBounds": { + "left": -0.032336100879277595, + "bottom": -0.10090434143298473, + "right": 0.42393766337927752, + "top": 0.75080668518298488 + }, + "atlasBounds": { + "left": 156.5, + "bottom": 183.5, + "right": 171.5, + "top": 211.5 + } + }, + { + "unicode": 48, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.021962445045152143, + "bottom": -0.055177637832699571, + "right": 0.53907271120484801, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 58.5, + "bottom": 147.5, + "right": 75.5, + "top": 174.5 + } + }, + { + "unicode": 49, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.052182041646863096, + "bottom": -0.038259527982414394, + "right": 0.38678280210313687, + "top": 0.7526149967324145 + }, + "atlasBounds": { + "left": 140.5, + "bottom": 120.5, + "right": 151.5, + "top": 146.5 + } + }, + { + "unicode": 50, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.011391991444866975, + "bottom": -0.035085699857414394, + "right": 0.5589205085551332, + "top": 0.7557888248574145 + }, + "atlasBounds": { + "left": 152.5, + "bottom": 120.5, + "right": 170.5, + "top": 146.5 + } + }, + { + "unicode": 51, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.012685101295152145, + "bottom": -0.055177637832699571, + "right": 0.52979536745484801, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 76.5, + "bottom": 147.5, + "right": 93.5, + "top": 174.5 + } + }, + { + "unicode": 52, + "advance": 0.5615234375, + "planeBounds": { + "left": -0.0065026809054181973, + "bottom": -0.039968512357414394, + "right": 0.57144408715541828, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 171.5, + "bottom": 120.5, + "right": 190.5, + "top": 146.5 + } + }, + { + "unicode": 53, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.04002885129515215, + "bottom": -0.044851324857414394, + "right": 0.55713911745484801, + "top": 0.7460231998574145 + }, + "atlasBounds": { + "left": 142.5, + "bottom": 92.5, + "right": 159.5, + "top": 118.5 + } + }, + { + "unicode": 54, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.03050736692015215, + "bottom": -0.044607184232414394, + "right": 0.54761763307984801, + "top": 0.7462673404824145 + }, + "atlasBounds": { + "left": 180.5, + "bottom": 92.5, + "right": 197.5, + "top": 118.5 + } + }, + { + "unicode": 55, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.0040677726948669755, + "bottom": -0.039968512357414394, + "right": 0.5515962898051332, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 146.5, + "bottom": 65.5, + "right": 164.5, + "top": 91.5 + } + }, + { + "unicode": 56, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.022206585670152143, + "bottom": -0.055177637832699571, + "right": 0.53931685182984801, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 118.5, + "bottom": 147.5, + "right": 135.5, + "top": 174.5 + } + }, + { + "unicode": 57, + "advance": 0.5615234375, + "planeBounds": { + "left": 0.013905804420152145, + "bottom": -0.035329840482414394, + "right": 0.53101607057984801, + "top": 0.7555446842324145 + }, + "atlasBounds": { + "left": 44.5, + "bottom": 38.5, + "right": 61.5, + "top": 64.5 + } + }, + { + "unicode": 58, + "advance": 0.2421875, + "planeBounds": { + "left": 0.030571419023288991, + "bottom": -0.040266493880703365, + "right": 0.21308092472671103, + "top": 0.56809852513070347 + }, + "atlasBounds": { + "left": 201.5, + "bottom": 65.5, + "right": 207.5, + "top": 85.5 + } + }, + { + "unicode": 59, + "advance": 0.21142578125, + "planeBounds": { + "left": -0.013202159576996183, + "bottom": -0.18442735563212925, + "right": 0.19972559707699622, + "top": 0.57602891813212931 + }, + "atlasBounds": { + "left": 98.5, + "bottom": 39.5, + "right": 105.5, + "top": 64.5 + } + }, + { + "unicode": 60, + "advance": 0.50830078125, + "planeBounds": { + "left": -0.0084827263545627658, + "bottom": 0.05711869504515215, + "right": 0.47820928885456265, + "top": 0.57422896120484801 + }, + "atlasBounds": { + "left": 174.5, + "bottom": 20.5, + "right": 190.5, + "top": 37.5 + } + }, + { + "unicode": 61, + "advance": 0.548828125, + "planeBounds": { + "left": 0.034486023645437264, + "bottom": 0.15293971304657797, + "right": 0.52117803885456271, + "top": 0.51795872445342206 + }, + "atlasBounds": { + "left": 32.5, + "bottom": 4.5, + "right": 48.5, + "top": 16.5 + } + }, + { + "unicode": 62, + "advance": 0.5224609375, + "planeBounds": { + "left": 0.030579773645437264, + "bottom": 0.05760697629515215, + "right": 0.51727178885456271, + "top": 0.57471724245484801 + }, + "atlasBounds": { + "left": 191.5, + "bottom": 20.5, + "right": 207.5, + "top": 37.5 + } + }, + { + "unicode": 63, + "advance": 0.47216796875, + "planeBounds": { + "left": -0.0087268669795627658, + "bottom": -0.037771246732414394, + "right": 0.47796514822956265, + "top": 0.7531032779824145 + }, + "atlasBounds": { + "left": 62.5, + "bottom": 38.5, + "right": 78.5, + "top": 64.5 + } + }, + { + "unicode": 64, + "advance": 0.89794921875, + "planeBounds": { + "left": 0.012067393169925377, + "bottom": -0.26313160943441061, + "right": 0.89419667073646536, + "top": 0.74067067193441072 + }, + "atlasBounds": { + "left": 88.5, + "bottom": 178.5, + "right": 117.5, + "top": 211.5 + } + }, + { + "unicode": 65, + "advance": 0.65234375, + "planeBounds": { + "left": -0.02339387030655888, + "bottom": -0.039968512357414394, + "right": 0.67622590155655904, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 20.5, + "bottom": 38.5, + "right": 43.5, + "top": 64.5 + } + }, + { + "unicode": 66, + "advance": 0.62255859375, + "planeBounds": { + "left": 0.050698632069866974, + "bottom": -0.039968512357414394, + "right": 0.5982271491801332, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 79.5, + "bottom": 38.5, + "right": 97.5, + "top": 64.5 + } + }, + { + "unicode": 67, + "advance": 0.65087890625, + "planeBounds": { + "left": 0.027604599869296632, + "bottom": -0.055177637832699571, + "right": 0.63596961888070347, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 136.5, + "bottom": 147.5, + "right": 156.5, + "top": 174.5 + } + }, + { + "unicode": 68, + "advance": 0.65576171875, + "planeBounds": { + "left": 0.050626225344581804, + "bottom": -0.039968512357414394, + "right": 0.62857299340541828, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 38.5, + "right": 19.5, + "top": 64.5 + } + }, + { + "unicode": 69, + "advance": 0.568359375, + "planeBounds": { + "left": 0.04979447629515215, + "bottom": -0.039968512357414394, + "right": 0.56690474245484801, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 183.5, + "bottom": 65.5, + "right": 200.5, + "top": 91.5 + } + }, + { + "unicode": 70, + "advance": 0.552734375, + "planeBounds": { + "left": 0.04417924192015215, + "bottom": -0.039968512357414394, + "right": 0.56128950807984801, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 165.5, + "bottom": 65.5, + "right": 182.5, + "top": 91.5 + } + }, + { + "unicode": 71, + "advance": 0.68115234375, + "planeBounds": { + "left": 0.014104458769011461, + "bottom": -0.055177637832699571, + "right": 0.65288772873098866, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 32.5, + "bottom": 119.5, + "right": 53.5, + "top": 146.5 + } + }, + { + "unicode": 72, + "advance": 0.712890625, + "planeBounds": { + "left": 0.051530381119296635, + "bottom": -0.039968512357414394, + "right": 0.65989540013070347, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 125.5, + "bottom": 65.5, + "right": 145.5, + "top": 91.5 + } + }, + { + "unicode": 73, + "advance": 0.27197265625, + "planeBounds": { + "left": 0.044975715898288991, + "bottom": -0.039968512357414394, + "right": 0.22748522160171103, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 205.5, + "bottom": 92.5, + "right": 211.5, + "top": 118.5 + } + }, + { + "unicode": 74, + "advance": 0.5517578125, + "planeBounds": { + "left": -0.0083109924548478552, + "bottom": -0.044851324857414394, + "right": 0.50879927370484801, + "top": 0.7460231998574145 + }, + "atlasBounds": { + "left": 86.5, + "bottom": 65.5, + "right": 103.5, + "top": 91.5 + } + }, + { + "unicode": 75, + "advance": 0.626953125, + "planeBounds": { + "left": 0.050797959244296635, + "bottom": -0.039968512357414394, + "right": 0.65916297825570347, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 65.5, + "bottom": 65.5, + "right": 85.5, + "top": 91.5 + } + }, + { + "unicode": 76, + "advance": 0.5380859375, + "planeBounds": { + "left": 0.039540570045152094, + "bottom": -0.039968512357414394, + "right": 0.5566508362048479, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 47.5, + "bottom": 65.5, + "right": 64.5, + "top": 91.5 + } + }, + { + "unicode": 77, + "advance": 0.873046875, + "planeBounds": { + "left": 0.040842034517585606, + "bottom": -0.039968512357414394, + "right": 0.8317165592324145, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 20.5, + "bottom": 65.5, + "right": 46.5, + "top": 91.5 + } + }, + { + "unicode": 78, + "advance": 0.712890625, + "planeBounds": { + "left": 0.051530381119296635, + "bottom": -0.039968512357414394, + "right": 0.65989540013070347, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 104.5, + "bottom": 65.5, + "right": 124.5, + "top": 91.5 + } + }, + { + "unicode": 79, + "advance": 0.6875, + "planeBounds": { + "left": 0.024114224394011459, + "bottom": -0.055177637832699571, + "right": 0.66289749435598866, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 72.5, + "bottom": 119.5, + "right": 93.5, + "top": 146.5 + } + }, + { + "unicode": 80, + "advance": 0.630859375, + "planeBounds": { + "left": 0.049161381594581804, + "bottom": -0.039968512357414394, + "right": 0.62710814965541828, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 65.5, + "right": 19.5, + "top": 91.5 + } + }, + { + "unicode": 81, + "advance": 0.6875, + "planeBounds": { + "left": 0.021184536894011459, + "bottom": -0.15598079550855509, + "right": 0.65996780685598866, + "top": 0.75656673300855526 + }, + "atlasBounds": { + "left": 134.5, + "bottom": 181.5, + "right": 155.5, + "top": 211.5 + } + }, + { + "unicode": 82, + "advance": 0.61572265625, + "planeBounds": { + "left": 0.051114506594581804, + "bottom": -0.039968512357414394, + "right": 0.62906127465541828, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 160.5, + "bottom": 92.5, + "right": 179.5, + "top": 118.5 + } + }, + { + "unicode": 83, + "advance": 0.59326171875, + "planeBounds": { + "left": 0.0083898972195818027, + "bottom": -0.055177637832699571, + "right": 0.58633666528041828, + "top": 0.76611513783269969 + }, + "atlasBounds": { + "left": 192.5, + "bottom": 147.5, + "right": 211.5, + "top": 174.5 + } + }, + { + "unicode": 84, + "advance": 0.5966796875, + "planeBounds": { + "left": -0.020563509980988541, + "bottom": -0.039968512357414394, + "right": 0.61821975998098866, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 120.5, + "bottom": 92.5, + "right": 141.5, + "top": 118.5 + } + }, + { + "unicode": 85, + "advance": 0.6484375, + "planeBounds": { + "left": 0.036710209719581804, + "bottom": -0.044851324857414394, + "right": 0.61465697778041828, + "top": 0.7460231998574145 + }, + "atlasBounds": { + "left": 100.5, + "bottom": 92.5, + "right": 119.5, + "top": 118.5 + } + }, + { + "unicode": 86, + "advance": 0.63623046875, + "planeBounds": { + "left": -0.03120637030655888, + "bottom": -0.039968512357414394, + "right": 0.66841340155655904, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 76.5, + "bottom": 92.5, + "right": 99.5, + "top": 118.5 + } + }, + { + "unicode": 87, + "advance": 0.88720703125, + "planeBounds": { + "left": -0.0085198580085550802, + "bottom": -0.039968512357414394, + "right": 0.90402767050855526, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 45.5, + "bottom": 92.5, + "right": 75.5, + "top": 118.5 + } + }, + { + "unicode": 88, + "advance": 0.626953125, + "planeBounds": { + "left": -0.0051826506059885393, + "bottom": -0.039968512357414394, + "right": 0.63360061935598866, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 23.5, + "bottom": 92.5, + "right": 44.5, + "top": 118.5 + } + }, + { + "unicode": 89, + "advance": 0.6005859375, + "planeBounds": { + "left": -0.03528435420627371, + "bottom": -0.039968512357414394, + "right": 0.63391716670627374, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 92.5, + "right": 22.5, + "top": 118.5 + } + }, + { + "unicode": 90, + "advance": 0.5986328125, + "planeBounds": { + "left": -0.0034012595057033666, + "bottom": -0.039968512357414394, + "right": 0.60496375950570347, + "top": 0.7509060123574145 + }, + "atlasBounds": { + "left": 191.5, + "bottom": 120.5, + "right": 211.5, + "top": 146.5 + } + }, + { + "unicode": 91, + "advance": 0.26513671875, + "planeBounds": { + "left": 0.026447948847433435, + "bottom": -0.18703214115969582, + "right": 0.30021220740256649, + "top": 0.84718839115969591 + }, + "atlasBounds": { + "left": 37.5, + "bottom": 177.5, + "right": 46.5, + "top": 211.5 + } + }, + { + "unicode": 92, + "advance": 0.41015625, + "planeBounds": { + "left": -0.017199382129277595, + "bottom": -0.10090434143298473, + "right": 0.43907438212927752, + "top": 0.75080668518298488 + }, + "atlasBounds": { + "left": 172.5, + "bottom": 183.5, + "right": 187.5, + "top": 211.5 + } + }, + { + "unicode": 93, + "advance": 0.26513671875, + "planeBounds": { + "left": -0.040202441777566537, + "bottom": -0.18703214115969582, + "right": 0.23356181677756652, + "top": 0.84718839115969591 + }, + "atlasBounds": { + "left": 60.5, + "bottom": 177.5, + "right": 69.5, + "top": 211.5 + } + }, + { + "unicode": 94, + "advance": 0.41796875, + "planeBounds": { + "left": -0.0049199441539924237, + "bottom": 0.32051950897100762, + "right": 0.42093556915399238, + "top": 0.74637502227899244 + }, + "atlasBounds": { + "left": 17.5, + "bottom": 2.5, + "right": 31.5, + "top": 16.5 + } + }, + { + "unicode": 95, + "advance": 0.451171875, + "planeBounds": { + "left": -0.032969195579847906, + "bottom": -0.11291086175142585, + "right": 0.4841410705798479, + "top": 0.039180393001425839 + }, + "atlasBounds": { + "left": 112.5, + "bottom": 11.5, + "right": 129.5, + "top": 16.5 + } + }, + { + "unicode": 96, + "advance": 0.30908203125, + "planeBounds": { + "left": -0.0072434574025665669, + "bottom": 0.57175877792300378, + "right": 0.26652080115256649, + "top": 0.78468653457699622 + }, + "atlasBounds": { + "left": 95.5, + "bottom": 9.5, + "right": 104.5, + "top": 16.5 + } + }, + { + "unicode": 97, + "advance": 0.5439453125, + "planeBounds": { + "left": 0.012685101295152093, + "bottom": -0.055231478730988541, + "right": 0.5297953674548479, + "top": 0.58355179123098866 + }, + "atlasBounds": { + "left": 191.5, + "bottom": 43.5, + "right": 208.5, + "top": 64.5 + } + }, + { + "unicode": 98, + "advance": 0.56103515625, + "planeBounds": { + "left": 0.03343705442015215, + "bottom": -0.040529200332699564, + "right": 0.55054732057984801, + "top": 0.78076357533269969 + }, + "atlasBounds": { + "left": 54.5, + "bottom": 119.5, + "right": 71.5, + "top": 146.5 + } + }, + { + "unicode": 99, + "advance": 0.5234375, + "planeBounds": { + "left": 0.0090229919201521448, + "bottom": -0.055231478730988541, + "right": 0.52613325807984801, + "top": 0.58355179123098866 + }, + "atlasBounds": { + "left": 138.5, + "bottom": 43.5, + "right": 155.5, + "top": 64.5 + } + }, + { + "unicode": 100, + "advance": 0.56396484375, + "planeBounds": { + "left": 0.010731976295152145, + "bottom": -0.040529200332699564, + "right": 0.52784224245484801, + "top": 0.78076357533269969 + }, + "atlasBounds": { + "left": 14.5, + "bottom": 119.5, + "right": 31.5, + "top": 146.5 + } + }, + { + "unicode": 101, + "advance": 0.52978515625, + "planeBounds": { + "left": 0.010976116920152145, + "bottom": -0.055231478730988541, + "right": 0.52808638307984801, + "top": 0.58355179123098866 + }, + "atlasBounds": { + "left": 173.5, + "bottom": 43.5, + "right": 190.5, + "top": 64.5 + } + }, + { + "unicode": 102, + "advance": 0.34716796875, + "planeBounds": { + "left": -0.008753787428707251, + "bottom": -0.030519434707699571, + "right": 0.38668347492870719, + "top": 0.79077334095769969 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 119.5, + "right": 13.5, + "top": 146.5 + } + }, + { + "unicode": 103, + "advance": 0.56103515625, + "planeBounds": { + "left": 0.011464398170152145, + "bottom": -0.24560732533269961, + "right": 0.52857466432984801, + "top": 0.57568545033269969 + }, + "atlasBounds": { + "left": 174.5, + "bottom": 147.5, + "right": 191.5, + "top": 174.5 + } + }, + { + "unicode": 104, + "advance": 0.55078125, + "planeBounds": { + "left": 0.032777039270437264, + "bottom": -0.035646387832699571, + "right": 0.51946905447956271, + "top": 0.78564638783269969 + }, + "atlasBounds": { + "left": 157.5, + "bottom": 147.5, + "right": 173.5, + "top": 174.5 + } + }, + { + "unicode": 105, + "advance": 0.24267578125, + "planeBounds": { + "left": 0.031059700273288991, + "bottom": -0.035085699857414394, + "right": 0.21356920597671103, + "top": 0.7557888248574145 + }, + "atlasBounds": { + "left": 198.5, + "bottom": 92.5, + "right": 204.5, + "top": 118.5 + } + }, + { + "unicode": 106, + "advance": 0.23876953125, + "planeBounds": { + "left": -0.06852275427756653, + "bottom": -0.24823903130941069, + "right": 0.20524150427756652, + "top": 0.75556325005941072 + }, + "atlasBounds": { + "left": 118.5, + "bottom": 178.5, + "right": 127.5, + "top": 211.5 + } + }, + { + "unicode": 107, + "advance": 0.5068359375, + "planeBounds": { + "left": 0.028798382545152094, + "bottom": -0.035646387832699571, + "right": 0.5459086487048479, + "top": 0.78564638783269969 + }, + "atlasBounds": { + "left": 100.5, + "bottom": 147.5, + "right": 117.5, + "top": 174.5 + } + }, + { + "unicode": 108, + "advance": 0.24267578125, + "planeBounds": { + "left": 0.045292263248574161, + "bottom": -0.035646387832699571, + "right": 0.19738351800142587, + "top": 0.78564638783269969 + }, + "atlasBounds": { + "left": 94.5, + "bottom": 147.5, + "right": 99.5, + "top": 174.5 + } + }, + { + "unicode": 109, + "advance": 0.87646484375, + "planeBounds": { + "left": 0.027586034042300436, + "bottom": -0.035139540755703365, + "right": 0.84887880970769969, + "top": 0.57322547825570347 + }, + "atlasBounds": { + "left": 82.5, + "bottom": 17.5, + "right": 109.5, + "top": 37.5 + } + }, + { + "unicode": 110, + "advance": 0.5517578125, + "planeBounds": { + "left": 0.032777039270437264, + "bottom": -0.035139540755703365, + "right": 0.51946905447956271, + "top": 0.57322547825570347 + }, + "atlasBounds": { + "left": 18.5, + "bottom": 17.5, + "right": 34.5, + "top": 37.5 + } + }, + { + "unicode": 111, + "advance": 0.5703125, + "planeBounds": { + "left": 0.011147850819866975, + "bottom": -0.055231478730988541, + "right": 0.5586763679301332, + "top": 0.58355179123098866 + }, + "atlasBounds": { + "left": 119.5, + "bottom": 43.5, + "right": 137.5, + "top": 64.5 + } + }, + { + "unicode": 112, + "advance": 0.56103515625, + "planeBounds": { + "left": 0.03294877317015215, + "bottom": -0.24316591908269961, + "right": 0.55005903932984801, + "top": 0.57812685658269969 + }, + "atlasBounds": { + "left": 18.5, + "bottom": 147.5, + "right": 35.5, + "top": 174.5 + } + }, + { + "unicode": 113, + "advance": 0.568359375, + "planeBounds": { + "left": 0.010487835670152145, + "bottom": -0.24316591908269961, + "right": 0.52759810182984801, + "top": 0.57812685658269969 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 147.5, + "right": 17.5, + "top": 174.5 + } + }, + { + "unicode": 114, + "advance": 0.33837890625, + "planeBounds": { + "left": 0.028744541646863096, + "bottom": -0.035139540755703365, + "right": 0.36334530210313687, + "top": 0.57322547825570347 + }, + "atlasBounds": { + "left": 70.5, + "bottom": 17.5, + "right": 81.5, + "top": 37.5 + } + }, + { + "unicode": 115, + "advance": 0.515625, + "planeBounds": { + "left": 0.013001648645437234, + "bottom": -0.055231478730988541, + "right": 0.49969366385456265, + "top": 0.58355179123098866 + }, + "atlasBounds": { + "left": 156.5, + "bottom": 43.5, + "right": 172.5, + "top": 64.5 + } + }, + { + "unicode": 116, + "advance": 0.32666015625, + "planeBounds": { + "left": -0.03431614632842208, + "bottom": -0.041776823906844049, + "right": 0.330702865078422, + "top": 0.68826119890684423 + }, + "atlasBounds": { + "left": 106.5, + "bottom": 40.5, + "right": 118.5, + "top": 64.5 + } + }, + { + "unicode": 117, + "advance": 0.55126953125, + "planeBounds": { + "left": 0.031068054895437264, + "bottom": -0.044905165755703365, + "right": 0.51776007010456271, + "top": 0.56345985325570347 + }, + "atlasBounds": { + "left": 110.5, + "bottom": 17.5, + "right": 126.5, + "top": 37.5 + } + }, + { + "unicode": 118, + "advance": 0.484375, + "planeBounds": { + "left": -0.017588336204847906, + "bottom": -0.040022353255703365, + "right": 0.4995219299548479, + "top": 0.56834266575570347 + }, + "atlasBounds": { + "left": 35.5, + "bottom": 17.5, + "right": 52.5, + "top": 37.5 + } + }, + { + "unicode": 119, + "advance": 0.75146484375, + "planeBounds": { + "left": -0.020925543607414394, + "bottom": -0.040022353255703365, + "right": 0.7699489811074145, + "top": 0.56834266575570347 + }, + "atlasBounds": { + "left": 127.5, + "bottom": 17.5, + "right": 153.5, + "top": 37.5 + } + }, + { + "unicode": 120, + "advance": 0.49560546875, + "planeBounds": { + "left": -0.011728961204847855, + "bottom": -0.040022353255703365, + "right": 0.50538130495484801, + "top": 0.56834266575570347 + }, + "atlasBounds": { + "left": 0.5, + "bottom": 17.5, + "right": 17.5, + "top": 37.5 + } + }, + { + "unicode": 121, + "advance": 0.47314453125, + "planeBounds": { + "left": -0.022715289329847906, + "bottom": -0.25317568470769958, + "right": 0.4943949768298479, + "top": 0.56811709095769969 + }, + "atlasBounds": { + "left": 94.5, + "bottom": 119.5, + "right": 111.5, + "top": 146.5 + } + }, + { + "unicode": 122, + "advance": 0.49560546875, + "planeBounds": { + "left": 0.0093395392704372342, + "bottom": -0.040022353255703365, + "right": 0.49603155447956265, + "top": 0.56834266575570347 + }, + "atlasBounds": { + "left": 53.5, + "bottom": 17.5, + "right": 69.5, + "top": 37.5 + } + }, + { + "unicode": 123, + "advance": 0.33837890625, + "planeBounds": { + "left": -0.0033102869534220817, + "bottom": -0.21657315678469582, + "right": 0.361708724453422, + "top": 0.81764737553469591 + }, + "atlasBounds": { + "left": 47.5, + "bottom": 177.5, + "right": 59.5, + "top": 211.5 + } + }, + { + "unicode": 124, + "advance": 0.24365234375, + "planeBounds": { + "left": 0.045780544498574161, + "bottom": -0.16672298300855509, + "right": 0.19787179925142587, + "top": 0.74582454550855526 + }, + "atlasBounds": { + "left": 128.5, + "bottom": 181.5, + "right": 133.5, + "top": 211.5 + } + }, + { + "unicode": 125, + "advance": 0.33837890625, + "planeBounds": { + "left": -0.02503880257842208, + "bottom": -0.21657315678469582, + "right": 0.339980208828422, + "top": 0.81764737553469591 + }, + "atlasBounds": { + "left": 24.5, + "bottom": 177.5, + "right": 36.5, + "top": 211.5 + } + }, + { + "unicode": 126, + "advance": 0.68017578125, + "planeBounds": { + "left": 0.020940396269011466, + "bottom": 0.15706318322243343, + "right": 0.65972366623098866, + "top": 0.43082744177756649 + }, + "atlasBounds": { + "left": 73.5, + "bottom": 7.5, + "right": 94.5, + "top": 16.5 + } + } + ], + "kerning": [] +} \ No newline at end of file diff --git a/kayak_font/examples/main.rs b/kayak_font/examples/main.rs deleted file mode 100644 index 2bed828..0000000 --- a/kayak_font/examples/main.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::{fs::File, io::BufWriter}; - -use kayak_font::{ - compute_msdf, recolor_contours, rescale_contours, Angle, FlatPathBuilder, PathCollector, Point, - Rect, -}; - -pub fn main() { - let font_data = include_bytes!("../resources/Roboto-Regular.ttf"); - let face = ttf_parser::Face::from_slice(font_data, 0).unwrap(); - - let char_dim: u32 = 64; - - let c = 'A'; - if let Some(glyph) = face.glyph_index(c) { - let mut path_collector = PathCollector::new(); - path_collector.scale = 1.0; //0.0001; //1024 as f32 / face.units_per_em() as f32; - let rect = face.outline_glyph(glyph, &mut path_collector).unwrap(); - let contours = path_collector.build(); - let uv_rect = Rect::new(Point::new(0.0, 0.0), lyon_geom::math::Size::new(1.0, 1.0)); - - let font_rect = Rect::new( - Point::new(rect.x_min as f32, rect.y_min as f32), - lyon_geom::math::Size::new(rect.width() as f32, rect.height() as f32), - ); - - let (contours, _) = rescale_contours(contours, font_rect, uv_rect, 0); - - let contours = recolor_contours(contours, Angle::degrees(3.0), 1); - let msdf = compute_msdf(&contours, char_dim as usize); - - let file = File::create(format!("./test-{}.png", c)).unwrap(); - let ref mut w = BufWriter::new(file); - - let pixels: Vec<u8> = msdf - .iter() - .flat_map(|y| { - y.iter().flat_map(|pixel| { - vec![ - (pixel.0 * 255.0) as u8, - (pixel.1 * 255.0) as u8, - (pixel.2 * 255.0) as u8, - 255u8, - ] - }) - }) - .collect(); - - let mut encoder = png::Encoder::new(w, char_dim, char_dim); - encoder.set_color(png::ColorType::RGBA); - let mut writer = encoder.write_header().unwrap(); - writer.write_image_data(&pixels).unwrap(); - } -} diff --git a/kayak_font/examples/simple.rs b/kayak_font/examples/simple.rs deleted file mode 100644 index 97efddb..0000000 --- a/kayak_font/examples/simple.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::{fs::File, io::BufWriter}; - -use kayak_font::Font; - -fn main() { - let font_bytes = include_bytes!("../resources/Roboto-Regular.ttf"); - let mut font = Font::new(font_bytes, (64, 64)); - - font.add_character('A'); - font.add_character('B'); - font.add_character('C'); - font.add_character('!'); - font.add_character('&'); - - // Characters that have already been calculated wont be calculated again! - for _ in 0..1000000 { - font.add_character('A'); - } - - let dimensions = font.cache.dimensions; - for (c, _, pixels) in font.get_data_to_process() { - let file = File::create(format!("./test-{}.png", c)).unwrap(); - let ref mut w = BufWriter::new(file); - - let mut encoder = png::Encoder::new(w, dimensions.0, dimensions.1); - encoder.set_color(png::ColorType::RGBA); - let mut writer = encoder.write_header().unwrap(); - writer.write_image_data(&pixels).unwrap(); - } -} diff --git a/kayak_font/resources/Roboto-Regular.ttf b/kayak_font/resources/Roboto-Regular.ttf deleted file mode 100644 index 2b6392ffe8712b9c5450733320cd220d6c0f4bce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171272 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	$$K|G-##kgg<a}7Wmh5J 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 diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/atlas.rs b/kayak_font/src/atlas.rs similarity index 100% rename from bevy_kayak_ui/src/render/unified/font/sdf/atlas.rs rename to kayak_font/src/atlas.rs diff --git a/kayak_font/src/color_flags.rs b/kayak_font/src/color_flags.rs deleted file mode 100644 index 7322912..0000000 --- a/kayak_font/src/color_flags.rs +++ /dev/null @@ -1,62 +0,0 @@ -bitflags::bitflags! { - pub struct ColorFlags: u32 { - const BLACK = 0b000; - const RED = 0b001; - const GREEN = 0b010; - const BLUE = 0b100; - const YELLOW = 0b011; - const MAGENTA = 0b101; - const CYAN = 0b110; - const WHITE = 0b111; - } -} - -impl ColorFlags { - pub(crate) fn switch(self, seed: &mut u64) -> Self { - match self { - ColorFlags::WHITE | ColorFlags::BLACK => { - const START: [ColorFlags; 3] = - [ColorFlags::CYAN, ColorFlags::MAGENTA, ColorFlags::YELLOW]; - let tr = START[(*seed % 3) as usize]; - *seed /= 3; - tr - } - ColorFlags::RED | ColorFlags::GREEN | ColorFlags::BLUE => self ^ ColorFlags::WHITE, - _ => { - let v = self.bits(); - let v = (v << (1 + (*seed & 1))) & 0b111; - let v = match v.count_ones() { - 0 => 0b11, /* Somehow we lost all the bits. Default to yellow */ - 1 => v | 0b001, /* We just shifted a bit off the left side, add one on the right */ - 2 => v, /* We already have 2 bits, nothing to do */ - _ => unreachable!(), /* There should never be 3+ bits set */ - }; - *seed >>= 1; - - Self::from_bits_truncate(v) - } - } - } - - pub(crate) fn switch_banned(self, seed: &mut u64, banned: ColorFlags) -> Self { - let combined = self & banned; - match combined { - ColorFlags::RED | ColorFlags::GREEN | ColorFlags::BLUE => combined ^ ColorFlags::WHITE, - _ => self.switch(seed), - } - } - - pub fn float_color(self) -> [f32; 3] { - match self { - ColorFlags::BLACK => [0.0f32, 0.0f32, 0.0f32], - ColorFlags::RED => [1.0f32, 0.0f32, 0.0f32], - ColorFlags::GREEN => [0.0f32, 1.0f32, 0.0f32], - ColorFlags::BLUE => [0.0f32, 0.0f32, 1.0f32], - ColorFlags::CYAN => [0.0f32, 1.0f32, 1.0f32], - ColorFlags::MAGENTA => [1.0f32, 0.0f32, 1.0f32], - ColorFlags::YELLOW => [1.0f32, 1.0f32, 0.0f32], - ColorFlags::WHITE => [1.0f32, 1.0f32, 1.0f32], - _ => [0.5, 0.7, 0.5], - } - } -} diff --git a/kayak_font/src/contour.rs b/kayak_font/src/contour.rs deleted file mode 100644 index 6b21056..0000000 --- a/kayak_font/src/contour.rs +++ /dev/null @@ -1,107 +0,0 @@ -use lyon_geom::math::{Point, Rect}; -use lyon_path::Segment; - -use crate::path_element::PathElement; - -/// A list of path elements forming a closed loop -#[derive(Clone, Debug)] -pub struct Contour { - pub elements: Vec<PathElement>, -} - -impl Contour { - pub fn winding(&self) -> f32 { - let shoelace = |a: Point, b: Point| (b.x - a.x) * (a.y + b.y); - let n = self.elements.len(); - match n { - 0 => 0.0, - 1 => { - let a = self.elements[0].sample(0.0); - let b = self.elements[0].sample(1.0 / 3.0); - let c = self.elements[0].sample(2.0 / 3.0); - - shoelace(a, b) + shoelace(b, c) + shoelace(c, a) - } - 2 => { - let a = self.elements[0].sample(0.0); - let b = self.elements[0].sample(0.5); - let c = self.elements[1].sample(0.0); - let d = self.elements[1].sample(0.5); - - shoelace(a, b) + shoelace(b, c) + shoelace(c, d) + shoelace(d, a) - } - _ => { - let mut total = 0.0; - let mut prev = self.elements[n - 1].sample(0.0); - - for e in &self.elements { - let curr = e.sample(0.0); - total += shoelace(prev, curr); - prev = curr; - } - - total - } - } - .signum() - } -} - -/// Rescale contours so they fit in the provided rectangle. -/// Returns the scaled contours along with the transformation used to rescale the contours -pub fn rescale_contours( - mut contours: Vec<Contour>, - initial_bounds: Rect, - bounds: Rect, - _units_per_em: u16, -) -> (Vec<Contour>, lyon_geom::math::Transform2D) { - // let (new_width, new_height) = if initial_bounds.size.width > initial_bounds.size.height { - // let new_width = 1.0; - // let new_height = aspect_ratio_height( - // initial_bounds.size.height, - // initial_bounds.size.width, - // new_width, - // ); - - // (new_width, new_height) - // } else { - // let new_height = 1.0; - // let new_width = aspect_ratio_width( - // initial_bounds.size.height, - // initial_bounds.size.width, - // new_height, - // ); - - // (new_width, new_height) - // }; - - - // let x_scale = new_width / initial_bounds.size.width; - // let y_scale = new_height / initial_bounds.size.height; - - let initial_scale = initial_bounds.size.height.max(initial_bounds.size.width); - let bounds_scale = bounds.size.width.max(bounds.size.height); - - // let size = 128.0 / units_per_em as f32; - let transformation = lyon_geom::math::Transform2D::create_translation( - -initial_bounds.origin.x as f32, - -initial_bounds.origin.y as f32, - ) - .post_scale(bounds_scale / initial_scale, bounds_scale / initial_scale) - .post_translate(bounds.origin.to_vector()); - for contour in &mut contours { - for mut elem in &mut contour.elements { - elem.segment = match elem.segment { - Segment::Line(s) => Segment::Line(s.transform(&transformation)), - Segment::Quadratic(s) => Segment::Quadratic(s.transform(&transformation)), - Segment::Cubic(s) => Segment::Cubic(s.transform(&transformation)), - Segment::Arc(s) => Segment::Arc(lyon_geom::Arc { - center: transformation.transform_point(&s.center), - ..s - }), - } - } - } - - (contours, transformation) -} diff --git a/kayak_font/src/font.rs b/kayak_font/src/font.rs index 81f4977..2a2b06d 100644 --- a/kayak_font/src/font.rs +++ b/kayak_font/src/font.rs @@ -1,267 +1,36 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; -use lyon_geom::math::{Angle, Point, Rect, Size}; -use lyon_path::builder::FlatPathBuilder; -use crate::{compute_msdf, recolor_contours, rescale_contours, PathCollector}; +use bevy::{prelude::Handle, reflect::TypeUuid, render2::texture::Image}; -#[derive(Debug, Clone)] -pub struct FontCache { - count: usize, - pub dimensions: (u32, u32), - chars: HashMap<char, (usize, Vec<u8>)>, - needs_processing: HashSet<usize>, - id_to_char_mappings: HashMap<usize, char>, -} - -impl FontCache { - pub fn new(texture_size: (u32, u32)) -> Self { - Self { - count: 0, - dimensions: texture_size, - chars: HashMap::default(), - needs_processing: HashSet::default(), - id_to_char_mappings: HashMap::default(), - } - } - - pub fn add_character(&mut self, c: char) { - self.chars.insert(c, (self.count, vec![])); - self.id_to_char_mappings.insert(self.count, c); - self.count += 1; - } - - fn set_texture(&mut self, c: char, texture_data: Vec<Vec<(f32, f32, f32)>>) { - // let pixels: Vec<u8> = texture_data - // .iter() - // .flat_map(|y| { - // y.iter().flat_map(|pixel| { - // vec![ - // (pixel.0 * 255.0) as u8, - // (pixel.1 * 255.0) as u8, - // (pixel.2 * 255.0) as u8, - // 255u8, - // ] - // }) - // }) - // .collect(); - let pixels = texture_data - .iter() - .flat_map(|x| { - x.iter() - .flat_map(|p| { - vec![ - p.0.to_le_bytes(), - p.1.to_le_bytes(), - p.2.to_le_bytes(), - 1.0f32.to_le_bytes(), - ] - .into_iter() - .flatten() - .collect::<Vec<u8>>() - }) - .collect::<Vec<u8>>() - }) - .collect(); - self.chars.insert(c, (self.count, pixels)); - self.needs_processing.insert(self.count); - self.id_to_char_mappings.insert(self.count, c); - self.count += 1; - } +use crate::Sdf; - pub fn has_character(&self, c: char) -> bool { - self.chars.contains_key(&c) - } - - fn get_dimensions(&self) -> (u32, u32) { - self.dimensions - } +#[derive(Debug, Clone, TypeUuid)] +#[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"] +pub struct KayakFont { + pub sdf: Sdf, + pub atlas_image: Handle<Image>, + char_ids: HashMap<char, u32>, } -#[derive(Debug, Clone)] -pub struct Font { - internal_face: ttf_parser::Face<'static>, - font: fontdue::Font, - pub cache: FontCache, -} - -impl Font { - pub fn new(font_data: &'static [u8], texture_size: (u32, u32)) -> Font { - Font { - internal_face: ttf_parser::Face::from_slice(&font_data, 0).unwrap(), - font: fontdue::Font::from_bytes(font_data.clone(), fontdue::FontSettings::default()) - .unwrap(), - cache: FontCache::new(texture_size), - } - } - - /// Adds all of the common known characters. - pub fn add_all_common(&mut self) { - let chars = vec![ - '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '~', '!', '@', '#', - '$', '%', '^', '&', '*', '(', ')', '_', '+', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\\', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', - '|', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 'A', 'S', 'D', 'F', 'G', - 'H', 'J', 'K', 'L', ':', '"', 'z', 'x', 'c', 'v', 'b', 'n', 'n', 'm', ',', '.', '/', - 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', - ]; - - for char in chars { - self.add_character(char); - } - } - - pub fn get_layout( - &self, - content: &String, - font_size: f32, - original_font_size: f32, - max_glyph_size: (f32, f32), - ) -> Vec<(char, (f32, f32), (f32, f32))> { - let mut layout = - fontdue::layout::Layout::new(fontdue::layout::CoordinateSystem::PositiveYDown); - layout.append( - &[&self.font], - &fontdue::layout::TextStyle::new(content, font_size, 0), - ); - let font_ratio = font_size / original_font_size; - let resized_max_glyph_size = ( - (max_glyph_size.0 * font_ratio).round(), - (max_glyph_size.1 * font_ratio).round(), - ); - - let glyphs = layout.glyphs(); - let glyphs: Vec<_> = glyphs - .iter() - .filter_map(|glyph_position| { - if glyph_position.parent == ' ' { - return None; - } - // let metrics = self.font.metrics(glyph_position.parent, font_size); - - let shift_y = resized_max_glyph_size.1 - glyph_position.height as f32; - Some(( - glyph_position.parent, - (glyph_position.x, glyph_position.y - shift_y), - resized_max_glyph_size, - )) - }) - .collect(); - glyphs - } - - // pub fn get_size(&self, c: char, font_size: f32) -> (f32, f32) { - // if let Some(glyph) = self.internal_face.glyph_index(c) { - // // Collect our path's from the glyph's outline shape. - // let mut path_collector = PathCollector::new(); - // let rect = self - // .internal_face - // .outline_glyph(glyph, &mut path_collector) - // .unwrap(); - // let metrics = font_size / self.font.units_per_em(); - - // (width as f32 * metrics, height as f32 * metrics) - // } else { - // panic!("") - // } - // } - - pub fn get_char_id(&self, c: char) -> usize { - if self.cache.has_character(c) { - if let Some((id, _)) = self.cache.chars.get(&c) { - return *id; - } +impl KayakFont { + pub fn new(sdf: Sdf, atlas_image: Handle<Image>) -> Self { + Self { + sdf, + atlas_image, + char_ids: HashMap::default(), } - panic!("No char found!"); } - pub fn add_character(&mut self, c: char) { - if !self.cache.has_character(c) { - if let Some(glyph) = self.internal_face.glyph_index(c) { - // Collect our path's from the glyph's outline shape. - let mut path_collector = PathCollector::new(); - let rect = self - .internal_face - .outline_glyph(glyph, &mut path_collector) - .unwrap(); - let contours = path_collector.build(); - - // Bounds of our texture in UV's - // TODO: Allow this to change because some people may want texture atlases instead. - let uv_rect = Rect::new(Point::new(0.0, 0.0), Size::new(1.0, 1.0)); - - // Bounds of our rect in font space coords. - let font_rect = Rect::new( - Point::new(rect.x_min as f32, rect.y_min as f32), - Size::new(rect.width() as f32, rect.height() as f32), - ); - - let (contours, _transform) = rescale_contours( - contours, - font_rect, - uv_rect, - self.internal_face.units_per_em(), - ); - let contours = recolor_contours(contours, Angle::degrees(3.0), 1); - let msdf = compute_msdf(&contours, self.cache.get_dimensions().0 as usize); - - self.cache.set_texture(c, msdf); - } + pub fn generate_char_ids(&mut self) { + let mut count = 0; + for glyph in self.sdf.glyphs.iter() { + self.char_ids.insert(glyph.unicode, count); + count += 1; } } - pub fn get_data_to_process<'b>(&'b mut self) -> Vec<(char, usize, &'b Vec<u8>)> { - let data = self - .cache - .needs_processing - .iter() - .filter_map(|unprocessed_id| { - if let Some(c) = self.cache.id_to_char_mappings.get(unprocessed_id) { - if let Some((_, data)) = self.cache.chars.get(c) { - return Some((*c, *unprocessed_id, data)); - } - } - - None - }) - .collect(); - - self.cache.needs_processing.clear(); - - data + pub fn get_char_id(&self, c: char) -> Option<u32> { + self.char_ids.get(&c).and_then(|id| Some(*id)) } - - // Checks the given chars and returns ones that haven't been seen before. - pub fn check_chars(&self, chars: std::str::Chars<'_>) -> Vec<char> { - chars - .into_iter() - .filter(|c| !self.cache.chars.contains_key(&c)) - .collect() - } - - pub fn units_per_em(&self) -> f32 { - self.font.units_per_em() - } -} - -fn get_new_size(org_width: f32, new_width: f32, org_height: f32, new_height: f32) -> (f32, f32) { - let ratio = calculate_ratio(org_width, new_width, org_height, new_height); - // let ratio = new_width / new_height; - (org_width * ratio, org_height * ratio) -} - -pub fn calculate_ratio(org_width: f32, new_width: f32, org_height: f32, new_height: f32) -> f32 { - let area_size; - let image_size; - - if new_height * org_width > new_width * org_height { - area_size = new_height; - image_size = org_height; - } else { - area_size = new_width; - image_size = org_width; - } - - let ratio = area_size / image_size; - ratio } diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/glyph.rs b/kayak_font/src/glyph.rs similarity index 100% rename from bevy_kayak_ui/src/render/unified/font/sdf/glyph.rs rename to kayak_font/src/glyph.rs diff --git a/kayak_font/src/lib.rs b/kayak_font/src/lib.rs index 6a97d01..3ffc493 100644 --- a/kayak_font/src/lib.rs +++ b/kayak_font/src/lib.rs @@ -1,28 +1,14 @@ -#![allow(dead_code)] -mod color_flags; -mod contour; +mod atlas; mod font; -mod msdf; -mod path_collector; -mod path_element; -mod recolor; +mod glyph; +mod metrics; +mod renderer; mod sdf; -mod ttf_parser; -mod utils; -pub use color_flags::ColorFlags; -pub use contour::{rescale_contours, Contour}; -pub use font::{Font, FontCache}; -pub use lyon_geom::math::{Angle, Point, Rect, Vector}; -pub use lyon_path::builder::FlatPathBuilder; -pub use msdf::compute_msdf; -pub use path_collector::PathCollector; -pub use path_element::PathElement; -pub use recolor::recolor_contours; -pub use sdf::compute_sdf; +pub use atlas::*; +pub use font::*; +pub use glyph::*; +pub use metrics::*; +pub use sdf::*; -pub(crate) fn median(a: f32, b: f32, c: f32) -> f32 { - let min = |a: f32, b: f32| a.min(b); - let max = |a: f32, b: f32| a.max(b); - max(min(a, b), min(max(a, b), c)) -} +pub use renderer::*; diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/metrics.rs b/kayak_font/src/metrics.rs similarity index 100% rename from bevy_kayak_ui/src/render/unified/font/sdf/metrics.rs rename to kayak_font/src/metrics.rs diff --git a/kayak_font/src/msdf.rs b/kayak_font/src/msdf.rs deleted file mode 100644 index 8429e93..0000000 --- a/kayak_font/src/msdf.rs +++ /dev/null @@ -1,171 +0,0 @@ -use lyon_geom::math::Vector; - -use crate::{contour::Contour, median, utils::EdgeDistance, ColorFlags}; - -/// Computes an MSDF from a list of contours. The returned vectors are a `dim` by `dim` -/// matrix of signed distance values. The output represents the signed distances to the contours -/// within [0, 1] x [0, 1] -pub fn compute_msdf(contours: &[Contour], dim: usize) -> Vec<Vec<(f32, f32, f32)>> { - #[derive(Copy, Clone, PartialEq)] - struct MultiDistance { - r: f32, - g: f32, - b: f32, - med: f32, - } - impl MultiDistance { - fn new(v: f32) -> Self { - Self { - r: v, - g: v, - b: v, - med: v, - } - } - } - let scale: f32 = 1.0 / (dim as f32); - let windings: Vec<i32> = contours.iter().map(|c| c.winding() as i32).collect(); - - (0..dim) - .map(|y| { - let py = (y as f32 + 0.5) * scale; - (0..dim) - .map(|x| { - // We assume there is at least 1 contour - // If there isn't make everything magenta - if contours.len() == 0 { - return (1.0f32, 0.0, 1.0); - } - - let px = (x as f32 + 0.5) * scale; - let p = Vector::new(px, py); - - let mut neg_dist = 1e24f32; - let mut pos_dist = -1e24f32; - let mut d = 1e24f32; - let mut winding = 0; - let mut contour_distances = Vec::new(); - contour_distances.reserve(contours.len()); - - let mut sr = EdgeDistance::new(); - let mut sg = EdgeDistance::new(); - let mut sb = EdgeDistance::new(); - - for (i, contour) in contours.iter().enumerate() { - let mut contour_min_r = EdgeDistance::new(); - let mut contour_min_g = EdgeDistance::new(); - let mut contour_min_b = EdgeDistance::new(); - - for elem in &contour.elements { - let (d, na) = elem.distance(p.to_point()); - - if elem.color.contains(ColorFlags::RED) && d < contour_min_r.dist { - contour_min_r.dist = d; - contour_min_r.edge = Some(&elem); - contour_min_r.nearest_approach = na; - } - if elem.color.contains(ColorFlags::GREEN) && d < contour_min_g.dist { - contour_min_g.dist = d; - contour_min_g.edge = Some(&elem); - contour_min_g.nearest_approach = na; - } - if elem.color.contains(ColorFlags::BLUE) && d < contour_min_b.dist { - contour_min_b.dist = d; - contour_min_b.edge = Some(&elem); - contour_min_b.nearest_approach = na; - } - } - - if contour_min_r.dist < sr.dist { - sr = contour_min_r; - } - if contour_min_g.dist < sg.dist { - sg = contour_min_g; - } - if contour_min_b.dist < sb.dist { - sb = contour_min_b; - } - - let med_min_dist = median( - contour_min_r.dist.distance, - contour_min_g.dist.distance, - contour_min_b.dist.distance, - ) - .abs(); - if med_min_dist < d { - d = med_min_dist; - winding = -windings[i]; - } - - contour_min_r.to_pseudodistance(p); - contour_min_g.to_pseudodistance(p); - contour_min_b.to_pseudodistance(p); - - let med_min_dist = median( - contour_min_r.dist.distance, - contour_min_g.dist.distance, - contour_min_b.dist.distance, - ); - - let mut msd = MultiDistance::new(med_min_dist); - msd.r = contour_min_r.dist.distance; - msd.g = contour_min_g.dist.distance; - msd.b = contour_min_b.dist.distance; - msd.med = med_min_dist; - contour_distances.push(msd); - if windings[i] > 0 - && med_min_dist >= 0.0 - && med_min_dist.abs() < pos_dist.abs() - { - pos_dist = med_min_dist; - } - if windings[i] < 0 - && med_min_dist <= 0.0 - && med_min_dist.abs() < neg_dist.abs() - { - neg_dist = med_min_dist; - } - } - - assert!(contour_distances.len() == windings.len()); - - sr.to_pseudodistance(p); - sg.to_pseudodistance(p); - sb.to_pseudodistance(p); - - let mut mmsd = MultiDistance::new(-1e24); - if pos_dist >= 0.0 && pos_dist.abs() <= neg_dist.abs() { - mmsd.med = -1e24; - winding = 1; - for (csd, cw) in contour_distances.iter().zip(windings.iter()) { - if *cw > 0 && csd.med > mmsd.med && csd.med.abs() < neg_dist.abs() { - mmsd = *csd; - } - } - } else if neg_dist <= 0.0 && neg_dist.abs() <= pos_dist.abs() { - mmsd.med = 1e24; - winding = -1; - for (csd, cw) in contour_distances.iter().zip(windings.iter()) { - if *cw < 0 && csd.med < mmsd.med && csd.med.abs() < pos_dist.abs() { - mmsd = *csd; - } - } - } - for (csd, w) in contour_distances.iter().zip(windings.iter()) { - if *w != winding && csd.med.abs() < mmsd.med.abs() { - mmsd = *csd; - } - } - - if median(sr.dist.distance, sg.dist.distance, sb.dist.distance) == mmsd.med { - mmsd.r = sr.dist.distance; - mmsd.g = sg.dist.distance; - mmsd.b = sb.dist.distance; - } - - (mmsd.r / 0.5, mmsd.g / 0.5, mmsd.b / 0.5) - }) - .collect() - }) - .collect() -} diff --git a/kayak_font/src/path_collector.rs b/kayak_font/src/path_collector.rs deleted file mode 100644 index 077bc44..0000000 --- a/kayak_font/src/path_collector.rs +++ /dev/null @@ -1,134 +0,0 @@ -use lyon_geom::math::{Angle, Point, Vector}; -use lyon_path::{ - builder::{FlatPathBuilder, PathBuilder}, - Segment, -}; - -use crate::{color_flags::ColorFlags, contour::Contour, path_element::PathElement}; - -/// This is a path collector which produces our custom contour type. -pub struct PathCollector { - /// The start point of the last contour - pub(crate) contour_start: Point, - /// The current pen location - pub(crate) pen: Point, - /// in-flight path elements - pub(crate) elements: Vec<PathElement>, - /// Completed contours - pub(crate) contours: Vec<Contour>, - pub scale: f32, -} - -impl PathCollector { - pub fn new() -> Self { - Self { - contour_start: Point::new(0.0, 0.0), - pen: Point::new(0.0, 0.0), - elements: Vec::new(), - contours: Vec::new(), - scale: 1.0, - } - } -} - -impl PathBuilder for PathCollector { - fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point) { - self.elements.push(PathElement::new( - Segment::Quadratic(lyon_geom::QuadraticBezierSegment { - from: self.pen * self.scale, - to: to * self.scale, - ctrl: ctrl * self.scale, - }), - ColorFlags::WHITE, - )); - self.pen = to; - } - - fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point) { - self.elements.push(PathElement::new( - Segment::Cubic(lyon_geom::CubicBezierSegment { - from: self.pen * self.scale, - to: to * self.scale, - ctrl1: ctrl1 * self.scale, - ctrl2: ctrl2 * self.scale, - }), - ColorFlags::WHITE, - )); - - self.pen = to; - } - - fn arc(&mut self, _center: Point, _radii: Vector, _sweep_angle: Angle, _x_rotation: Angle) { - unimplemented!() - } -} - -impl FlatPathBuilder for PathCollector { - type PathType = Vec<Contour>; - - fn move_to(&mut self, to: Point) { - self.pen = to * self.scale; - self.contour_start = to * self.scale; - } - - fn line_to(&mut self, to: Point) { - self.elements.push(PathElement::new( - Segment::Line(lyon_geom::LineSegment { - from: self.pen * self.scale, - to: to * self.scale, - }), - ColorFlags::WHITE, - )); - self.pen = to * self.scale; - } - - fn close(&mut self) { - if (self.pen - self.contour_start).length() > 1E-14 { - self.elements.push(PathElement::new( - Segment::Line(lyon_geom::LineSegment { - from: self.pen * self.scale, - to: self.contour_start * self.scale, - }), - ColorFlags::WHITE, - )); - } - - self.pen = self.contour_start; - let elements = std::mem::replace(&mut self.elements, Vec::new()); - - self.contours.push(Contour { elements }); - } - - fn build(self) -> Self::PathType { - let mut contours = self.contours; - if self.elements.len() > 0 { - let final_contour = Contour { - elements: self.elements, - }; - - contours.push(final_contour); - } - - contours - } - - fn build_and_reset(&mut self) -> Self::PathType { - let elements = std::mem::replace(&mut self.elements, Vec::new()); - if elements.len() > 0 { - let final_contour = Contour { elements }; - - self.contours.push(final_contour); - } - - let tr = std::mem::replace(&mut self.contours, Vec::new()); - - self.contour_start = Point::new(0.0, 0.0); - self.pen = Point::new(0.0, 0.0); - - tr - } - - fn current_position(&self) -> Point { - self.pen - } -} diff --git a/kayak_font/src/path_element.rs b/kayak_font/src/path_element.rs deleted file mode 100644 index 7500fcc..0000000 --- a/kayak_font/src/path_element.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::{color_flags::ColorFlags, utils::AugmentedDistance}; -use lyon_geom::math::{Point, Vector}; -use lyon_path::Segment; - -#[derive(Clone, Debug, Copy)] -pub struct PathElement { - pub segment: Segment, - pub color: ColorFlags, -} - -impl PathElement { - pub fn new(segment: Segment, color: ColorFlags) -> PathElement { - Self { segment, color } - } - - pub fn sample(&self, t: f32) -> Point { - match self.segment { - Segment::Line(s) => s.sample(t), - Segment::Quadratic(s) => s.sample(t), - Segment::Cubic(s) => s.sample(t), - Segment::Arc(s) => s.sample(t), - } - } - - pub fn direction(&self, f: f32) -> Vector { - use lyon_geom::Segment as SegmentTrait; - let f = f.min(1.0).max(0.0); - match self.segment { - Segment::Line(s) => s.derivative(f), - Segment::Quadratic(s) => s.derivative(f), - Segment::Cubic(s) => s.derivative(f), - Segment::Arc(s) => s.derivative(f), - } - } - - /// Split a path element into 3rds - pub fn split_in_thirds(&self) -> [PathElement; 3] { - macro_rules! segment_case { - ($i:expr, $s:expr) => {{ - let (a, b) = ($i).split(1.0 / 3.0); - let (b, c) = b.split(1.0 / 2.0); - - [a, b, c] - .into_iter() - .map(|x| PathElement::new(($s)(x), self.color)) - .collect() - }}; - } - let segments: arrayvec::ArrayVec<PathElement, 3> = match self.segment { - Segment::Line(s) => segment_case!(s, Segment::Line), - Segment::Quadratic(s) => segment_case!(s, Segment::Quadratic), - Segment::Cubic(s) => segment_case!(s, Segment::Cubic), - Segment::Arc(s) => segment_case!(s, Segment::Arc), - }; - - segments - .into_inner() - .expect("We should have precisely the right capacity") - } - - /// Computes the distance from p to this path element - /// Returns the distance from the point to this path element, - /// and the distance along this element to the closest point. - pub fn distance(&self, p: Point) -> (AugmentedDistance, f32) { - use lyon_geom::{LineSegment, QuadraticBezierSegment}; - match self.segment { - Segment::Line(LineSegment { from: s, to: e }) => { - let aq = p - s; - let ab = e - s; - let f = aq.dot(ab) / ab.dot(ab); - let eq = if f >= 0.5 { p - e } else { p - s }; - - let dist_to_endpoint = eq.length(); - let endpoint_sd = AugmentedDistance::new( - aq.cross(ab).signum() * dist_to_endpoint, - // ab.normalize().cross(eq.normalize()), - ab.normalize().dot(eq.normalize()).abs(), - ); - - if 0.0 < f && f < 1.0 { - let ortho = Vector::new(ab.y, -ab.x).normalize(); - let ortho_dist = ortho.dot(aq); - if ortho_dist.abs() < endpoint_sd.distance.abs() { - (AugmentedDistance::new(ortho_dist, 0.0), f) - } else { - (endpoint_sd, f) - } - } else { - (endpoint_sd, f) - } - } - - Segment::Quadratic(QuadraticBezierSegment { - from: p0, - ctrl: p1, - to: p2, - }) => { - use lyon_geom::utils::cubic_polynomial_roots; - let qa = p0 - p; - let ab = p1 - p0; - let br = (p0 - p1) + (p2 - p1); - let a = br.dot(br); - let b = 3.0 * ab.dot(br); - let c = 2.0 * ab.dot(ab) + qa.dot(br); - let d = qa.dot(ab); - let solutions = cubic_polynomial_roots(a, b, c, d); - - let mut min_dist = ab.cross(qa).signum() * qa.length(); - - let mut f = -qa.dot(ab) / ab.dot(ab); - { - let ec = p2 - p1; - let ep = p2 - p; - let dist = ec.cross(ep).signum() * ep.length(); - if dist.abs() < min_dist.abs() { - min_dist = dist; - f = (p - p1).dot(ec) / ec.dot(ec); - } - } - for t in solutions { - if t <= 0.0 || 1.0 <= t { - continue; - } - let endpoint = p0 + (ab * 2.0 * t) + (br * t * t); - let delta = endpoint - p; - let dist = (p2 - p0).cross(delta).signum() * delta.length(); - - if dist.abs() < min_dist.abs() { - min_dist = dist; - f = t; - } - } - - if 0.0 <= f && f <= 1.0 { - (AugmentedDistance::new(min_dist, 0.0), f) - // (AugmentedDistance::new(200f32, 0.0), f) - } else if f < 0.5 { - ( - AugmentedDistance::new(min_dist, ab.normalize().dot(qa.normalize()).abs()), - f, - ) - } else { - ( - AugmentedDistance::new( - min_dist, - (p2 - p1).normalize().dot((p2 - p).normalize()).abs(), - ), - f, - ) - } - } - - _ => unimplemented!(), - } - } - - pub(crate) fn to_psuedodistance( - &self, - dist: AugmentedDistance, - p: Vector, - near: f32, - ) -> AugmentedDistance { - if near <= 0.0 { - let dir = self.direction(0.0).normalize(); - let aq = p - self.sample(0.0).to_vector(); - let ts = aq.dot(dir); - if ts < 0.0 { - let ds = aq.cross(dir); - if ds.abs() <= dist.distance.abs() { - return AugmentedDistance::new(ds, 0.0); - } - } - - dist - } else if near >= 1.0 { - let dir = self.direction(1.0).normalize(); - let aq = p - self.sample(1.0).to_vector(); - let ts = aq.dot(dir); - if ts > 0.0 { - let ds = aq.cross(dir); - if ds.abs() <= dist.distance.abs() { - return AugmentedDistance::new(ds, 0.0); - } - } - - dist - } else { - dist - } - } -} diff --git a/kayak_font/src/recolor.rs b/kayak_font/src/recolor.rs deleted file mode 100644 index 61cbbe8..0000000 --- a/kayak_font/src/recolor.rs +++ /dev/null @@ -1,124 +0,0 @@ -use lyon_geom::math::{Angle, Vector}; - -use crate::contour::Contour; -use crate::ColorFlags; - -/// Recolor the contours prior to MSDF computation. -/// This function uses a simple technique, -/// again based on Viktor's implementation. -/// It is left as a separate step so you can implement more complex techniques as desired. -pub fn recolor_contours(contours: Vec<Contour>, threshold: Angle, mut seed: u64) -> Vec<Contour> { - let (threshold, _) = threshold.sin_cos(); - - // Determine if a point is a corner, assuming i and o are incoming and - // outgoing normalized direction vectors - let is_corner = |i: Vector, o: Vector| { - let d = i.dot(o); /* |i| |o| cos(t) */ - let c = i.cross(o).abs(); /* |i| |o| sin(t) */ - - // if this corner turns more than 90 degrees (detected by dot product/cos) - // or if it turns more than the threshold angle (detected by cross product/sin) - (d <= 0.0) || (c > threshold) - }; - contours - .into_iter() - .map(|mut c| { - let mut corners = Vec::new(); - let n = c.elements.len(); - // Find all the corners - if n != 0 { - let mut prev_dir = c.elements[n - 1].direction(1.0).normalize(); - for (i, e) in c.elements.iter().enumerate() { - let c_dir = e.direction(0.0).normalize(); - if is_corner(prev_dir, c_dir) { - corners.push(i) - } - prev_dir = e.direction(1.0).normalize(); - } - } - - match corners.len() { - 0 => { - // The whole contour is smooth, and we initialized all colors to white. - // No work to do - c - } - 1 => { - // "Teardrop" case: there is only one sharp corner so we - // just pick 3 colors up front and cycle through them - let mut colors = [ - (ColorFlags::WHITE).switch(&mut seed), - ColorFlags::WHITE, - ColorFlags::WHITE, - ]; - colors[1] = colors[0].switch(&mut seed); - colors[2] = colors[1].switch(&mut seed); - let corner = corners[0]; - match n { - 0 => { - unreachable!(); - } - 1 => { - // Only a single edge segment, but it's a teardrop. - // We split it in 3 to make the colors happen - let mut split = c.elements[0].split_in_thirds(); - split[0].color = colors[0]; - split[1].color = colors[1]; - split[2].color = colors[2]; - - c.elements.clear(); - c.elements.extend_from_slice(&split); - } - 2 => { - // 2 segments. We split it into 6, and assign colors by hand - let mut split0 = c.elements[0].split_in_thirds(); - let mut split1 = c.elements[1].split_in_thirds(); - split0[0].color = colors[0]; - split0[1].color = colors[0]; - split0[2].color = colors[1]; - split1[0].color = colors[1]; - split1[1].color = colors[2]; - split1[2].color = colors[2]; - - c.elements.clear(); - c.elements.extend_from_slice(&split0); - c.elements.extend_from_slice(&split1); - } - _ => { - // We have more than 3 edges to rotate colors through - for (i, e) in c.elements.iter_mut().enumerate() { - // ported from this cursed C++ code: - // contour->edges[(corner+i)%m]->color = (colors+1)[int(3+2.875*i/(m-1)-1.4375+.5)-3]; - let i = (n + i - corner) % n; // Emulate the ( corner + i) % m - let idx_fractional = - 3.5f32 + 2.875f32 * (i as f32) / ((n - 1) as f32) - 1.4375f32; - let idx = idx_fractional.floor() as usize - 2; - e.color = colors[idx]; - } - } - } - c - } - _ => { - // We have 2 or more corners - // Cycle through colors, switching whenever we hit another corner - let n_corners = corners.len(); - let mut spline = 0; - let start = corners[0]; - let mut color = ColorFlags::WHITE; - color = color.switch(&mut seed); - let initial_color = color; - for i in 0..n { - let i = (start + i) % n; - if spline + 1 < n_corners && corners[spline + 1] == i { - spline = spline + 1; - color = color.switch_banned(&mut seed, initial_color); - } - c.elements[i].color = color; - } - c - } - } - }) - .collect() -} diff --git a/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs b/kayak_font/src/renderer/font_texture_cache.rs similarity index 94% rename from bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs rename to kayak_font/src/renderer/font_texture_cache.rs index e195c2b..e170a25 100644 --- a/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs +++ b/kayak_font/src/renderer/font_texture_cache.rs @@ -1,3 +1,4 @@ +use crate::{KayakFont, Sdf}; use bevy::{ math::Vec2, prelude::{Handle, Res}, @@ -16,9 +17,9 @@ use bevy::{ utils::HashMap, }; -use crate::render::unified::pipeline::UnifiedPipeline; - -use super::{font::KayakFont, sdf::Sdf}; +pub trait FontRenderingPipeline { + fn get_font_image_layout(&self) -> &BindGroupLayout; +} pub const MAX_CHARACTERS: u32 = 100; @@ -59,11 +60,15 @@ impl FontTextureCache { } } - pub fn process_new( + pub fn get_binding(&self, handle: &Handle<KayakFont>) -> Option<&BindGroup> { + self.bind_groups.get(handle) + } + + pub fn process_new<T: FontRenderingPipeline>( &mut self, device: &RenderDevice, queue: &RenderQueue, - pipeline: &UnifiedPipeline, + pipeline: &T, render_images: &Res<RenderAssets<Image>>, ) { let new_fonts: Vec<_> = self.new_fonts.drain(..).collect(); @@ -151,10 +156,7 @@ impl FontTextureCache { images.insert(font_handle, image); } - pub fn get_empty( - device: &RenderDevice, - image_layout: &BindGroupLayout, - ) -> (GpuImage, BindGroup) { + pub fn get_empty(device: &RenderDevice, layout: &BindGroupLayout) -> (GpuImage, BindGroup) { let texture_descriptor = TextureDescriptor { label: Some("font_texture_array"), size: Extent3d { @@ -203,20 +205,20 @@ impl FontTextureCache { resource: BindingResource::Sampler(&image.sampler), }, ], - layout: image_layout, + layout, }); (image, binding) } - pub fn create_from_atlas( + pub fn create_from_atlas<T: FontRenderingPipeline>( images: &mut HashMap<Handle<KayakFont>, GpuImage>, bind_groups: &mut HashMap<Handle<KayakFont>, BindGroup>, sdf: &Sdf, font_handle: Handle<KayakFont>, device: &RenderDevice, queue: &RenderQueue, - pipeline: &UnifiedPipeline, + pipeline: &T, atlas_texture: &GpuImage, size: Vec2, ) { @@ -247,7 +249,7 @@ impl FontTextureCache { resource: BindingResource::Sampler(&gpu_image.sampler), }, ], - layout: &pipeline.font_image_layout, + layout: &pipeline.get_font_image_layout(), }); bind_groups.insert(font_handle.clone_weak(), binding); diff --git a/kayak_font/src/renderer/mod.rs b/kayak_font/src/renderer/mod.rs new file mode 100644 index 0000000..4373261 --- /dev/null +++ b/kayak_font/src/renderer/mod.rs @@ -0,0 +1,2 @@ +mod font_texture_cache; +pub use font_texture_cache::*; diff --git a/kayak_font/src/sdf.rs b/kayak_font/src/sdf.rs index c1cd976..129efb1 100644 --- a/kayak_font/src/sdf.rs +++ b/kayak_font/src/sdf.rs @@ -1,87 +1,61 @@ -use lyon_geom::math::Vector; - -use crate::{contour::Contour, utils::EdgeDistance}; - -/// Computes a SDF from a list of contours. The returned vectors are a `dim` by `dim` -/// matrix of signed distances. The output represents the signed distances to the contours -/// within [0, 1] x [0, 1] -pub fn compute_sdf(contours: &[Contour], dim: usize) -> Vec<Vec<f32>> { - let scale: f32 = 1.0 / (dim as f32); - let windings: Vec<i32> = contours.iter().map(|c| c.winding() as i32).collect(); - - (0..dim) - .map(|y| { - let py = (y as f32 + 0.5) * scale; - (0..dim) - .map(|x| { - if contours.len() == 0 { - return 1.0f32; - } - - let px = (x as f32 + 0.5) * scale; - let p = Vector::new(px, py); - - let mut neg_dist = 1e24f32; - let mut pos_dist = -1e24f32; - let mut winding = 0; - let mut contour_distances = Vec::new(); - contour_distances.reserve(contours.len()); - - for (i, contour) in contours.iter().enumerate() { - let mut contour_min = EdgeDistance::new(); - - for elem in contour.elements.iter() { - let (d, na) = elem.distance(p.to_point()); - - if d < contour_min.dist { - contour_min.dist = d; - contour_min.edge = Some(&elem); - contour_min.nearest_approach = na; - } - } - - // contour_min.to_pseudodistance(p); - let cmdd = contour_min.dist.distance; - - contour_distances.push(cmdd); - - if windings[i] > 0 && cmdd >= 0.0 && cmdd.abs() < pos_dist.abs() { - pos_dist = cmdd; - } - if windings[i] < 0 && cmdd <= 0.0 && cmdd.abs() < neg_dist.abs() { - neg_dist = cmdd; - } - } +use crate::{atlas::Atlas, glyph::Glyph, metrics::Metrics, SDFType}; +use bevy::math::Vec2; +use serde::Deserialize; + +#[derive(Deserialize, Debug, Clone)] +pub struct Sdf { + pub atlas: Atlas, + metrics: Metrics, + pub glyphs: Vec<Glyph>, + kerning: Vec<KerningData>, +} - assert!(contour_distances.len() == windings.len()); +#[derive(serde::Deserialize, Debug, Clone, Copy)] +pub struct KerningData { + pub unicode1: u32, + pub unicode2: u32, + pub advance: f32, +} - let mut md = -1e24; - if pos_dist >= 0.0 && pos_dist.abs() <= neg_dist.abs() { - md = pos_dist; - winding = 1; - for (d, w) in contour_distances.iter().zip(windings.iter()) { - if *w > 0 && *d > md && d.abs() < neg_dist.abs() { - md = *d; - } - } - } else if neg_dist <= 0.0 && neg_dist.abs() <= pos_dist.abs() { - md = neg_dist; - winding = -1; - for (d, w) in contour_distances.iter().zip(windings.iter()) { - if *w < 0 && *d < md && d.abs() < pos_dist.abs() { - md = *d; - } - } - } - for (c, w) in contour_distances.iter().zip(windings.iter()) { - if *w != winding && c.abs() < md.abs() { - md = *c; - } - } +impl Sdf { + pub fn from_string(data: String) -> Sdf { + let value: Sdf = match serde_path_to_error::deserialize( + &mut serde_json::Deserializer::from_str(&data), + ) { + Ok(v) => v, + Err(err) => { + let path = err.path().to_string(); + dbg!(err); + panic!("failed to deserialize json! path: {}", path); + } + }; + + value + } + + pub fn max_glyph_size(&self) -> Vec2 { + let mut size = Vec2::new(0.0, 0.0); + self.glyphs.iter().for_each(|glyph| { + if let Some(atlas_bounds) = glyph.atlas_bounds { + let atlas_size = atlas_bounds.size(); + if atlas_size.x > size.x { + size.x = atlas_size.x; + } + if atlas_size.y > size.y { + size.y = atlas_size.y; + } + } + }); + + size + } +} - md / 0.5 - }) - .collect() - }) - .collect() +#[test] +fn test_sdf_loader() { + let sdf = Sdf::from_string(include_str!("../assets/roboto.json").to_string()); + assert!(sdf.max_glyph_size() == Vec2::new(30.0, 36.0)); + assert!(sdf.atlas.width == 212); + assert!(sdf.atlas.height == 212); + assert!(matches!(sdf.atlas.sdf_type, SDFType::Msdf)); } diff --git a/kayak_font/src/ttf_parser.rs b/kayak_font/src/ttf_parser.rs deleted file mode 100644 index 4c8607c..0000000 --- a/kayak_font/src/ttf_parser.rs +++ /dev/null @@ -1,69 +0,0 @@ -use lyon_geom::math::Point; -use lyon_path::Segment; - -use crate::{ColorFlags, Contour, PathCollector, PathElement}; - -impl ttf_parser::OutlineBuilder for PathCollector { - fn move_to(&mut self, x: f32, y: f32) { - let to = Point::new(x, y); - self.pen = to; - self.contour_start = to; - } - - fn line_to(&mut self, x: f32, y: f32) { - let to = Point::new(x, y) * self.scale; - self.elements.push(PathElement::new( - Segment::Line(lyon_geom::LineSegment { from: self.pen, to }), - ColorFlags::WHITE, - )); - self.pen = to; - } - - fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) { - let ctrl = Point::new(x1, y1) * self.scale; - let to = Point::new(x, y) * self.scale; - self.elements.push(PathElement::new( - Segment::Quadratic(lyon_geom::QuadraticBezierSegment { - from: self.pen, - to, - ctrl, - }), - ColorFlags::WHITE, - )); - self.pen = to; - } - - fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) { - let ctrl1 = Point::new(x1, y1) * self.scale; - let ctrl2 = Point::new(x2, y2) * self.scale; - let to = Point::new(x, y) * self.scale; - self.elements.push(PathElement::new( - Segment::Cubic(lyon_geom::CubicBezierSegment { - from: self.pen, - to, - ctrl1, - ctrl2, - }), - ColorFlags::WHITE, - )); - - self.pen = to; - } - - fn close(&mut self) { - if (self.pen - self.contour_start).length() > 1E-14 { - self.elements.push(PathElement::new( - Segment::Line(lyon_geom::LineSegment { - from: self.pen * self.scale, - to: self.contour_start * self.scale, - }), - ColorFlags::WHITE, - )); - } - - self.pen = self.contour_start; - let elements = std::mem::replace(&mut self.elements, Vec::new()); - - self.contours.push(Contour { elements }); - } -} diff --git a/kayak_font/src/utils.rs b/kayak_font/src/utils.rs deleted file mode 100644 index 5e8e35f..0000000 --- a/kayak_font/src/utils.rs +++ /dev/null @@ -1,61 +0,0 @@ -use lyon_path::math::Vector; - -use crate::path_element::PathElement; - -/// Represents a distance to an edge segment -#[derive(Copy, Clone)] -pub(crate) struct EdgeDistance<'a> { - pub(crate) dist: AugmentedDistance, - pub(crate) edge: Option<&'a PathElement>, - pub(crate) nearest_approach: f32, -} - -impl<'a> EdgeDistance<'a> { - /// Create a new edge point, initialized to infinite distance - pub(crate) fn new() -> Self { - Self { - dist: AugmentedDistance::new(-1e24, 0.0), - edge: None, - nearest_approach: 0.0, - } - } - - pub(crate) fn to_pseudodistance(&mut self, p: Vector) { - match self.edge { - Some(edge) => self.dist = edge.to_psuedodistance(self.dist, p, self.nearest_approach), - None => {} - } - } -} - -/// A signed distance, augmented with the cosine of the angle -/// between the tangent of the edge and the vector from the -/// point of nearest approach to the measured point. -#[derive(Copy, Clone, PartialEq, Debug)] -pub struct AugmentedDistance { - /// The actual distance - pub(crate) distance: f32, - /// The cosine of the angle between the tangent vector of the path segment - /// at the point of closest approach and the vector from the point of - /// closest approach to the point to which distance was measured. This is used to - dot: f32, -} - -impl AugmentedDistance { - pub(crate) fn new(distance: f32, dot: f32) -> Self { - Self { distance, dot } - } -} - -impl std::cmp::PartialOrd for AugmentedDistance { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - use std::cmp::Ordering; - - match self.distance.abs().partial_cmp(&other.distance.abs()) { - Some(Ordering::Less) => Some(Ordering::Less), - Some(Ordering::Greater) => Some(Ordering::Greater), - Some(Ordering::Equal) => self.dot.partial_cmp(&other.dot), - None => None, - } - } -} -- GitLab