# Klyff MSDF generation
<img src="https://img.shields.io/badge/min%20rust-1.91-green.svg" alt="Minimum Rust Version">
<a href="https://docs.rs/klyff_msdf"><img src="https://docs.rs/klyff_msdf/badge.svg" alt="docs.rs"></a>
<a href="https://crates.io/crates/klyff_msdf"><img src="https://img.shields.io/crates/v/klyff_msdf.svg?label=klyff_msdf" alt="crates.io"></a>
klyff_msdf is a MSDF generation library. It supports klyff, a text rendering library designed for games with high customization needs.
MSDF (Multi-channel Signed Distance Field) is a technique for text rendering, originally made by Chlumsky at [msdfgen](https://github.com/Chlumsky/msdfgen). It supports infinite scaling while still retaining sharp corners (as opposed to SDF).
MSDF generation is reimplemented in 100% pure Rust, instead of binding to the original [msdfgen](https://github.com/Chlumsky/msdfgen) C++ library.
See also: [klyff](https://crates.io/crates/klyff), a text rendering library based on this crate.
## Features
- **GPU generation** - Glyphs can be generated on the gpu using [wgpu](https://crates.io/crates/wgpu), gated behind [`wgpu`] feature flag.
- **Trait for other font reader** - Outline providers are abstracted behind a trait, allowing you to use your own font reader or any other file format. Interops with [skrifa](https://crates.io/crates/skrifa) by default.
- **Pure rust** - No C/C++ dependencies.
Please note that GPU generation is currently recommended, as the CPU path is quite slow (O(n) lookup of nearest segment per pixel).
## Quick Start
CPU generation:
```rust
//! use klyff_msdf::{AtlasRegionSize, MsdfGenerator, MsdfPixelFormat, SkrifaOutlineProvider};
//! use klyff_msdf::skrifa::{FontRef, GlyphId};
//!
//! let mut generator = MsdfGenerator::new();
//! let mut outline = generator
//! .read_glyph(&SkrifaOutlineProvider::new(font, glyph_id))
//! .expect("glyph is msdf-compatible");
//!
//! let size = AtlasRegionSize {
//! inner_width: 32,
//! inner_height: 32,
//! padding_x: 4,
//! padding_y: 4,
//! };
//!
//! // RGB MSDF, packed bytes suitable for writing to an image.
//! let _msdf: &[u8] = outline.generate_msdf(size, MsdfPixelFormat::PackedRgb8);
//! // Or the full MTSDF (RGBA), e.g. for uploading to a GPU texture.
//! let _mtsdf: &[u8] = outline.generate_mtsdf(size);
```
GPU generation:
```rust
//! use klyff_msdf::{GpuAtlasRegion, MsdfGenerator, MtsdfGpuWriter, SkrifaOutlineProvider};
//! use klyff_msdf::skrifa::{FontRef, GlyphId};
//!
//! fn gen_gpu(
//! device: &wgpu::Device,
//! queue: &wgpu::Queue,
//! atlas: &wgpu::Texture,
//! writer: &mut MtsdfGpuWriter,
//! generator: &mut MsdfGenerator,
//! font: FontRef<'_>,
//! glyph_ids: &[GlyphId],
//! ) {
//! // Queue multiple glyphs
//! for glyph_id in glyph_ids {
//! let outline = generator
//! .read_glyph(&SkrifaOutlineProvider::new(font.clone(), *glyph_id))
//! .expect("glyph is msdf-compatible");
//!
//! let region = GpuAtlasRegion {
//! layer: 0,
//! min_x: 0,
//! min_y: 0,
//! width: 40,
//! height: 40,
//! padding_x: 4,
//! padding_y: 4,
//! };
//! writer.add_glyph(outline, region);
//! }
//!
//! // Then flush them all in a single set of render passes:
//! let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
//! writer.write_glyphs(device, queue, &mut encoder, atlas);
//! queue.submit(std::iter::once(encoder.finish()));
//! }
```
## License
All source code is licensed under the MIT License.