diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@
 and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## 0.1.1.0 - 2026-02-26
+
+- Experimental support for capsHeight-enabled msdf-atlas-gen.
+
 ## 0.1.0.0 - 2025-12-30
 
 Initial release.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,14 @@
 # msdf-atlas
+![Hackage Version](https://img.shields.io/hackage/v/msdf-atlas)
 
-https://github.com/Chlumsky/msdf-atlas-gen
+Structures and aeson parsers for glyph atlases.
 
-The package alsoo provides a compacted representation of the atlas
-to use with text shaping packages like ktx-font / kb-text-shape.
+You may not want this when working with libfreetype/TTFs directly, but it can be useful for pre-rendered bitmap/sdf fonts.
+
+Compatible generators:
+- original: https://github.com/Chlumsky/msdf-atlas-gen
+- modded to support `capsHeight` metric: https://github.com/dpwiz/msdf-atlas-gen/tree/v1.13%2Bcapsheight
+  - A new field is `"sizeUnit": "capsHeight"`, indicating that `size` is not EMs and you don't have to convert.
+
+The package also provides a compacted representation of the atlas which boils down to a pair of storable vectors of boxes (and some metadata).
+This allows you to e.g. upload them to GPU and shuttle just glyph ids and styles when rendering.
diff --git a/msdf-atlas.cabal b/msdf-atlas.cabal
--- a/msdf-atlas.cabal
+++ b/msdf-atlas.cabal
@@ -1,16 +1,16 @@
 cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.38.1.
+-- This file has been generated from package.yaml by hpack version 0.39.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           msdf-atlas
-version:        0.1.0.0
+version:        0.1.1.0
 synopsis:       Types and parser for the MSDF atlas layout
 category:       Graphics
 author:         IC Rainbow
 maintainer:     aenor.realm@gmail.com
-copyright:      2025 IC Rainbow
+copyright:      2026 IC Rainbow
 license:        BSD-3-Clause
 license-file:   LICENSE
 build-type:     Simple
diff --git a/src/Graphics/MSDF/Atlas/Compact.hs b/src/Graphics/MSDF/Atlas/Compact.hs
--- a/src/Graphics/MSDF/Atlas/Compact.hs
+++ b/src/Graphics/MSDF/Atlas/Compact.hs
@@ -9,19 +9,22 @@
   ) where
 
 import Data.Aeson.Types (FromJSON(..), ToJSON(..))
-import Data.Vector.Storable qualified as Storable
+import Data.Maybe (fromMaybe)
 import Data.Vector.Generic qualified as Vector
+import Data.Vector.Storable qualified as Storable
 import Foreign (Storable(..))
 import GHC.Generics (Generic)
 
 import Graphics.MSDF.Atlas.Layout (AtlasType, Layout (..), Atlas (..))
-import qualified Graphics.MSDF.Atlas.Layout as Atlas
+import Graphics.MSDF.Atlas.Layout qualified as Atlas
 
 data Compact = Compact
   { _atlasSize :: (Int, Int) -- ^ Atlas image size in pixels
   , _size :: Float -- ^ Font size in pixels
   , _type :: AtlasType
   , _yOrigin :: Atlas.YOrigin
+  , _distanceLower :: Float -- ^ SDF range lower bound, in pixels
+  , _distanceRange :: Float -- ^ SDF range in pixels
   , glyphs :: Storable.Vector Box -- ^ Glyph boxes in the atlas UV space, normalized
   , planes :: Storable.Vector Box -- ^ Quad boxes in word space
   }
@@ -63,6 +66,8 @@
     , _size = size
     , _type = aType
     , _yOrigin = yOrigin
+    , _distanceLower = fromMaybe 0 $ (\r m -> m - 0.5 * r) <$> distanceRange <*> distanceRangeMiddle
+    , _distanceRange = fromMaybe 0 distanceRange
     , glyphs = Storable.convert as
     , planes = Storable.convert ps
     }
diff --git a/src/Graphics/MSDF/Atlas/Layout.hs b/src/Graphics/MSDF/Atlas/Layout.hs
--- a/src/Graphics/MSDF/Atlas/Layout.hs
+++ b/src/Graphics/MSDF/Atlas/Layout.hs
@@ -23,7 +23,8 @@
   { aType :: AtlasType
   , distanceRange :: Maybe Float
   , distanceRangeMiddle :: Maybe Float
-  , size :: Float -- ^ The `size` field represents the font size in pixels per em.
+  , size :: Float -- ^ The `size` field represents the font size in pixels per size unit (em or capsHeight).
+  , sizeUnit :: Maybe SizeUnit
   , width :: Int -- ^ Atlas image width in pixels
   , height :: Int -- ^ Atlas image height in pixels
   , yOrigin :: YOrigin
@@ -36,6 +37,7 @@
     distanceRange <- o .:? "distanceRange"
     distanceRangeMiddle <- o .:? "distanceRangeMiddle"
     size <- o .: "size"
+    sizeUnit <- o .:? "sizeUnit"
     width <- o .: "width"
     height <- o .: "height"
     yOrigin <- o .: "yOrigin"
@@ -96,9 +98,19 @@
     Top -> String "top"
     Bottom -> String "bottom"
 
-    -- - If there are multiple input fonts (`-and` parameter), the remaining data are grouped into `variants`, each representing an input font.
-    --
+data SizeUnit
+  = CapsHeight
+  deriving (Eq, Ord, Show, Enum, Bounded, Generic)
 
+instance FromJSON SizeUnit where
+  parseJSON = withText "sizeUnit" \case
+    "capsHeight" -> pure CapsHeight
+    huh -> fail $ "Unexpected sizeUnit: " <> show huh
+
+instance ToJSON SizeUnit where
+  toJSON = \case
+    CapsHeight -> String "capsHeight"
+
 -- | Useful font metric values retrieved from the font. All values are in em's.
 data Metrics = Metrics
   { emSize :: Float
@@ -107,6 +119,7 @@
   , descender :: Float
   , underlineY :: Float
   , underlineThickness :: Float
+  , capHeight :: Maybe Float
   }
   deriving (Eq, Ord, Show, Generic)
 
