# ktx-font A KTX2 format containing a font atlas texture, enriched with: - [kb-text-shape](https://hackage.haskell.org/package/kb-text-shape) font shaping data. - [msdf-astlas](https://hackage.haskell.org/package/msdf-astlas) compacted atlas. The package also has a module to run the shaping using stacks of those font bundles. ## The pipeline Typically you'd just use your rendering engine's utilities to do this. To implement one, you have to address the three points in the font lifecycle: ## Preparing the font bundle This part is the slowest one, as it takes care to distill and optimize the data for faster use later. 1. Generate an atlas with [msdf-atlas-gen](https://github.com/Chlumsky/msdf-atlas-gen) 2. [Transcode](https://gitlab.com/dpwiz/msdf-atlas/-/blob/main/test/regenerate.sh) into KTX file. 3. Preprocess and inject the extras as texture attributes. ## Loading Since all the data are already preprocessed you only have to move it to the appropriate places on CPU/GPU. For each font file: * Load the texture like the usual (with [ktx-codec](https://hackage.haskell.org/package/ktx-codec)). * Load font and atlas data from the same file/bytestring. For each combination of fonts (font stack: * Create a shaping context from a bunch of loaded fonts. ## Using 1. Run `Codec.Ktx2.Font.Shaping.shape` on your text. 2. Iterate over the result and convert the UV and world boxes to the data you use for rendering. * Since the shaping library does the font picking for you, you may have to look up the associated font data from the context, like texture id. NB: Due to font format and design shenanigans you have to use a sane "font size" metric that is shared for all the fonts in the stack. Typically that would be "cap height", and `msdf-atlas` takes care of converting "em" units into that. For more details on the problem see: - https://tonsky.me/blog/font-size/ - https://tonsky.me/blog/centering/ ## Demo The repo has a demo of using the shaping results in a Gloss (Brillo) context. ![sorry for the swearing, i was that mad making all this](./demo/screenshot.png) - Green line: baseline, on which every font sits. - Blue line: capital letter height, which is used for alignment. Every font rendered to have this one equal. - Cyan circles: innermost (tiny) - cursor position. Then, "font size", then "line size". - Red box: the bounding box for all glyph box. - Yellow line: the initial cursor position (at 0,0) shifted to match the aligned box. The glyphs have black boxes because the atlas is transcoded as having the single channel swizzled as `rrr1`. This allows to see the glyph boxes against the grey background. The `msdf-atlas-gen` is typically used to produce distance fields, but Gloss can't render them.