diff --git a/Cargo.lock b/Cargo.lock
index 4b9e0ca7c5ebf99adaca5c433e566899d60944a0..ff48216dd365e02b01add0c1fb6e13299b1013f6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -72,12 +72,6 @@ dependencies = [
  "pkg-config",
 ]
 
-[[package]]
-name = "android_log-sys"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e"
-
 [[package]]
 name = "android_log-sys"
 version = "0.2.0"
@@ -86,11 +80,11 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
 
 [[package]]
 name = "android_logger"
-version = "0.8.6"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cbd542dd180566fad88fd2729a53a62a734843c626638006a9d63ec0688484e"
+checksum = "2ec2333c185d826313162cee39d3fcc6a84ba08114a839bebf53b961e7e75773"
 dependencies = [
- "android_log-sys 0.1.2",
+ "android_log-sys",
  "env_logger",
  "lazy_static",
  "log",
@@ -208,7 +202,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
 [[package]]
 name = "bevy"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_internal",
 ]
@@ -222,7 +216,7 @@ checksum = "0d5f2f58f0aec3c50a20799792c3705e80dd7df327e79791cacec197e84e5e61"
 [[package]]
 name = "bevy_app"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_derive",
  "bevy_ecs",
@@ -235,7 +229,7 @@ dependencies = [
 [[package]]
 name = "bevy_asset"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "bevy_app",
@@ -248,7 +242,7 @@ dependencies = [
  "crossbeam-channel",
  "downcast-rs",
  "js-sys",
- "ndk-glue 0.2.1",
+ "ndk-glue 0.4.0",
  "notify",
  "parking_lot",
  "rand",
@@ -262,7 +256,7 @@ dependencies = [
 [[package]]
 name = "bevy_audio"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "bevy_app",
@@ -277,7 +271,7 @@ dependencies = [
 [[package]]
 name = "bevy_core"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_derive",
@@ -292,7 +286,7 @@ dependencies = [
 [[package]]
 name = "bevy_core_pipeline"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -304,7 +298,7 @@ dependencies = [
 [[package]]
 name = "bevy_derive"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "Inflector",
  "bevy_macro_utils",
@@ -315,7 +309,7 @@ dependencies = [
 [[package]]
 name = "bevy_diagnostic"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_core",
@@ -324,19 +318,10 @@ dependencies = [
  "bevy_utils",
 ]
 
-[[package]]
-name = "bevy_dynamic_plugin"
-version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
-dependencies = [
- "bevy_app",
- "libloading",
-]
-
 [[package]]
 name = "bevy_ecs"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "async-channel",
  "bevy_ecs_macros",
@@ -346,7 +331,6 @@ dependencies = [
  "downcast-rs",
  "fixedbitset",
  "fxhash",
- "rand",
  "serde",
  "thiserror",
 ]
@@ -354,7 +338,7 @@ dependencies = [
 [[package]]
 name = "bevy_ecs_macros"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_macro_utils",
  "proc-macro2 1.0.32",
@@ -365,7 +349,7 @@ dependencies = [
 [[package]]
 name = "bevy_gilrs"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_ecs",
@@ -377,7 +361,7 @@ dependencies = [
 [[package]]
 name = "bevy_gltf2"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "base64",
@@ -392,6 +376,7 @@ dependencies = [
  "bevy_render2",
  "bevy_scene",
  "bevy_transform",
+ "bevy_utils",
  "gltf",
  "percent-encoding",
  "thiserror",
@@ -401,7 +386,7 @@ dependencies = [
 [[package]]
 name = "bevy_input"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_ecs",
@@ -412,7 +397,7 @@ dependencies = [
 [[package]]
 name = "bevy_internal"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -421,7 +406,6 @@ dependencies = [
  "bevy_core_pipeline",
  "bevy_derive",
  "bevy_diagnostic",
- "bevy_dynamic_plugin",
  "bevy_ecs",
  "bevy_gilrs",
  "bevy_gltf2",
@@ -444,7 +428,7 @@ dependencies = [
  "bevy_wgpu",
  "bevy_window",
  "bevy_winit",
- "ndk-glue 0.2.1",
+ "ndk-glue 0.4.0",
 ]
 
 [[package]]
@@ -458,14 +442,17 @@ dependencies = [
  "kayak_core",
  "kayak_font",
  "kayak_render_macros",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
 ]
 
 [[package]]
 name = "bevy_log"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
- "android_log-sys 0.2.0",
+ "android_log-sys",
  "bevy_app",
  "bevy_utils",
  "console_error_panic_hook",
@@ -477,7 +464,7 @@ dependencies = [
 [[package]]
 name = "bevy_macro_utils"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "cargo-manifest",
  "quote 1.0.10",
@@ -487,7 +474,7 @@ dependencies = [
 [[package]]
 name = "bevy_math"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_reflect",
  "glam",
@@ -496,7 +483,7 @@ dependencies = [
 [[package]]
 name = "bevy_pbr"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -512,7 +499,7 @@ dependencies = [
 [[package]]
 name = "bevy_pbr2"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -533,7 +520,7 @@ dependencies = [
 [[package]]
 name = "bevy_reflect"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_reflect_derive",
  "bevy_utils",
@@ -549,7 +536,7 @@ dependencies = [
 [[package]]
 name = "bevy_reflect_derive"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_macro_utils",
  "proc-macro2 1.0.32",
@@ -561,7 +548,7 @@ dependencies = [
 [[package]]
 name = "bevy_render"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "bevy-glsl-to-spirv",
@@ -591,7 +578,7 @@ dependencies = [
 [[package]]
 name = "bevy_render2"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "bevy_app",
@@ -624,7 +611,7 @@ dependencies = [
 [[package]]
 name = "bevy_scene"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "anyhow",
  "bevy_app",
@@ -642,7 +629,7 @@ dependencies = [
 [[package]]
 name = "bevy_sprite"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -665,7 +652,7 @@ dependencies = [
 [[package]]
 name = "bevy_sprite2"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -679,6 +666,7 @@ dependencies = [
  "bevy_transform",
  "bevy_utils",
  "bytemuck",
+ "crevice",
  "guillotiere",
  "rectangle-pack",
  "serde",
@@ -688,7 +676,7 @@ dependencies = [
 [[package]]
 name = "bevy_tasks"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "async-channel",
  "async-executor",
@@ -701,7 +689,7 @@ dependencies = [
 [[package]]
 name = "bevy_text"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "ab_glyph",
  "anyhow",
@@ -723,7 +711,7 @@ dependencies = [
 [[package]]
 name = "bevy_transform"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_ecs",
@@ -736,12 +724,11 @@ dependencies = [
 [[package]]
 name = "bevy_ui"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
  "bevy_core",
- "bevy_derive",
  "bevy_ecs",
  "bevy_input",
  "bevy_log",
@@ -761,7 +748,7 @@ dependencies = [
 [[package]]
 name = "bevy_utils"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "ahash",
  "bevy_derive",
@@ -774,7 +761,7 @@ dependencies = [
 [[package]]
 name = "bevy_wgpu"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
  "bevy_asset",
@@ -795,10 +782,9 @@ dependencies = [
 [[package]]
 name = "bevy_window"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bevy_app",
- "bevy_ecs",
  "bevy_math",
  "bevy_utils",
  "raw-window-handle",
@@ -808,8 +794,9 @@ dependencies = [
 [[package]]
 name = "bevy_winit"
 version = "0.5.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
+ "approx",
  "bevy_app",
  "bevy_ecs",
  "bevy_input",
@@ -965,18 +952,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
 
-[[package]]
-name = "chrono"
-version = "0.4.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
-dependencies = [
- "libc",
- "num-integer",
- "num-traits",
- "winapi",
-]
-
 [[package]]
 name = "clang-sys"
 version = "1.3.0"
@@ -1217,6 +1192,7 @@ dependencies = [
  "parking_lot",
  "stdweb 0.1.3",
  "thiserror",
+ "wasm-bindgen",
  "web-sys",
  "winapi",
 ]
@@ -1233,7 +1209,7 @@ dependencies = [
 [[package]]
 name = "crevice"
 version = "0.8.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "bytemuck",
  "crevice-derive",
@@ -1244,7 +1220,7 @@ dependencies = [
 [[package]]
 name = "crevice-derive"
 version = "0.8.0"
-source = "git+https://github.com/StarArawn/bevy?rev=b26f563b13c267ffe1ee801bd71fd40b98a256e7#b26f563b13c267ffe1ee801bd71fd40b98a256e7"
+source = "git+https://github.com/StarArawn/bevy?rev=146ddbe5f839d5d635fe350a535155231d4050c2#146ddbe5f839d5d635fe350a535155231d4050c2"
 dependencies = [
  "proc-macro2 1.0.32",
  "quote 1.0.10",
@@ -1993,6 +1969,26 @@ dependencies = [
  "libloading",
 ]
 
+[[package]]
+name = "kqueue"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "058a107a784f8be94c7d35c1300f4facced2e93d2fbe5b1452b44e905ddca4a9"
+dependencies = [
+ "kqueue-sys",
+ "libc",
+]
+
+[[package]]
+name = "kqueue-sys"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
+dependencies = [
+ "bitflags",
+ "libc",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -2104,9 +2100,9 @@ dependencies = [
 
 [[package]]
 name = "matchers"
-version = "0.0.1"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
 dependencies = [
  "regex-automata",
 ]
@@ -2238,18 +2234,6 @@ dependencies = [
  "thiserror",
 ]
 
-[[package]]
-name = "ndk"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73"
-dependencies = [
- "jni-sys",
- "ndk-sys",
- "num_enum 0.4.3",
- "thiserror",
-]
-
 [[package]]
 name = "ndk"
 version = "0.3.0"
@@ -2258,7 +2242,7 @@ checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab"
 dependencies = [
  "jni-sys",
  "ndk-sys",
- "num_enum 0.5.4",
+ "num_enum",
  "thiserror",
 ]
 
@@ -2271,25 +2255,10 @@ dependencies = [
  "bitflags",
  "jni-sys",
  "ndk-sys",
- "num_enum 0.5.4",
+ "num_enum",
  "thiserror",
 ]
 
-[[package]]
-name = "ndk-glue"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241"
-dependencies = [
- "android_logger",
- "lazy_static",
- "libc",
- "log",
- "ndk 0.2.1",
- "ndk-macro",
- "ndk-sys",
-]
-
 [[package]]
 name = "ndk-glue"
 version = "0.3.0"
@@ -2310,6 +2279,7 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d3e9e94628f24e7a3cb5b96a2dc5683acd9230bf11991c2a1677b87695138420"
 dependencies = [
+ "android_logger",
  "lazy_static",
  "libc",
  "log",
@@ -2367,15 +2337,16 @@ dependencies = [
 
 [[package]]
 name = "notify"
-version = "5.0.0-pre.10"
+version = "5.0.0-pre.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51f18203a26893ca1d3526cf58084025d5639f91c44f8b70ab3b724f60e819a0"
+checksum = "c614e7ed2b1cf82ec99aeffd8cf6225ef5021b9951148eb161393c394855032c"
 dependencies = [
  "bitflags",
  "crossbeam-channel",
  "filetime",
  "fsevent-sys",
  "inotify",
+ "kqueue",
  "libc",
  "mio",
  "walkdir",
@@ -2453,16 +2424,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "num_enum"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4"
-dependencies = [
- "derivative",
- "num_enum_derive 0.4.3",
-]
-
 [[package]]
 name = "num_enum"
 version = "0.5.4"
@@ -2470,19 +2431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f"
 dependencies = [
  "derivative",
- "num_enum_derive 0.5.4",
-]
-
-[[package]]
-name = "num_enum_derive"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d"
-dependencies = [
- "proc-macro-crate 0.1.5",
- "proc-macro2 1.0.32",
- "quote 1.0.10",
- "syn 1.0.81",
+ "num_enum_derive",
 ]
 
 [[package]]
@@ -2974,6 +2923,15 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0421d4f173fab82d72d6babf36d57fae38b994ca5c2d78e704260ba6d12118b"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "sha1"
 version = "0.6.0"
@@ -3276,43 +3234,29 @@ dependencies = [
  "tracing-core",
 ]
 
-[[package]]
-name = "tracing-serde"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
-dependencies = [
- "serde",
- "tracing-core",
-]
-
 [[package]]
 name = "tracing-subscriber"
-version = "0.2.24"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3"
+checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
 dependencies = [
  "ansi_term 0.12.1",
- "chrono",
  "lazy_static",
  "matchers",
  "regex",
- "serde",
- "serde_json",
  "sharded-slab",
  "smallvec",
  "thread_local",
  "tracing",
  "tracing-core",
  "tracing-log",
- "tracing-serde",
 ]
 
 [[package]]
 name = "tracing-wasm"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae741706df70547fca8715f74a8569677666e7be3454313af70f6e158034485"
+checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07"
 dependencies = [
  "tracing",
  "tracing-subscriber",
diff --git a/Cargo.toml b/Cargo.toml
index 86833ba5ae799e4fd16fbd0d1789cae2b3d9024d..1e3c3c6a090877757bb3b1d38b281fcf7ae0cb29 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,5 +17,5 @@ kayak_components = { path = "kayak_components" }
 kayak_core = { path = "kayak_core" }
 
 [dev-dependencies]
-bevy = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
+bevy = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
 bevy_kayak_ui = { path = "bevy_kayak_ui" }
diff --git a/assets/fullsheet.png b/assets/fullsheet.png
new file mode 100644
index 0000000000000000000000000000000000000000..dd20342dc66c717d908eb3c956e3f2b80cddaa2c
Binary files /dev/null and b/assets/fullsheet.png differ
diff --git a/assets/roboto.json b/assets/roboto.json
new file mode 100644
index 0000000000000000000000000000000000000000..60008778e8ac698e344216c88570a2f698dbd4e3
--- /dev/null
+++ b/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/assets/roboto.json.old b/assets/roboto.json.old
new file mode 100644
index 0000000000000000000000000000000000000000..875af49e5db852469951736f27ca09844079dbcb
--- /dev/null
+++ b/assets/roboto.json.old
@@ -0,0 +1 @@
+{"atlas":{"type":"msdf","distanceRange":2,"size":151.375,"width":1024,"height":720,"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.06883374567764243,"bottom":-0.013855938080615242,"right":0.19434984807235753,"top":0.71942234433061514},"atlasBounds":{"left":697.5,"bottom":331.5,"right":716.5,"top":442.5}},{"unicode":34,"advance":0.31982421875,"planeBounds":{"left":0.057747221111168451,"bottom":0.50057537352910819,"right":0.27574887263883152,"top":0.75821368897089192},"atlasBounds":{"left":899.5,"bottom":178.5,"right":932.5,"top":217.5}},{"unicode":35,"advance":0.61572265625,"planeBounds":{"left":0.049806703524979304,"bottom":-0.0078673358794385286,"right":0.6113261089750206,"top":0.71880483587943844},"atlasBounds":{"left":858.5,"bottom":332.5,"right":943.5,"top":442.5}},{"unicode":36,"advance":0.5615234375,"planeBounds":{"left":0.046488931216453339,"bottom":-0.11003222414327002,"right":0.51552278753354663,"top":0.83464159914326996},"atlasBounds":{"left":278.5,"bottom":576.5,"right":349.5,"top":719.5}},{"unicode":37,"advance":0.732421875,"planeBounds":{"left":0.043114710208505325,"bottom":-0.017776501857968668,"right":0.69711966479149456,"top":0.72871400185796853},"atlasBounds":{"left":438.5,"bottom":446.5,"right":537.5,"top":559.5}},{"unicode":38,"advance":0.62158203125,"planeBounds":{"left":0.040012450970272451,"bottom":-0.017776501857968668,"right":0.62795629902972738,"top":0.72871400185796853},"atlasBounds":{"left":538.5,"bottom":446.5,"right":627.5,"top":559.5}},{"unicode":39,"advance":0.17431640625,"planeBounds":{"left":0.040671287933526007,"bottom":0.50754053823028489,"right":0.13315683706647397,"top":0.75857274301971511},"atlasBounds":{"left":994.5,"bottom":27.5,"right":1008.5,"top":65.5}},{"unicode":40,"advance":0.341796875,"planeBounds":{"left":0.055119332550578062,"bottom":-0.23880884373709743,"right":0.33257597994942201,"top":0.81156274998709732},"atlasBounds":{"left":0.5,"bottom":560.5,"right":42.5,"top":719.5}},{"unicode":41,"advance":0.34765625,"planeBounds":{"left":0.0089767544255780589,"bottom":-0.23880884373709743,"right":0.28643340182442201,"top":0.81156274998709732},"atlasBounds":{"left":43.5,"bottom":560.5,"right":85.5,"top":719.5}},{"unicode":42,"advance":0.4306640625,"planeBounds":{"left":0.0069954050758670762,"bottom":0.2894517944235136,"right":0.42318037617413296,"top":0.71884898682648635},"atlasBounds":{"left":713.5,"bottom":152.5,"right":776.5,"top":217.5}},{"unicode":43,"advance":0.56689453125,"planeBounds":{"left":0.03070607646056973,"bottom":0.062530643579686171,"right":0.53277048603943011,"top":0.5976256064203137},"atlasBounds":{"left":505.5,"bottom":136.5,"right":581.5,"top":217.5}},{"unicode":44,"advance":0.1962890625,"planeBounds":{"left":0.0063051181229355786,"bottom":-0.14945619742206853,"right":0.15824566312706437,"top":0.1147882286720685},"atlasBounds":{"left":994.5,"bottom":66.5,"right":1017.5,"top":106.5}},{"unicode":45,"advance":0.27587890625,"planeBounds":{"left":0.0083878735291081988,"bottom":0.25575917855852598,"right":0.26602618897089186,"top":0.34824472769147397},"atlasBounds":{"left":144.5,"bottom":6.5,"right":183.5,"top":20.5}},{"unicode":46,"advance":0.26318359375,"planeBounds":{"left":0.06040373722646572,"bottom":-0.014418207447357567,"right":0.19252595027353425,"top":0.11109789494735753},"atlasBounds":{"left":472.5,"bottom":115.5,"right":492.5,"top":134.5}},{"unicode":47,"advance":0.412109375,"planeBounds":{"left":0.00092051700557392938,"bottom":-0.068112411940028941,"right":0.39068104549442606,"top":0.71801475569002882},"atlasBounds":{"left":578.5,"bottom":600.5,"right":637.5,"top":719.5}},{"unicode":48,"advance":0.5615234375,"planeBounds":{"left":0.049303705292630062,"bottom":-0.017776501857968668,"right":0.51173145095736994,"top":0.72871400185796853},"atlasBounds":{"left":628.5,"bottom":446.5,"right":698.5,"top":559.5}},{"unicode":49,"advance":0.5615234375,"planeBounds":{"left":0.074147987523224629,"bottom":-0.0094614068306152418,"right":0.3648168562267754,"top":0.72381687558061514},"atlasBounds":{"left":717.5,"bottom":331.5,"right":761.5,"top":442.5}},{"unicode":50,"advance":0.5615234375,"planeBounds":{"left":0.037427100536746485,"bottom":-0.0095906340317919551,"right":0.53288539946325342,"top":0.73029375903179183},"atlasBounds":{"left":172.5,"bottom":330.5,"right":247.5,"top":442.5}},{"unicode":51,"advance":0.5615234375,"planeBounds":{"left":0.036723306216453339,"bottom":-0.017776501857968668,"right":0.50575716253354663,"top":0.72871400185796853},"atlasBounds":{"left":699.5,"bottom":446.5,"right":770.5,"top":559.5}},{"unicode":52,"advance":0.5615234375,"planeBounds":{"left":0.018226277030862877,"bottom":-0.0078673358794385286,"right":0.54671512921913701,"top":0.71880483587943844},"atlasBounds":{"left":602.5,"bottom":218.5,"right":682.5,"top":328.5}},{"unicode":53,"advance":0.5615234375,"planeBounds":{"left":0.067370111542630021,"bottom":-0.019356259031791955,"right":0.52979785720736983,"top":0.72052813403179183},"atlasBounds":{"left":248.5,"bottom":330.5,"right":318.5,"top":442.5}},{"unicode":54,"advance":0.5615234375,"planeBounds":{"left":0.054545571841453339,"bottom":-0.019112118406791955,"right":0.52357942815854663,"top":0.72077227465679183},"atlasBounds":{"left":319.5,"bottom":330.5,"right":390.5,"top":442.5}},{"unicode":55,"advance":0.5615234375,"planeBounds":{"left":0.030102881786746489,"bottom":-0.0078673358794385286,"right":0.52556118071325342,"top":0.71880483587943844},"atlasBounds":{"left":944.5,"bottom":332.5,"right":1019.5,"top":442.5}},{"unicode":56,"advance":0.5615234375,"planeBounds":{"left":0.046244790591453339,"bottom":-0.017776501857968668,"right":0.51527864690854663,"top":0.72871400185796853},"atlasBounds":{"left":771.5,"bottom":446.5,"right":842.5,"top":559.5}},{"unicode":57,"advance":0.5615234375,"planeBounds":{"left":0.041247064667630062,"bottom":-0.0098347746567919551,"right":0.50367481033236994,"top":0.73004961840679183},"atlasBounds":{"left":411.5,"bottom":330.5,"right":481.5,"top":442.5}},{"unicode":58,"advance":0.2421875,"planeBounds":{"left":0.05576506535146572,"bottom":-0.013540631773843976,"right":0.18788727839853425,"top":0.54137266302384379},"atlasBounds":{"left":428.5,"bottom":22.5,"right":448.5,"top":106.5}},{"unicode":59,"advance":0.21142578125,"planeBounds":{"left":0.010685335595582152,"bottom":-0.15102002799855493,"right":0.17583810190441782,"top":0.54262159049855485},"atlasBounds":{"left":0.5,"bottom":1.5,"right":25.5,"top":106.5}},{"unicode":60,"advance":0.50830078125,"planeBounds":{"left":0.026770795700867076,"bottom":0.08776301061880673,"right":0.44295576679913296,"top":0.54358464563119313},"atlasBounds":{"left":582.5,"bottom":148.5,"right":645.5,"top":217.5}},{"unicode":61,"advance":0.548828125,"planeBounds":{"left":0.066436490374690363,"bottom":0.18681172907204793,"right":0.48922757212530965,"top":0.48408670842795209},"atlasBounds":{"left":834.5,"bottom":172.5,"right":898.5,"top":217.5}},{"unicode":62,"advance":0.5224609375,"planeBounds":{"left":0.055924129722336915,"bottom":0.08825129186880673,"right":0.4919274327776631,"top":0.54407292688119313},"atlasBounds":{"left":646.5,"bottom":148.5,"right":712.5,"top":217.5}},{"unicode":63,"advance":0.47216796875,"planeBounds":{"left":0.029829710402043789,"bottom":-0.012276180906791955,"right":0.43940857084795626,"top":0.72760821215679183},"atlasBounds":{"left":482.5,"bottom":330.5,"right":544.5,"top":442.5}},{"unicode":64,"advance":0.89794921875,"planeBounds":{"left":0.05015928215963629,"bottom":-0.2302643250670933,"right":0.85610478174675431,"top":0.70780338756709327},"atlasBounds":{"left":350.5,"bottom":577.5,"right":472.5,"top":719.5}},{"unicode":65,"advance":0.65234375,"planeBounds":{"left":0.0060196489858587478,"bottom":-0.0078673358794385286,"right":0.64681238226414106,"top":0.71880483587943844},"atlasBounds":{"left":250.5,"bottom":107.5,"right":347.5,"top":217.5}},{"unicode":66,"advance":0.62255859375,"planeBounds":{"left":0.073430685835569734,"bottom":-0.0078673358794385286,"right":0.57549509541443022,"top":0.71880483587943844},"atlasBounds":{"left":173.5,"bottom":107.5,"right":249.5,"top":217.5}},{"unicode":67,"advance":0.65087890625,"planeBounds":{"left":0.051027406649979304,"bottom":-0.017776501857968668,"right":0.6125468121000206,"top":0.72871400185796853},"atlasBounds":{"left":843.5,"bottom":446.5,"right":928.5,"top":559.5}},{"unicode":68,"advance":0.65576171875,"planeBounds":{"left":0.075355183280862881,"bottom":-0.0078673358794385286,"right":0.60384403546913701,"top":0.71880483587943844},"atlasBounds":{"left":0.5,"bottom":107.5,"right":80.5,"top":217.5}},{"unicode":69,"advance":0.568359375,"planeBounds":{"left":0.073832681216453297,"bottom":-0.0078673358794385286,"right":0.54286653753354663,"top":0.71880483587943844},"atlasBounds":{"left":939.5,"bottom":218.5,"right":1010.5,"top":328.5}},{"unicode":70,"advance":0.552734375,"planeBounds":{"left":0.07482355749380673,"bottom":-0.0078673358794385286,"right":0.53064519250619313,"top":0.71880483587943844},"atlasBounds":{"left":869.5,"bottom":218.5,"right":938.5,"top":328.5}},{"unicode":71,"advance":0.68115234375,"planeBounds":{"left":0.052736391024979304,"bottom":-0.017776501857968668,"right":0.6142557964750206,"top":0.72871400185796853},"atlasBounds":{"left":929.5,"bottom":446.5,"right":1014.5,"top":559.5}},{"unicode":72,"advance":0.712890625,"planeBounds":{"left":0.074953187899979318,"bottom":-0.0078673358794385286,"right":0.6364725933500206,"top":0.71880483587943844},"atlasBounds":{"left":701.5,"bottom":218.5,"right":786.5,"top":328.5}},{"unicode":73,"advance":0.27197265625,"planeBounds":{"left":0.080078528204995864,"bottom":-0.0078673358794385286,"right":0.19238240929500411,"top":0.71880483587943844},"atlasBounds":{"left":683.5,"bottom":218.5,"right":700.5,"top":328.5}},{"unicode":74,"advance":0.5517578125,"planeBounds":{"left":0.019030267792630059,"bottom":-0.019356259031791955,"right":0.48145801345736994,"top":0.72052813403179183},"atlasBounds":{"left":545.5,"bottom":330.5,"right":615.5,"top":442.5}},{"unicode":75,"advance":0.626953125,"planeBounds":{"left":0.074220766024979318,"bottom":-0.0078673358794385286,"right":0.6357401714750206,"top":0.71880483587943844},"atlasBounds":{"left":516.5,"bottom":218.5,"right":601.5,"top":328.5}},{"unicode":76,"advance":0.5380859375,"planeBounds":{"left":0.07348794094498344,"bottom":-0.0078673358794385286,"right":0.52270346530501643,"top":0.71880483587943844},"atlasBounds":{"left":447.5,"bottom":218.5,"right":515.5,"top":328.5}},{"unicode":77,"advance":0.873046875,"planeBounds":{"left":0.072943210995561475,"bottom":-0.0078673358794385286,"right":0.79961538275443844,"top":0.71880483587943844},"atlasBounds":{"left":336.5,"bottom":218.5,"right":446.5,"top":328.5}},{"unicode":78,"advance":0.712890625,"planeBounds":{"left":0.074953187899979318,"bottom":-0.0078673358794385286,"right":0.6364725933500206,"top":0.71880483587943844},"atlasBounds":{"left":250.5,"bottom":218.5,"right":335.5,"top":328.5}},{"unicode":79,"advance":0.6875,"planeBounds":{"left":0.049533935345272451,"bottom":-0.017776501857968668,"right":0.63747778340472738,"top":0.72871400185796853},"atlasBounds":{"left":0.5,"bottom":329.5,"right":89.5,"top":442.5}},{"unicode":80,"advance":0.630859375,"planeBounds":{"left":0.073890339530862881,"bottom":-0.0078673358794385286,"right":0.60237919171913701,"top":0.71880483587943844},"atlasBounds":{"left":82.5,"bottom":218.5,"right":162.5,"top":328.5}},{"unicode":81,"advance":0.6875,"planeBounds":{"left":0.046604247845272451,"bottom":-0.12910422365297272,"right":0.63454809590472738,"top":0.72969016115297269},"atlasBounds":{"left":473.5,"bottom":589.5,"right":562.5,"top":719.5}},{"unicode":82,"advance":0.61572265625,"planeBounds":{"left":0.072540409204686171,"bottom":-0.0078673358794385286,"right":0.6076353720453137,"top":0.71880483587943844},"atlasBounds":{"left":0.5,"bottom":218.5,"right":81.5,"top":328.5}},{"unicode":83,"advance":0.59326171875,"planeBounds":{"left":0.029815799829686164,"bottom":-0.017776501857968668,"right":0.5649107626703137,"top":0.72871400185796853},"atlasBounds":{"left":90.5,"bottom":329.5,"right":171.5,"top":442.5}},{"unicode":84,"advance":0.5966796875,"planeBounds":{"left":0.014765366948802596,"bottom":-0.0078673358794385286,"right":0.58289088305119729,"top":0.71880483587943844},"atlasBounds":{"left":163.5,"bottom":218.5,"right":249.5,"top":328.5}},{"unicode":85,"advance":0.6484375,"planeBounds":{"left":0.061439167655862881,"bottom":-0.019356259031791955,"right":0.58992801984413701,"top":0.72052813403179183},"atlasBounds":{"left":616.5,"bottom":330.5,"right":696.5,"top":442.5}},{"unicode":86,"advance":0.63623046875,"planeBounds":{"left":0.0048132596382121744,"bottom":-0.0078673358794385286,"right":0.63239377161178767,"top":0.71880483587943844},"atlasBounds":{"left":762.5,"bottom":332.5,"right":857.5,"top":442.5}},{"unicode":87,"advance":0.88720703125,"planeBounds":{"left":0.021659769173203964,"bottom":-0.0078673358794385286,"right":0.87384804332679589,"top":0.71880483587943844},"atlasBounds":{"left":893.5,"bottom":609.5,"right":1022.5,"top":719.5}},{"unicode":88,"advance":0.626953125,"planeBounds":{"left":0.020237060345272454,"bottom":-0.0078673358794385286,"right":0.60818090840472738,"top":0.71880483587943844},"atlasBounds":{"left":348.5,"bottom":107.5,"right":437.5,"top":217.5}},{"unicode":89,"advance":0.6005859375,"planeBounds":{"left":-0.0012616284320809716,"bottom":-0.0078673358794385286,"right":0.59989444093208089,"top":0.71880483587943844},"atlasBounds":{"left":81.5,"bottom":107.5,"right":172.5,"top":217.5}},{"unicode":90,"advance":0.5986328125,"planeBounds":{"left":0.033233768579686164,"bottom":-0.0078673358794385286,"right":0.5683287314203137,"top":0.71880483587943844},"atlasBounds":{"left":787.5,"bottom":218.5,"right":868.5,"top":328.5}},{"unicode":91,"advance":0.26513671875,"planeBounds":{"left":0.064238418339698608,"bottom":-0.16207711860033028,"right":0.26242173791030143,"top":0.82223336860033025},"atlasBounds":{"left":86.5,"bottom":570.5,"right":116.5,"top":719.5}},{"unicode":92,"advance":0.41015625,"planeBounds":{"left":0.012754180429397216,"bottom":-0.068112411940028941,"right":0.40912081957060281,"top":0.71801475569002882},"atlasBounds":{"left":638.5,"bottom":600.5,"right":698.5,"top":719.5}},{"unicode":93,"advance":0.26513671875,"planeBounds":{"left":-0.0024119722853014154,"bottom":-0.16207711860033028,"right":0.19577134728530138,"top":0.82223336860033025},"atlasBounds":{"left":117.5,"bottom":570.5,"right":147.5,"top":719.5}},{"unicode":94,"advance":0.41796875,"planeBounds":{"left":0.023036714234104069,"bottom":0.34847616735910403,"right":0.39297891076589592,"top":0.71841836389089586},"atlasBounds":{"left":777.5,"bottom":161.5,"right":833.5,"top":217.5}},{"unicode":95,"advance":0.451171875,"planeBounds":{"left":-0.0056279353323699412,"bottom":-0.083108008941473993,"right":0.45679981033236994,"top":0.0093775401914739792},"atlasBounds":{"left":73.5,"bottom":6.5,"right":143.5,"top":20.5}},{"unicode":96,"advance":0.30908203125,"planeBounds":{"left":0.020637846111168454,"bottom":0.59894932842175885,"right":0.23863949763883152,"top":0.75749598407824115},"atlasBounds":{"left":438.5,"bottom":110.5,"right":471.5,"top":134.5}},{"unicode":97,"advance":0.5439453125,"planeBounds":{"left":0.043329416868806772,"bottom":-0.016599546475020693,"right":0.49915105188119319,"top":0.5449198589750206},"atlasBounds":{"left":358.5,"bottom":21.5,"right":427.5,"top":106.5}},{"unicode":98,"advance":0.56103515625,"planeBounds":{"left":0.060778314667630062,"bottom":-0.019643340988852235,"right":0.52320606033236994,"top":0.75987771598885212},"atlasBounds":{"left":699.5,"bottom":601.5,"right":769.5,"top":719.5}},{"unicode":99,"advance":0.5234375,"planeBounds":{"left":0.036364252167630062,"bottom":-0.016599546475020693,"right":0.49879199783236994,"top":0.5449198589750206},"atlasBounds":{"left":287.5,"bottom":21.5,"right":357.5,"top":106.5}},{"unicode":100,"advance":0.56396484375,"planeBounds":{"left":0.038073236542630062,"bottom":-0.019643340988852235,"right":0.50050098220736994,"top":0.75987771598885212},"atlasBounds":{"left":770.5,"bottom":601.5,"right":840.5,"top":719.5}},{"unicode":101,"advance":0.52978515625,"planeBounds":{"left":0.038317377167630062,"bottom":-0.016599546475020693,"right":0.50074512283236994,"top":0.5449198589750206},"atlasBounds":{"left":149.5,"bottom":21.5,"right":219.5,"top":106.5}},{"unicode":102,"advance":0.34716796875,"planeBounds":{"left":0.020509022114987636,"bottom":-0.0096335753638522349,"right":0.35742066538501238,"top":0.76988748161385212},"atlasBounds":{"left":841.5,"bottom":601.5,"right":892.5,"top":719.5}},{"unicode":103,"advance":0.56103515625,"planeBounds":{"left":0.038805658417630062,"bottom":-0.21481230001032209,"right":0.50123340408236994,"top":0.54489042501032192},"atlasBounds":{"left":367.5,"bottom":444.5,"right":437.5,"top":559.5}},{"unicode":104,"advance":0.55078125,"planeBounds":{"left":0.061424450673513625,"bottom":-0.0081544178364988083,"right":0.49082164307648635,"top":0.75815441783649862},"atlasBounds":{"left":0.5,"bottom":443.5,"right":65.5,"top":559.5}},{"unicode":105,"advance":0.24267578125,"planeBounds":{"left":0.05955640192764243,"bottom":-0.0095906340317919551,"right":0.18507250432235753,"top":0.73029375903179183},"atlasBounds":{"left":391.5,"bottom":330.5,"right":410.5,"top":442.5}},{"unicode":106,"advance":0.23876953125,"planeBounds":{"left":-0.040641450763831549,"bottom":-0.22197785759444671,"right":0.17736020076383152,"top":0.72930207634444666},"atlasBounds":{"left":244.5,"bottom":575.5,"right":277.5,"top":719.5}},{"unicode":107,"advance":0.5068359375,"planeBounds":{"left":0.059442698118806772,"bottom":-0.0081544178364988083,"right":0.51526433313119313,"top":0.75815441783649862},"atlasBounds":{"left":66.5,"bottom":443.5,"right":135.5,"top":559.5}},{"unicode":108,"advance":0.24267578125,"planeBounds":{"left":0.068489005406172587,"bottom":-0.0081544178364988083,"right":0.17418677584382741,"top":0.75815441783649862},"atlasBounds":{"left":136.5,"bottom":443.5,"right":152.5,"top":559.5}},{"unicode":109,"advance":0.87646484375,"planeBounds":{"left":0.058381059364677898,"bottom":-0.0084136786488439776,"right":0.81808378438532192,"top":0.54649961614884379},"atlasBounds":{"left":515.5,"bottom":22.5,"right":630.5,"top":106.5}},{"unicode":110,"advance":0.5517578125,"planeBounds":{"left":0.061424450673513625,"bottom":-0.0084136786488439776,"right":0.49082164307648635,"top":0.54649961614884379},"atlasBounds":{"left":673.5,"bottom":22.5,"right":738.5,"top":106.5}},{"unicode":111,"advance":0.5703125,"planeBounds":{"left":0.037182959911746485,"bottom":-0.016599546475020693,"right":0.53264125883825342,"top":0.5449198589750206},"atlasBounds":{"left":73.5,"bottom":21.5,"right":148.5,"top":106.5}},{"unicode":112,"advance":0.56103515625,"planeBounds":{"left":0.060290033417630062,"bottom":-0.21237089376032209,"right":0.52271777908236994,"top":0.54733183126032192},"atlasBounds":{"left":296.5,"bottom":444.5,"right":366.5,"top":559.5}},{"unicode":113,"advance":0.568359375,"planeBounds":{"left":0.037829095917630062,"bottom":-0.21237089376032209,"right":0.50025684158236994,"top":0.54733183126032192},"atlasBounds":{"left":225.5,"bottom":444.5,"right":295.5,"top":559.5}},{"unicode":114,"advance":0.33837890625,"planeBounds":{"left":0.060619653501754772,"bottom":-0.0084136786488439776,"right":0.33147019024824526,"top":0.54649961614884379},"atlasBounds":{"left":631.5,"bottom":22.5,"right":672.5,"top":106.5}},{"unicode":115,"advance":0.515625,"planeBounds":{"left":0.038346004722336915,"bottom":-0.016599546475020693,"right":0.4743493077776631,"top":0.5449198589750206},"atlasBounds":{"left":220.5,"bottom":21.5,"right":286.5,"top":106.5}},{"unicode":116,"advance":0.32666015625,"planeBounds":{"left":-0.0037471856291287952,"bottom":-0.016972511096201532,"right":0.30013390437912885,"top":0.66345688609620135},"atlasBounds":{"left":26.5,"bottom":3.5,"right":72.5,"top":106.5}},{"unicode":117,"advance":0.55126953125,"planeBounds":{"left":0.059715466298513625,"bottom":-0.018179303648843976,"right":0.48911265870148635,"top":0.53673399114884379},"atlasBounds":{"left":449.5,"bottom":22.5,"right":514.5,"top":106.5}},{"unicode":118,"advance":0.484375,"planeBounds":{"left":0.0064498687164533447,"bottom":-0.006690380496490551,"right":0.47548372503354663,"top":0.5350106929964904},"atlasBounds":{"left":922.5,"bottom":24.5,"right":993.5,"top":106.5}},{"unicode":119,"advance":0.75146484375,"planeBounds":{"left":0.011175632870561471,"bottom":-0.006690380496490551,"right":0.73784780462943844,"top":0.5350106929964904},"atlasBounds":{"left":739.5,"bottom":24.5,"right":849.5,"top":106.5}},{"unicode":120,"advance":0.49560546875,"planeBounds":{"left":0.012309243716453346,"bottom":-0.006690380496490551,"right":0.48134310003354663,"top":0.5350106929964904},"atlasBounds":{"left":850.5,"bottom":24.5,"right":921.5,"top":106.5}},{"unicode":121,"advance":0.47314453125,"planeBounds":{"left":0.0013229155914533447,"bottom":-0.22238065938532209,"right":0.47035677190854663,"top":0.53732206563532192},"atlasBounds":{"left":153.5,"bottom":444.5,"right":224.5,"top":559.5}},{"unicode":122,"advance":0.49560546875,"planeBounds":{"left":0.034683895347336915,"bottom":-0.006690380496490551,"right":0.4706871984026631,"top":0.5350106929964904},"atlasBounds":{"left":438.5,"bottom":135.5,"right":504.5,"top":217.5}},{"unicode":123,"advance":0.33837890625,"planeBounds":{"left":0.023955618419694489,"bottom":-0.18831507889915358,"right":0.33444281908030554,"top":0.78938929764915344},"atlasBounds":{"left":196.5,"bottom":571.5,"right":243.5,"top":719.5}},{"unicode":124,"advance":0.24365234375,"planeBounds":{"left":0.075583397308526007,"bottom":-0.13984641115297272,"right":0.16806894644147397,"top":0.71894797365297269},"atlasBounds":{"left":563.5,"bottom":589.5,"right":577.5,"top":719.5}},{"unicode":125,"advance":0.33837890625,"planeBounds":{"left":0.0022271027946944911,"bottom":-0.18831507889915358,"right":0.31271430345530554,"top":0.78938929764915344},"atlasBounds":{"left":148.5,"bottom":571.5,"right":195.5,"top":719.5}},{"unicode":126,"advance":0.68017578125,"planeBounds":{"left":0.056269273198802594,"bottom":0.1882475420623452,"right":0.62439478930119729,"top":0.39964308293765483},"atlasBounds":{"left":933.5,"bottom":185.5,"right":1019.5,"top":217.5}}],"kerning":[]}
diff --git a/assets/roboto.png b/assets/roboto.png
new file mode 100644
index 0000000000000000000000000000000000000000..89b02748344575a1d88383963b3796e94b8ebd7c
Binary files /dev/null and b/assets/roboto.png differ
diff --git a/assets/roboto.png.old b/assets/roboto.png.old
new file mode 100644
index 0000000000000000000000000000000000000000..7f4e0f9128bb32bb381d5ae42d21ed7cc8177e5a
Binary files /dev/null and b/assets/roboto.png.old differ
diff --git a/bevy_kayak_ui/Cargo.toml b/bevy_kayak_ui/Cargo.toml
index 1ffcf7e7de740ee391bff8892cd6eaffecf43563..6a9445a03b581ed9122fdc4561b4c72a63605e41 100644
--- a/bevy_kayak_ui/Cargo.toml
+++ b/bevy_kayak_ui/Cargo.toml
@@ -5,9 +5,12 @@ edition = "2021"
 
 [dependencies]
 bytemuck = "1.7.2"
-bevy = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
+bevy = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
 kayak_core = { path = "../kayak_core" }
 kayak_components = { path = "../kayak_components" }
 kayak_render_macros = { path = "../kayak_render_macros" }
 kayak_font = { path = "../kayak_font" }
-crevice = { git = "https://github.com/StarArawn/bevy", rev = "b26f563b13c267ffe1ee801bd71fd40b98a256e7" }
+crevice = { git = "https://github.com/StarArawn/bevy", rev = "146ddbe5f839d5d635fe350a535155231d4050c2" }
+serde = "1.0"
+serde_json = "1.0"
+serde_path_to_error = "0.1"
diff --git a/bevy_kayak_ui/src/camera/ortho.rs b/bevy_kayak_ui/src/camera/ortho.rs
index e4e6621f259008610d897e843f8268c625ae51c0..ceacb30fa8fd644551117eb6d4f227dcfccfe2ff 100644
--- a/bevy_kayak_ui/src/camera/ortho.rs
+++ b/bevy_kayak_ui/src/camera/ortho.rs
@@ -1,11 +1,12 @@
 use bevy::ecs::reflect::ReflectComponent;
+use bevy::prelude::Component;
 use bevy::{
     math::Mat4,
     reflect::Reflect,
     render2::camera::{CameraProjection, DepthCalculation, ScalingMode, WindowOrigin},
 };
 
-#[derive(Debug, Clone, Reflect)]
+#[derive(Debug, Clone, Component, Reflect)]
 #[reflect(Component)]
 pub struct UIOrthographicProjection {
     pub left: f32,
diff --git a/bevy_kayak_ui/src/render/unified/font/extract.rs b/bevy_kayak_ui/src/render/unified/font/extract.rs
index 65dbaba5c67fcee97a9d284be6718b06c399f468..ce8844dde4d434a346ecd64e354e29836e7a6317 100644
--- a/bevy_kayak_ui/src/render/unified/font/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/font/extract.rs
@@ -57,28 +57,91 @@ pub fn extract_texts(
             }
         }
         let font = fonts.get(font_handle.clone()).unwrap();
-        let char_layouts = font.font.get_layout(content, font_size);
+        let max_glyph_size = font
+            .sdf
+            .as_ref()
+            .and_then(|sdf| Some(sdf.max_glyph_size()))
+            .unwrap_or_default();
+        // let char_layouts = font.font.get_layout(
+        //     content,
+        //     font_size,
+        //     font.sdf.as_ref().unwrap().atlas.size,
+        //     (max_glyph_size.x, max_glyph_size.y),
+        // );
+        // let font_scale = font_size / font.font.units_per_em() as f32;
+        // for (c, (x, y), (width, height)) in char_layouts {
+        //     // let size = font.font.get_size(c, font_size);
+        //     let position_x = layout.posx + x;
+        //     let position_y = layout.posy + y;
+        //     extracted_texts.push(ExtractQuadBundle {
+        //         extracted_quad: ExtractedQuad {
+        //             font_handle: Some(font_handle.clone()),
+        //             rect: Rect {
+        //                 min: Vec2::new(position_x, position_y),
+        //                 max: Vec2::new(position_x + width, position_y + height),
+        //             },
+        //             color: to_bevy_color(background_color),
+        //             vertex_index: 0,
+        //             char_id: font.font.get_char_id(c),
+        //             z_index: layout.z_index,
+        //             quad_type: UIQuadType::Text,
+        //             type_index: 0,
+        //             border_radius: (0.0, 0.0, 0.0, 0.0),
+        //         },
+        //     });
+        // }
 
-        for (c, (x, y), (width, height)) in char_layouts {
-            // let size = font.font.get_size(c, font_size);
-            let position_x = layout.posx + x;
-            let position_y = layout.posy + y;
-            extracted_texts.push(ExtractQuadBundle {
-                extracted_quad: ExtractedQuad {
-                    font_handle: Some(font_handle.clone()),
-                    rect: Rect {
-                        min: Vec2::new(position_x, position_y),
-                        max: Vec2::new(position_x + width, position_y + height),
+        let mut x = 0.0;
+        for c in content.chars() {
+            if let Some(glyph) = font
+                .sdf
+                .as_ref()
+                .unwrap()
+                .glyphs
+                .iter()
+                .find(|glyph| glyph.unicode == c)
+            {
+                let plane_bounds = glyph.plane_bounds.as_ref();
+                let (left, top, width, height) = match plane_bounds {
+                    Some(val) => (
+                        val.left,
+                        val.top,
+                        val.size().x * font_size,
+                        val.size().y * font_size,
+                    ),
+                    None => (0.0, 0.0, 0.0, 0.0),
+                };
+
+                let font_ratio = font_size / font.sdf.as_ref().unwrap().atlas.size;
+                let resized_max_glyph_size =
+                    (max_glyph_size.x * font_ratio, max_glyph_size.y * font_ratio);
+
+                let shift_y = resized_max_glyph_size.1 - height;
+
+                let position_x = layout.posx + x + left * font_size;
+                let position_y = (layout.posy + (-top * font_size)) + font_size;
+                extracted_texts.push(ExtractQuadBundle {
+                    extracted_quad: ExtractedQuad {
+                        font_handle: Some(font_handle.clone()),
+                        rect: Rect {
+                            min: Vec2::new(position_x, position_y),
+                            max: Vec2::new(
+                                position_x + resized_max_glyph_size.0,
+                                position_y + resized_max_glyph_size.1,
+                            ),
+                        },
+                        color: to_bevy_color(background_color),
+                        vertex_index: 0,
+                        char_id: font.font.get_char_id(c),
+                        z_index: layout.z_index,
+                        quad_type: UIQuadType::Text,
+                        type_index: 0,
+                        border_radius: (0.0, 0.0, 0.0, 0.0),
                     },
-                    color: to_bevy_color(background_color),
-                    vertex_index: 0,
-                    char_id: font.font.get_char_id(c),
-                    z_index: layout.z_index,
-                    quad_type: UIQuadType::Text,
-                    type_index: 0,
-                    border_radius: (0.0, 0.0, 0.0, 0.0),
-                },
-            });
+                });
+
+                x += glyph.advance * font_size;
+            }
         }
     }
     commands.spawn_batch(extracted_texts);
diff --git a/bevy_kayak_ui/src/render/unified/font/font.rs b/bevy_kayak_ui/src/render/unified/font/font.rs
index 7a4424cdbbe7f29e72b778830d29aae73886ea24..7bfd702adaee4a0e18a848ff620637398fb9da97 100644
--- a/bevy_kayak_ui/src/render/unified/font/font.rs
+++ b/bevy_kayak_ui/src/render/unified/font/font.rs
@@ -1,8 +1,16 @@
-use bevy::reflect::TypeUuid;
+use bevy::{prelude::Handle, reflect::TypeUuid, render2::texture::Image};
 use kayak_font::Font;
 
+use super::sdf::Sdf;
+
 #[derive(Debug, Clone, TypeUuid)]
 #[uuid = "4fe4732c-6731-49bb-bafc-4690d636b848"]
 pub struct KayakFont {
+    pub sdf: Option<Sdf>,
+    pub atlas_image: Option<Handle<Image>>,
     pub font: Font,
 }
+
+// impl KayakFont {
+//     pub fn from_atlas(atlas: Texture, )
+// }
diff --git a/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs b/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs
index d96b6d0c87385e833398f902ea3835465962098f..f45898b206eac724845a3ff152defc20f0c621b3 100644
--- a/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs
+++ b/bevy_kayak_ui/src/render/unified/font/font_texture_cache.rs
@@ -1,8 +1,24 @@
-use bevy::{prelude::Handle, render2::{render_resource::{AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindingResource, Extent3d, FilterMode, ImageCopyTexture, ImageDataLayout, Origin3d, SamplerDescriptor, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureViewDescriptor, TextureViewDimension}, renderer::{RenderDevice, RenderQueue}, texture::{GpuImage, TextureFormatPixelInfo}}, utils::HashMap};
+use bevy::{
+    math::Vec2,
+    prelude::{Assets, Handle, Res},
+    render2::{
+        render_asset::RenderAssets,
+        render_resource::{
+            AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout,
+            BindingResource, CommandEncoderDescriptor, Extent3d, FilterMode, ImageCopyTexture,
+            ImageDataLayout, Origin3d, SamplerDescriptor, TextureAspect, TextureDescriptor,
+            TextureDimension, TextureFormat, TextureUsages, TextureViewDescriptor,
+            TextureViewDimension,
+        },
+        renderer::{RenderDevice, RenderQueue},
+        texture::{GpuImage, Image, TextureFormatPixelInfo},
+    },
+    utils::HashMap,
+};
 
 use crate::render::unified::pipeline::UnifiedPipeline;
 
-use super::font::KayakFont;
+use super::{font::KayakFont, sdf::Sdf};
 
 pub const MAX_CHARACTERS: u32 = 100;
 
@@ -43,36 +59,67 @@ impl FontTextureCache {
         }
     }
 
-    pub fn process_new(&mut self, device: &RenderDevice, pipeline: &UnifiedPipeline) {
-        let new_fonts = self.new_fonts.drain(..);
+    pub fn process_new(
+        &mut self,
+        device: &RenderDevice,
+        queue: &RenderQueue,
+        pipeline: &UnifiedPipeline,
+        render_images: &Res<RenderAssets<Image>>,
+    ) {
+        let new_fonts: Vec<_> = self.new_fonts.drain(..).collect();
         for kayak_font_handle in new_fonts {
+            let mut was_processed = true;
             if let Some(font) = self.fonts.get(&kayak_font_handle) {
-                Self::create_texture(
-                    &mut self.images,
-                    kayak_font_handle.clone_weak(),
-                    font,
-                    device,
-                );
+                if let Some(sdf) = &font.sdf {
+                    let atlas_handle = font.atlas_image.as_ref().unwrap();
+                    if let Some(atlas_texture) = render_images.get(atlas_handle) {
+                        Self::create_from_atlas(
+                            &mut self.images,
+                            &mut self.bind_groups,
+                            sdf,
+                            kayak_font_handle.clone_weak(),
+                            device,
+                            queue,
+                            pipeline,
+                            atlas_texture,
+                            sdf.max_glyph_size(),
+                        );
+                    } else {
+                        was_processed = false;
+                    }
+                } else {
+                    Self::create_texture(
+                        &mut self.images,
+                        kayak_font_handle.clone_weak(),
+                        (font.font.cache.dimensions.0, font.font.cache.dimensions.1),
+                        device,
+                        TextureFormat::Rgba32Float,
+                    );
 
-                let gpu_image = self.images.get(&kayak_font_handle).unwrap();
+                    let gpu_image = self.images.get(&kayak_font_handle).unwrap();
 
-                // create bind group
-                let binding = device.create_bind_group(&BindGroupDescriptor {
-                    label: Some("text_image_bind_group"),
-                    entries: &[
-                        BindGroupEntry {
-                            binding: 0,
-                            resource: BindingResource::TextureView(&gpu_image.texture_view),
-                        },
-                        BindGroupEntry {
-                            binding: 1,
-                            resource: BindingResource::Sampler(&gpu_image.sampler),
-                        },
-                    ],
-                    layout: &pipeline.image_layout,
-                });
+                    // create bind group
+                    let binding = device.create_bind_group(&BindGroupDescriptor {
+                        label: Some("text_image_bind_group"),
+                        entries: &[
+                            BindGroupEntry {
+                                binding: 0,
+                                resource: BindingResource::TextureView(&gpu_image.texture_view),
+                            },
+                            BindGroupEntry {
+                                binding: 1,
+                                resource: BindingResource::Sampler(&gpu_image.sampler),
+                            },
+                        ],
+                        layout: &pipeline.image_layout,
+                    });
 
-                self.bind_groups.insert(kayak_font_handle, binding);
+                    self.bind_groups
+                        .insert(kayak_font_handle.clone_weak(), binding);
+                }
+            }
+            if !was_processed {
+                self.new_fonts.push(kayak_font_handle.clone_weak());
             }
         }
     }
@@ -94,20 +141,21 @@ impl FontTextureCache {
     fn create_texture(
         images: &mut HashMap<Handle<KayakFont>, GpuImage>,
         font_handle: Handle<KayakFont>,
-        font: &KayakFont,
+        size: (u32, u32),
         device: &RenderDevice,
+        format: TextureFormat,
     ) {
         let texture_descriptor = TextureDescriptor {
             label: Some("font_texture_array"),
             size: Extent3d {
-                width: font.font.cache.dimensions,
-                height: font.font.cache.dimensions,
+                width: size.0,
+                height: size.1,
                 depth_or_array_layers: MAX_CHARACTERS,
             },
             mip_level_count: 1,
             sample_count: 1,
             dimension: TextureDimension::D2,
-            format: TextureFormat::Rgba32Float,
+            format,
             usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
         };
 
@@ -174,13 +222,13 @@ impl FontTextureCache {
                     ImageDataLayout {
                         offset: 0,
                         bytes_per_row: Some(
-                            std::num::NonZeroU32::new(size * format_size as u32).unwrap(),
+                            std::num::NonZeroU32::new(size.0 * format_size as u32).unwrap(),
                         ),
                         rows_per_image: None,
                     },
                     Extent3d {
-                        width: size,
-                        height: size,
+                        width: size.0,
+                        height: size.1,
                         depth_or_array_layers: 1,
                     },
                 );
@@ -245,4 +293,90 @@ impl FontTextureCache {
 
         (image, binding)
     }
+
+    pub fn create_from_atlas(
+        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,
+        atlas_texture: &GpuImage,
+        size: Vec2,
+    ) {
+        dbg!(size);
+        Self::create_texture(
+            images,
+            font_handle.clone_weak(),
+            (size.x as u32, size.y as u32),
+            device,
+            TextureFormat::Rgba8Unorm,
+        );
+
+        let mut command_encoder = device.create_command_encoder(&CommandEncoderDescriptor {
+            label: Some("create_sdf_from_atlas_encoder"),
+        });
+
+        let gpu_image = images.get(&font_handle).unwrap();
+
+        // create bind group
+        let binding = device.create_bind_group(&BindGroupDescriptor {
+            label: Some("text_image_bind_group"),
+            entries: &[
+                BindGroupEntry {
+                    binding: 0,
+                    resource: BindingResource::TextureView(&gpu_image.texture_view),
+                },
+                BindGroupEntry {
+                    binding: 1,
+                    resource: BindingResource::Sampler(&gpu_image.sampler),
+                },
+            ],
+            layout: &pipeline.image_layout,
+        });
+
+        bind_groups.insert(font_handle.clone_weak(), binding);
+
+        // Now fill the texture data.
+
+        let atlas_width = sdf.atlas.width;
+        let atlas_height = sdf.atlas.height;
+
+        for (i, glyph) in sdf.glyphs.iter().enumerate() {
+            if let Some(atlas_bounds) = glyph.atlas_bounds {
+                let glyph_size = atlas_bounds.size();
+                command_encoder.copy_texture_to_texture(
+                    ImageCopyTexture {
+                        texture: &atlas_texture.texture,
+                        mip_level: 0,
+                        origin: Origin3d {
+                            x: atlas_bounds.left as u32,
+                            y: atlas_height - atlas_bounds.top as u32,
+                            z: 0,
+                        },
+                        aspect: TextureAspect::All,
+                    },
+                    ImageCopyTexture {
+                        texture: &gpu_image.texture,
+                        mip_level: 0,
+                        origin: Origin3d {
+                            x: 0,
+                            y: 0,
+                            z: i as u32,
+                        },
+                        aspect: TextureAspect::All,
+                    },
+                    Extent3d {
+                        width: glyph_size.x as u32,
+                        height: glyph_size.y as u32,
+                        depth_or_array_layers: 1,
+                    },
+                );
+            }
+        }
+
+        let command_buffer = command_encoder.finish();
+        queue.submit(vec![command_buffer]);
+    }
 }
diff --git a/bevy_kayak_ui/src/render/unified/font/mod.rs b/bevy_kayak_ui/src/render/unified/font/mod.rs
index 6bb28ab028cc2065bbc5a714fd30b6e66d795f78..1ae275c690267860df26b5dc60f641c700a4a052 100644
--- a/bevy_kayak_ui/src/render/unified/font/mod.rs
+++ b/bevy_kayak_ui/src/render/unified/font/mod.rs
@@ -1,13 +1,19 @@
 use bevy::{
-    prelude::{AddAsset, AssetEvent, Assets, Commands, EventReader, Handle, Plugin, Res, ResMut},
+    prelude::{
+        AddAsset, AssetEvent, AssetServer, Assets, Commands, EventReader, Handle, Local, Plugin,
+        Res, ResMut,
+    },
     render2::{
+        render_asset::RenderAssets,
+        render_resource::{FilterMode, TextureFormat, TextureUsages},
         renderer::{RenderDevice, RenderQueue},
+        texture::Image,
         RenderApp, RenderStage,
     },
     utils::HashSet,
 };
 
-use self::extract::extract_texts;
+use self::{extract::extract_texts, sdf::Sdf};
 
 use super::pipeline::UnifiedPipeline;
 
@@ -15,6 +21,7 @@ mod extract;
 mod font;
 mod font_mapping;
 mod font_texture_cache;
+mod sdf;
 
 pub use font::*;
 pub use font_mapping::*;
@@ -27,7 +34,8 @@ impl Plugin for TextRendererPlugin {
     fn build(&self, app: &mut bevy::prelude::App) {
         app.add_asset::<KayakFont>()
             .init_resource::<FontMapping>()
-            .add_startup_system(load_fonts);
+            .add_startup_system(load_fonts)
+            .add_system(set_font_texture);
 
         let render_app = app.sub_app(RenderApp);
         render_app.add_system_to_stage(RenderStage::Extract, extract_texts);
@@ -46,18 +54,70 @@ pub struct ExtractedFonts {
     pub fonts: Vec<(Handle<KayakFont>, KayakFont)>,
 }
 
-fn load_fonts(mut font_assets: ResMut<Assets<KayakFont>>, mut font_mapping: ResMut<FontMapping>) {
+fn load_fonts(
+    mut font_assets: ResMut<Assets<KayakFont>>,
+    mut font_mapping: ResMut<FontMapping>,
+    asset_server: Res<AssetServer>,
+) {
     let font_bytes = include_bytes!("../../../../../resources/Roboto-Regular.ttf");
-    let font = kayak_font::Font::new(font_bytes, 128);
+    let sdf = Sdf::from_string(include_str!("../../../../../assets/roboto.json").to_string());
+    let max_glyph_size = sdf.max_glyph_size();
+    let mut font = kayak_font::Font::new(
+        font_bytes,
+        (max_glyph_size.x as u32, max_glyph_size.y as u32),
+    );
+
+    let atlas_image: Handle<Image> = asset_server.load("roboto.png");
+
+    for glyph in sdf.glyphs.iter() {
+        if !font.cache.has_character(glyph.unicode) {
+            font.cache.add_character(glyph.unicode);
+        }
+    }
 
-    let handle = font_assets.add(KayakFont { font });
+    let handle = font_assets.add(KayakFont {
+        font,
+        atlas_image: Some(atlas_image),
+        sdf: Some(sdf),
+    });
     font_mapping.add(handle);
 }
 
+pub fn set_font_texture(
+    mut texture_events: EventReader<AssetEvent<Image>>,
+    mut textures: ResMut<Assets<Image>>,
+    asset_server: Res<AssetServer>,
+) {
+    // quick and dirty, run this for all textures anytime a texture is created.
+    for event in texture_events.iter() {
+        dbg!(&event);
+        match event {
+            AssetEvent::Created { handle } => {
+                let handle_path = asset_server.get_handle_path(handle).unwrap();
+                dbg!(&handle_path);
+                if handle_path.path().to_str().unwrap().contains("roboto") {
+                    if let Some(mut texture) = textures.get_mut(handle) {
+                        dbg!("Setting font texture!");
+                        texture.texture_descriptor.format = TextureFormat::Rgba8Unorm;
+                        texture.sampler_descriptor.min_filter = FilterMode::Linear;
+                        texture.sampler_descriptor.mipmap_filter = FilterMode::Linear;
+                        texture.sampler_descriptor.mag_filter = FilterMode::Linear;
+                        texture.texture_descriptor.usage =
+                            TextureUsages::COPY_DST | TextureUsages::COPY_SRC;
+                    }
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
 fn extract_fonts(
+    mut not_processed: Local<Vec<Handle<KayakFont>>>,
     mut commands: Commands,
     font_assets: Res<Assets<KayakFont>>,
     mut events: EventReader<AssetEvent<KayakFont>>,
+    mut textures: ResMut<Assets<Image>>,
 ) {
     let mut extracted_fonts = ExtractedFonts { fonts: Vec::new() };
     let mut changed_assets = HashSet::default();
@@ -65,10 +125,10 @@ fn extract_fonts(
     for event in events.iter() {
         match event {
             AssetEvent::Created { handle } => {
-                changed_assets.insert(handle);
+                changed_assets.insert(handle.clone_weak());
             }
             AssetEvent::Modified { handle } => {
-                changed_assets.insert(handle);
+                changed_assets.insert(handle.clone_weak());
             }
             AssetEvent::Removed { handle } => {
                 if !changed_assets.remove(handle) {
@@ -78,11 +138,30 @@ fn extract_fonts(
         }
     }
 
+    for handle in not_processed.drain(..) {
+        changed_assets.insert(handle);
+    }
+
     for handle in changed_assets {
-        let font_asset = font_assets.get(handle).unwrap();
-        let font = font_asset.clone();
+        let font_asset = font_assets.get(&handle).unwrap();
+        if let Some(image) = font_asset.atlas_image.as_ref() {
+            if let Some(image) = textures.get(image) {
+                if !image
+                    .texture_descriptor
+                    .usage
+                    .contains(TextureUsages::COPY_SRC)
+                {
+                    not_processed.push(handle);
+                    continue;
+                }
+            } else {
+                not_processed.push(handle);
+                continue;
+            }
+        }
 
-        extracted_fonts.fonts.push((handle.clone_weak(), font));
+        let font = font_asset.clone();
+        extracted_fonts.fonts.push((handle, font));
     }
 
     commands.insert_resource(extracted_fonts);
@@ -92,7 +171,8 @@ fn prepare_fonts(
     mut extracted_fonts: ResMut<ExtractedFonts>,
     mut font_texture_cache: ResMut<FontTextureCache>,
 ) {
-    for (handle, font) in extracted_fonts.fonts.drain(..) {
+    let fonts: Vec<_> = extracted_fonts.fonts.drain(..).collect();
+    for (handle, font) in fonts {
         font_texture_cache.add(handle, font);
     }
 }
@@ -102,7 +182,8 @@ fn create_and_update_font_cache_texture(
     queue: Res<RenderQueue>,
     pipeline: Res<UnifiedPipeline>,
     mut font_texture_cache: ResMut<FontTextureCache>,
+    images: Res<RenderAssets<Image>>,
 ) {
-    font_texture_cache.process_new(&device, &pipeline);
+    font_texture_cache.process_new(&device, &queue, &pipeline, &images);
     font_texture_cache.process_updated(&queue);
 }
diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/atlas.rs b/bevy_kayak_ui/src/render/unified/font/sdf/atlas.rs
new file mode 100644
index 0000000000000000000000000000000000000000..58f653730bdec6c7ca837c68eff693fec4447edd
--- /dev/null
+++ b/bevy_kayak_ui/src/render/unified/font/sdf/atlas.rs
@@ -0,0 +1,32 @@
+use serde::Deserialize;
+
+#[derive(Deserialize, Debug, Copy, Clone)]
+pub enum SDFType {
+    #[serde(alias = "msdf")]
+    Msdf,
+}
+
+#[derive(Deserialize, Debug, Copy, Clone)]
+pub enum Origin {
+    #[serde(alias = "bottom")]
+    Bottom,
+    #[serde(alias = "left")]
+    Left,
+    #[serde(alias = "right")]
+    Right,
+    #[serde(alias = "top")]
+    Top,
+}
+
+#[derive(Deserialize, Debug, Copy, Clone)]
+pub struct Atlas {
+    #[serde(alias = "type")]
+    pub sdf_type: SDFType,
+    #[serde(alias = "distanceRange")]
+    pub distance_range: f32,
+    pub size: f32,
+    pub width: u32,
+    pub height: u32,
+    #[serde(alias = "yOrigin")]
+    pub y_origin: Origin,
+}
diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/glyph.rs b/bevy_kayak_ui/src/render/unified/font/sdf/glyph.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f883522fc5e9932423ad33cb4ab672ac45ed70ae
--- /dev/null
+++ b/bevy_kayak_ui/src/render/unified/font/sdf/glyph.rs
@@ -0,0 +1,46 @@
+use bevy::math::Vec2;
+use serde::{Deserialize, Deserializer};
+
+fn from_u32<'de, D>(deserializer: D) -> Result<char, D::Error>
+where
+    D: Deserializer<'de>,
+{
+    let number: u32 = Deserialize::deserialize(deserializer)?;
+    match char::from_u32(number) {
+        Some(c) => Ok(c),
+        None => Err(serde::de::Error::custom("Can't deserialize char from u32!")),
+    }
+}
+
+#[derive(Deserialize, Debug, Clone, Copy)]
+pub struct Glyph {
+    #[serde(deserialize_with = "from_u32")]
+    pub unicode: char,
+    pub advance: f32,
+    #[serde(alias = "atlasBounds")]
+    pub atlas_bounds: Option<Rect>,
+    #[serde(alias = "planeBounds")]
+    pub plane_bounds: Option<Rect>,
+}
+
+#[derive(Deserialize, Default, Clone, Copy, Debug)]
+pub struct Rect {
+    pub left: f32,
+    pub bottom: f32,
+    pub right: f32,
+    pub top: f32,
+}
+
+impl Rect {
+    pub fn width(&self) -> f32 {
+        self.right - self.left
+    }
+
+    pub fn height(&self) -> f32 {
+        self.top - self.bottom
+    }
+
+    pub fn size(&self) -> Vec2 {
+        Vec2::new(self.width(), self.height())
+    }
+}
diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/metrics.rs b/bevy_kayak_ui/src/render/unified/font/sdf/metrics.rs
new file mode 100644
index 0000000000000000000000000000000000000000..005e9bb567d503da679b64be21df6060cdf2852b
--- /dev/null
+++ b/bevy_kayak_ui/src/render/unified/font/sdf/metrics.rs
@@ -0,0 +1,15 @@
+use serde::Deserialize;
+
+#[derive(Deserialize, Debug, Copy, Clone)]
+pub struct Metrics {
+    #[serde(alias = "emSize")]
+    em_size: f32,
+    #[serde(alias = "lineHeight")]
+    line_height: f32,
+    ascender: f32,
+    descender: f32,
+    #[serde(alias = "underlineY")]
+    underline_y: f32,
+    #[serde(alias = "underlineThickness")]
+    underline_thickness: f32,
+}
diff --git a/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs b/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2a9ccf3c8746105fcd7fd87d9dd648fd4c5df50a
--- /dev/null
+++ b/bevy_kayak_ui/src/render/unified/font/sdf/mod.rs
@@ -0,0 +1,77 @@
+use crate::render::unified::pipeline::UnifiedPipeline;
+
+use self::{
+    atlas::Atlas,
+    glyph::{Glyph, Rect},
+    metrics::Metrics,
+};
+use bevy::{
+    math::Vec2,
+    prelude::Handle,
+    render2::{
+        renderer::{RenderDevice, RenderQueue},
+        texture::GpuImage,
+    },
+};
+use serde::Deserialize;
+
+use super::{FontTextureCache, KayakFont};
+
+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 744969b56c5e8a9bb00e3286644f2d761cb1992a..f110ca4fd630842b5def4579c9e89c7c55378df9 100644
--- a/bevy_kayak_ui/src/render/unified/pipeline.rs
+++ b/bevy_kayak_ui/src/render/unified/pipeline.rs
@@ -5,7 +5,7 @@ use bevy::{
         SystemState,
     },
     math::{const_vec3, Mat4, Quat, Vec3, Vec4},
-    prelude::{Bundle, Entity, FromWorld, Handle, Query, Res, ResMut, World},
+    prelude::{Bundle, Component, Entity, FromWorld, Handle, Query, Res, ResMut, World},
     render2::{
         color::Color,
         render_phase::{Draw, DrawFunctions, RenderPhase, TrackedRenderPass},
@@ -213,6 +213,7 @@ pub enum UIQuadType {
     Text,
 }
 
+#[derive(Component)]
 pub struct ExtractedQuad {
     pub rect: Rect,
     pub color: Color,
diff --git a/bevy_kayak_ui/src/render/unified/shader.wgsl b/bevy_kayak_ui/src/render/unified/shader.wgsl
index 11c8108a5453172a28d28b8b5da034e5c8de3eab..90a5af20ebd89422ce43604ca5bf70c367e7f87c 100644
--- a/bevy_kayak_ui/src/render/unified/shader.wgsl
+++ b/bevy_kayak_ui/src/render/unified/shader.wgsl
@@ -48,7 +48,7 @@ var sprite_texture: texture_2d_array<f32>;
 [[group(1), binding(1)]]
 var sprite_sampler: sampler;
 
-let RADIUS: f32 = 0.5;
+let RADIUS: f32 = 0.1;
 
 
 fn sd_box_rounded(
@@ -71,6 +71,9 @@ fn sd_box_rounded(
 
 [[stage(fragment)]]
 fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
+    var pxRange = 2.5;
+    var tex_dimensions = textureDimensions(sprite_texture);
+    var msdfUnit = vec2<f32>(pxRange, pxRange) / vec2<f32>(f32(tex_dimensions.x), f32(tex_dimensions.y));
     if (quad_type.t == 0) {
         var dist = sd_box_rounded(
             in.position.xy,
@@ -86,12 +89,22 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
         return vec4<f32>(in.color.rgb, dist);
     }
     if (quad_type.t == 1) {
-        var x = textureSample(sprite_texture, sprite_sampler, in.uv.xy, i32(in.uv.z)); 
+        var x = textureSample(sprite_texture, sprite_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y), i32(in.uv.z)); 
         var v = max(min(x.r, x.g), min(max(x.r, x.g), x.b));
         var c = v; //remap(v);
 
-        var v2 = c / fwidth( c );
-        var a = v2 + RADIUS; //clamp( v2 + RADIUS, 0.0, 1.0 );
+        // var v2 = c / fwidth( c );
+        // var a = clamp( v2 + RADIUS, 0.0, 1.0 );
+        // var a = smoothStep(
+        //     max(RADIUS - 0.5, 0.0),
+        //     RADIUS + 0.5,
+        //     c);
+
+        // var w = fwidth(c);
+        // var a = smoothStep(0.5 - w, 0.5 + w, c);
+
+        var sigDist = (c - 0.5) * dot(msdfUnit, 0.5 / fwidth(in.uv.xy));
+        var a = clamp(sigDist + 0.5, 0.0, 1.0);
 
         return vec4<f32>(in.color.rgb, a);
     }
diff --git a/kayak_components/src/window.rs b/kayak_components/src/window.rs
index 85c7e3e6be92d3353c86c225d015a761c16eef52..6f779562ce8aba457a377c9a665d4bb8d8734c63 100644
--- a/kayak_components/src/window.rs
+++ b/kayak_components/src/window.rs
@@ -47,7 +47,7 @@ pub fn Window(
     };
 
     let title_text_styles = Style {
-        height: StyleProp::Value(Units::Pixels(16.0)),
+        height: StyleProp::Value(Units::Pixels(22.0)),
         ..Style::default()
     };
 
@@ -56,7 +56,7 @@ pub fn Window(
         <Fragment>
             <Clip>
                 <Background styles={Some(title_background_styles)}>
-                    <Text styles={Some(title_text_styles)} size={14.0} content={title}>{}</Text>
+                    <Text styles={Some(title_text_styles)} size={16.0} content={title}>{}</Text>
                 </Background>
             </Clip>
             <Clip>
diff --git a/kayak_font/examples/simple.rs b/kayak_font/examples/simple.rs
index 09f8903e9eb757c0a80b715e86e58d9296a477c3..97efddbdff2d524c27beb9bf9a17a6636d0dd145 100644
--- a/kayak_font/examples/simple.rs
+++ b/kayak_font/examples/simple.rs
@@ -4,7 +4,7 @@ use kayak_font::Font;
 
 fn main() {
     let font_bytes = include_bytes!("../resources/Roboto-Regular.ttf");
-    let mut font = Font::new(font_bytes, 64);
+    let mut font = Font::new(font_bytes, (64, 64));
 
     font.add_character('A');
     font.add_character('B');
@@ -22,7 +22,7 @@ fn main() {
         let file = File::create(format!("./test-{}.png", c)).unwrap();
         let ref mut w = BufWriter::new(file);
 
-        let mut encoder = png::Encoder::new(w, dimensions, dimensions);
+        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/src/font.rs b/kayak_font/src/font.rs
index 806d47e1169949f0bc3d50c3c2b92b2f8bd9d837..cd0e7055bd442a54f2577c3a22d265d9ca22d470 100644
--- a/kayak_font/src/font.rs
+++ b/kayak_font/src/font.rs
@@ -8,14 +8,14 @@ use crate::{compute_msdf, recolor_contours, rescale_contours, PathCollector};
 #[derive(Debug, Clone)]
 pub struct FontCache {
     count: usize,
-    pub dimensions: u32,
+    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) -> Self {
+    pub fn new(texture_size: (u32, u32)) -> Self {
         Self {
             count: 0,
             dimensions: texture_size,
@@ -25,6 +25,12 @@ impl FontCache {
         }
     }
 
+    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()
@@ -63,11 +69,11 @@ impl FontCache {
         self.count += 1;
     }
 
-    fn has_character(&self, c: char) -> bool {
+    pub fn has_character(&self, c: char) -> bool {
         self.chars.contains_key(&c)
     }
 
-    fn get_dimensions(&self) -> u32 {
+    fn get_dimensions(&self) -> (u32, u32) {
         self.dimensions
     }
 }
@@ -80,7 +86,7 @@ pub struct Font {
 }
 
 impl Font {
-    pub fn new(font_data: &'static [u8], texture_size: u32) -> 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())
@@ -109,6 +115,8 @@ impl Font {
         &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);
@@ -116,6 +124,11 @@ impl Font {
             &[&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
@@ -125,37 +138,12 @@ impl Font {
                     return None;
                 }
                 // let metrics = self.font.metrics(glyph_position.parent, font_size);
-                let font_scale = font_size / self.font.units_per_em() as f32;
-                let scale =
-                    if let Some(glyph) = self.internal_face.glyph_index(glyph_position.parent) {
-                        // TODO: Cache this in add_character..
-                        let mut path_collector = PathCollector::new();
-                        let rect = self
-                            .internal_face
-                            .outline_glyph(glyph, &mut path_collector)
-                            .unwrap();
-                        let width = rect.width();
-                        let height = rect.height();
-                        width.max(height) as f32 * font_scale
-                    } else {
-                        0.0
-                    };
-
-                // let shift_x = if scale > glyph_position.width as f32 {
-                //     scale - glyph_position.width as f32
-                // } else {
-                //     // glyph_position.width as f32 - scale
-                //     0.0
-                // };
-                let shift_y = if scale > glyph_position.height as f32 {
-                    scale - glyph_position.height as f32
-                } else {
-                    0.0
-                };
+
+                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),
-                    (scale, scale),
+                    resized_max_glyph_size,
                 ))
             })
             .collect();
@@ -215,7 +203,7 @@ impl Font {
                     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() as usize);
+                let msdf = compute_msdf(&contours, self.cache.get_dimensions().0 as usize);
 
                 self.cache.set_texture(c, msdf);
             }
@@ -250,4 +238,30 @@ impl Font {
             .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 mut area_size = 0.0;
+    let mut image_size = 0.0;
+
+    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
 }