# Klyff MSDF generation

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.

## 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.
