diff --git a/assets/lato-light.kttf b/assets/lato-light.kttf
index 15e547e1171fc26bd38cfd25279144307481d46c..a4088c10216b5bf7172ba407895f446d1ca94598 100644
--- a/assets/lato-light.kttf
+++ b/assets/lato-light.kttf
@@ -1,5 +1,7 @@
 {
     "file": "lato-light.ttf",
     "char_range_start": "0x20",
-    "char_range_end": "0x7f"
+    "char_range_end": "0x7f",
+    "offset_x": 0.0,
+    "offset_y": 25.0,
 }
\ No newline at end of file
diff --git a/assets/roboto.kttf b/assets/roboto.kttf
index 9c7d59c6ed7f1c15a4d89b38b98ae946f470213b..d6411ede9bc5e2d8aa598405121d96b8028640a7 100644
--- a/assets/roboto.kttf
+++ b/assets/roboto.kttf
@@ -1,5 +1,7 @@
 {
     "file": "roboto.ttf",
     "char_range_start": "0x20",
-    "char_range_end": "0x7f"
+    "char_range_end": "0x7f",
+    "offset_x": 0.0,
+    "offset_y": 25.0,
 }
\ No newline at end of file
diff --git a/examples/layout.rs b/examples/layout.rs
index 41e335a54a0255ba8db2998b4a4468d87c91f3a9..6fdc489262656d4c4e1dc796f472809824ce5572 100644
--- a/examples/layout.rs
+++ b/examples/layout.rs
@@ -128,7 +128,7 @@ fn startup(
                 </ElementBundle>
             </WindowBundle>
         </KayakAppBundle>
-    }
+    };
 
     commands.spawn(UICameraBundle::new(widget_context));
 }
diff --git a/kayak_font/assets/lato-light.kttf b/kayak_font/assets/lato-light.kttf
new file mode 100644
index 0000000000000000000000000000000000000000..a4088c10216b5bf7172ba407895f446d1ca94598
--- /dev/null
+++ b/kayak_font/assets/lato-light.kttf
@@ -0,0 +1,7 @@
+{
+    "file": "lato-light.ttf",
+    "char_range_start": "0x20",
+    "char_range_end": "0x7f",
+    "offset_x": 0.0,
+    "offset_y": 25.0,
+}
\ No newline at end of file
diff --git a/kayak_font/assets/lato-light.kttf-cached.png b/kayak_font/assets/lato-light.kttf-cached.png
new file mode 100644
index 0000000000000000000000000000000000000000..6163dc114490f069d785bef1b745bbca5ac7051d
Binary files /dev/null and b/kayak_font/assets/lato-light.kttf-cached.png differ
diff --git a/kayak_font/assets/lato-light.ttf b/kayak_font/assets/lato-light.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..dfa72ce808fbb783042da88ce1bae5d9adb54fb6
Binary files /dev/null and b/kayak_font/assets/lato-light.ttf differ
diff --git a/kayak_font/assets/roboto.kttf b/kayak_font/assets/roboto.kttf
index 9c7d59c6ed7f1c15a4d89b38b98ae946f470213b..d6411ede9bc5e2d8aa598405121d96b8028640a7 100644
--- a/kayak_font/assets/roboto.kttf
+++ b/kayak_font/assets/roboto.kttf
@@ -1,5 +1,7 @@
 {
     "file": "roboto.ttf",
     "char_range_start": "0x20",
-    "char_range_end": "0x7f"
+    "char_range_end": "0x7f",
+    "offset_x": 0.0,
+    "offset_y": 25.0,
 }
\ No newline at end of file
diff --git a/kayak_font/examples/renderer/shader.wgsl b/kayak_font/examples/renderer/shader.wgsl
index 4bfdf8f701d0c5f46187aefc63043144488e487a..36af3a3045da9d17a6dfe361f221bdf6d84517c4 100644
--- a/kayak_font/examples/renderer/shader.wgsl
+++ b/kayak_font/examples/renderer/shader.wgsl
@@ -41,7 +41,7 @@ var font_sampler: sampler;
 
 @fragment
 fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
-    var px_range = 2.5;
+    var px_range = 4.5;
     var tex_dimensions = textureDimensions(font_texture);
     var msdf_unit = vec2<f32>(px_range, px_range) / vec2<f32>(f32(tex_dimensions.x), f32(tex_dimensions.y));
     var x = textureSample(font_texture, font_sampler, vec2<f32>(in.uv.x, in.uv.y), i32(in.uv.z));
diff --git a/kayak_font/src/ttf/loader.rs b/kayak_font/src/ttf/loader.rs
index 2c39c09b89517636e9412b1e22e1ddf380e49d21..1b3664375300bf11c9be2e881ae478c731ed24bb 100644
--- a/kayak_font/src/ttf/loader.rs
+++ b/kayak_font/src/ttf/loader.rs
@@ -21,6 +21,8 @@ pub struct KTTF {
     file: String,
     char_range_start: String,
     char_range_end: String,
+    offset_x: Option<f32>,
+    offset_y: Option<f32>,
 }
 
 impl AssetLoader for TTFLoader {
@@ -43,7 +45,7 @@ impl AssetLoader for TTFLoader {
                 u32::from_str_radix(kttf.char_range_start.trim_start_matches("0x"), 16)?;
             let char_range_end =
                 u32::from_str_radix(kttf.char_range_end.trim_start_matches("0x"), 16)?;
-            let font_bytes = load_context.read_asset_bytes(kttf.file).await?;
+            let font_bytes = load_context.read_asset_bytes(kttf.file.clone()).await?;
 
             let mut cache_path = std::path::PathBuf::from(load_context.path());
             let file_name = load_context
@@ -85,6 +87,8 @@ impl AssetLoader for TTFLoader {
                 }
             }
 
+            let loaded_file = &kttf;
+
             for char_u in font_range {
                 let c = char::from_u32(char_u).unwrap();
                 let glyph_id = *char_to_glyph.get(&c).unwrap();
@@ -108,11 +112,17 @@ impl AssetLoader for TTFLoader {
                 // let (left, bottom, right, top) = shape.get_bounds();
 
                 let scale = Vector2::new(1.0, 1.0);
-                let px_range = 2.0;
+                let px_range = 2.5;
                 let range = px_range / scale.x.min(scale.y);
 
-                let (translation, plane) =
-                    calculate_plane(&mut shape, pixel_scale as f32, 1.0, px_range as f32, 1.0);
+                let (translation, plane) = calculate_plane(
+                    loaded_file,
+                    &mut shape,
+                    pixel_scale as f32,
+                    1.0,
+                    px_range as f32,
+                    1.0,
+                );
                 let advance = face.glyph_hor_advance(glyph_id).unwrap_or(0) as f32 / size_x as f32;
                 let c = *glyph_to_char.get(&glyph_id).unwrap();
                 glyphs.push(Glyph {
@@ -208,7 +218,7 @@ impl AssetLoader for TTFLoader {
                 },
                 bevy::render::render_resource::TextureDimension::D2,
                 image_bytes,
-                TextureFormat::Rgba8UnormSrgb,
+                TextureFormat::Rgba8Unorm,
             );
             image.reinterpret_stacked_2d_as_array(char_count);
             let image_handle =
@@ -227,6 +237,7 @@ impl AssetLoader for TTFLoader {
 }
 
 fn calculate_plane(
+    loaded_file: &KTTF,
     shape: &mut Shape,
     geometry_scale: f32,
     scale: f32,
@@ -292,13 +303,20 @@ fn calculate_plane(
     //     t = geometry_scale as f64 * (-translation_y + (h as f64 - 0.5) * inv_box_scale);
     // }
 
+    let left = loaded_file
+        .offset_x
+        .unwrap_or_default();
+    let top = loaded_file
+        .offset_y
+        .unwrap_or_default();
+
     (
         Vector2::new(translation_x, translation_y) * geometry_scale as f64,
         Rect {
-            left: 0.0,                  // l as f32,
-            bottom: 0.0,                // b as f32,
-            right: 0.0,                 // r as f32,
-            top: 24.0 * geometry_scale, // t as f32,
+            left: left * geometry_scale,        // l as f32,
+            bottom: 0.0, // b as f32,
+            right: 0.0,  // r as f32,
+            top: top * geometry_scale,         //0.0, // t as f32,
         },
     )
 }
diff --git a/src/render/texture_atlas/extract.rs b/src/render/texture_atlas/extract.rs
index 3e343fec29efb825f68afdd160acb381c25d061a..24f7c8d876abc73e5936e5d800e1ea2d8fc4b667 100644
--- a/src/render/texture_atlas/extract.rs
+++ b/src/render/texture_atlas/extract.rs
@@ -13,7 +13,7 @@ pub fn extract_texture_atlas(
     camera_entity: Entity,
     render_primitive: &RenderPrimitive,
     images: &Res<Assets<Image>>,
-    dpi: f32,
+    _dpi: f32,
 ) -> Vec<ExtractQuadBundle> {
     let mut extracted_quads = Vec::new();
 
diff --git a/src/render/unified/shader.wgsl b/src/render/unified/shader.wgsl
index d2308ad37247e4fa0d580f7414a976c36d5825b9..cc6061d4ceb11fffbbac17adbff3e94f22de3a0b 100644
--- a/src/render/unified/shader.wgsl
+++ b/src/render/unified/shader.wgsl
@@ -70,6 +70,10 @@ fn sample_sdf(coords: vec2<f32>, arr: i32, scale: f32) -> f32 {
     return clamp((median3(sample.rgb) - 0.5) * scale + 0.5, 0., 1.);
 }
 
+fn range_curve(font_size: f32) -> f32 {
+    return (8.528 - 9.428 * font_size + 3.428 * pow(font_size, 2.0)) + 1.0;
+}
+
 @fragment
 fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
     if quad_type.t == 0 {
@@ -86,7 +90,9 @@ fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
         return vec4<f32>(in.color.rgb, rect_dist * in.color.a);
     }
     if quad_type.t == 1 {
-        var px_range = 2.5;
+        // var px_range = 4.5;
+        let font_size = min(max(in.size.y, 0.0), 32.0) / 32.0;
+        var px_range = range_curve(font_size);
         var tex_dimensions = textureDimensions(font_texture);
         var msdf_unit = vec2(px_range, px_range) / vec2(f32(tex_dimensions.x), f32(tex_dimensions.y));
         let subpixel_width = fwidth(in.uv.x) / 3.;
@@ -100,13 +106,13 @@ fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
         return vec4(red * in.color.r, green * in.color.g, blue * in.color.b, alpha);
     }
     if quad_type.t == 2 {
-        var px_range = 2.5;
+        // var px_range = 5.5;
+        let font_size = min(max(in.size.y, 0.0), 32.0) / 32.0;
+        var px_range = range_curve(font_size);
         var tex_dimensions = textureDimensions(font_texture);
         var msdf_unit = vec2(px_range, px_range) / vec2(f32(tex_dimensions.x), f32(tex_dimensions.y));
         let scale = dot(msdf_unit, 0.5 / fwidth(in.uv.xy));
-
         let alpha = sample_sdf(vec2(in.uv.x, 1. - in.uv.y), i32(in.uv.z), scale);
-
         return vec4(in.color.rgb, alpha);
     }
     if quad_type.t == 3 {