suzuri 0.2.1

Text rendering library
Documentation
# Suzuri

Suzuri is a text rendering library written in Rust.
Use this crate to layout and render text with consistent results.

This crate prioritizes consistency and reproducibility within a two-pass layout data flow.
It ensures that layout results remain stable even when constraints change, provided there is enough
whitespace (e.g., preventing unstable line breaks when layout width is reduced).

## Features

*   **Flexible Backend**: Supports both CPU-based rendering and GPU acceleration (via [wgpu]https://wgpu.rs/).
*   **Robust Layout**: Handles text wrapping, alignment, and multi-font shaping with predictable results.
*   **Font Management**: Easy loading of system fonts and custom font files via [fontdb]https://github.com/RazrFalcon/fontdb.
*   **Thread Safety**: Designed with internal locking for safe concurrent use.

## Overview

The library is composed of the following main functionalities:

*   **[`font_storage::FontStorage`]**: Manages font loading and caching. It handles system fonts and custom font data.
*   **Text Representation**: Defined by [`text::TextData`] and [`text::TextElement`]. These structures hold the content and styling information (font, size, color, etc.) for text.
*   **[`text::TextLayout`]**: The engine that calculates glyph positions, handling wrapping, alignment, and other layout properties based on the configuration.
*   **Renderers**:
    *   **[`renderer::CpuRenderer`]**: Renders text into a pixel buffer on the CPU.
    *   **[`renderer::GpuRenderer`]**: A graphics-API-independent text renderer. It manages texture atlases and glyph quads, allowing implementation on any graphics backend (e.g., OpenGL, Vulkan, DirectX).
    *   **[`renderer::WgpuRenderer`]**: A concrete implementation built on top of `GpuRenderer` using the [wgpu]https://wgpu.rs/ graphics API.

The [`FontSystem`] acts as the central hub, coordinating these components to provide a unified API.

## How to Read the Documentation

To get started with Suzuri, we recommend reading the documentation in the following order:

1.  **[`FontSystem`]**: The entry point of the library. Learn how to initialize the system.
2.  **[`fontdb`]**: Understanding `fontdb` is essential for querying fonts (by family, weight, style) to obtain the Font ID needed for text elements.
3.  **[`text::TextData`] & [`text::TextElement`]**: Learn how to create text content with styles and custom data.
4.  **[`text::TextLayout`]**: Understand how the text is measured and arranged.
5.  **Renderers**: Finally, explore the specific renderer you intend to use (e.g., in [`renderer`] module) for integration details.

## Installation

Add the following to your `Cargo.toml`:

```toml
[dependencies]
suzuri = "0.2.0"
```

To use wgpu features, enable the `wgpu` feature:

```toml
[dependencies]
suzuri = { version = "0.2.0", features = ["wgpu"] }
```

## Usage

### 1. Initialize FontSystem

[`FontSystem`] is the entry point for Suzuri. It handles font loading, layout, and renderer management.

```rust
use suzuri::{FontSystem, fontdb::{self, Family, Query}};

let font_system = FontSystem::new();
font_system.load_system_fonts();

// Query a font
let font_id = font_system
    .query(&Query {
        families: &[Family::Name("Arial"), Family::SansSerif],
        weight: fontdb::Weight::NORMAL,
        stretch: fontdb::Stretch::Normal,
        style: fontdb::Style::Normal,
    })
    .map(|(id, _)| id);
    // .expect("Font not found"); // Handle error appropriately
```

### 2. Prepare Text Data

Define the content and style of the text you want to render.

```rust
# use suzuri::{FontSystem, fontdb};
# use suzuri::text::{TextData, TextElement};
# let font_system = FontSystem::new();
# let font_id = None; 
#
// Color type is user-definable
#[derive(Clone, Copy, Debug)]
struct MyColor { r: f32, g: f32, b: f32, a: f32 }

// For wgpu rendering, convert to [f32; 4] (Premultiplied Alpha)
impl From<MyColor> for [f32; 4] {
    fn from(c: MyColor) -> Self {
        [c.r * c.a, c.g * c.a, c.b * c.a, c.a]
    }
}

let mut data = TextData::new();
if let Some(id) = font_id {
    data.append(TextElement {
        content: "Hello, Suzuri!".to_string(),
        font_id: id,
        font_size: 32.0,
        user_data: MyColor { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
    });
}
```

### 3. Layout the Text

Configure layout settings with [`text::TextLayoutConfig`] and calculate the placement.

```rust
# use suzuri::{FontSystem, text::TextData};
use suzuri::text::{TextLayoutConfig, HorizontalAlign, VerticalAlign, WrapStyle};
# let font_system = FontSystem::new();
# let data = TextData::<u8>::new();

let config = TextLayoutConfig {
    max_width: Some(800.0),
    max_height: None,
    horizontal_align: HorizontalAlign::Left,
    vertical_align: VerticalAlign::Top,
    line_height_scale: 1.2,
    wrap_style: WrapStyle::WordWrap,
    ..Default::default()
};

let layout = font_system.layout_text(&data, &config);
```

### 4. Rendering

#### CPU Rendering

For detailed usage, please refer to the [`renderer::CpuRenderer`] documentation.

#### GPU Rendering (wgpu)

To render using wgpu, initialize the renderer with the device and queue, then draw within a render pass.

For detailed usage, please refer to the [`renderer::WgpuRenderer`] documentation.

## License

MIT OR Apache-2.0