latex-rust 1.0.1

Pure-Rust LaTeX math renderer. Parse to AST, TeX-faithful layout in zenith-float, emit SVG, PNG, or egui shapes. No JavaScript, no webview, no runtime.
Documentation
# LaTeX-Rust

[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE-APACHE)

Repository: <https://github.com/jscarr64/LaTeX-Rust>

Pure Rust LaTeX math renderer. No JavaScript. No webview. No runtime dependencies.

It parses LaTeX math into a typed AST, lays the AST out with a TeX-faithful box
model whose dimensions are [zenith-float](https://crates.io/crates/zenith-float)
`Dim` values (no hardware `f32`/`f64` in the layout path), and renders to SVG,
PNG (`features = ["png"]`), or egui shapes (`features = ["egui"]`).

## Features

- Parses LaTeX math to a typed AST
- TeX-faithful layout engine (Appendix G exact)
- SVG output — self-contained, scalable, no font embedding required
- PNG output (`features = ["png"]`) via tiny-skia
- egui integration (`features = ["egui"]`) for native desktop apps
- Full symbol coverage — Greek, AMS, arrows, operators, font styles
- Complete accent and decoration support
- Multiline environments — align, gather, multline, cases, array
- Color support — named, RGB, HTML, CMYK, gray, `\definecolor`
- 100% pure Rust — no C, no Python, no shell, no subprocesses
- MIT OR Apache-2.0

```
src/parser/     LaTeX → AST
src/layout/     AST → box model
src/font/       STIX Two Math metrics / TrueType loader
src/render/svg  box model → SVG
src/render/png  box model → PNG (`tiny-skia`, feature `png`)
src/render/egui box model → egui Shapes (feature `egui`)
golds/          gold tests (repository only)
benches/        parse / layout / render timings
```

This crate does not typeset documents. Text-mode LaTeX, TikZ, chemistry, and PDF
are out of scope and return `Err` — never a fake render.

## Quick start

```toml
[dependencies]
latex-rust = "1.0"
```

Until the crate is on crates.io:

```toml
[dependencies]
latex-rust = { git = "https://github.com/jscarr64/LaTeX-Rust" }
```

```rust
use latex_rust::{parse, layout, latex_to_svg, MathFont, MathStyle, SvgOptions};

let ast = parse(r"\frac{1}{2}").expect("parse");
let font = MathFont::stix_two_math().expect("STIX Two Math");
let boxed = layout(&ast, &font, MathStyle::Text).expect("layout");
assert!(!boxed.width.is_zero());

let svg = latex_to_svg(r"\frac{1}{2}", &font, &SvgOptions::new()).expect("svg");
assert!(svg.contains("<svg"));
```

Layout math uses the published [zenith-float](https://crates.io/crates/zenith-float)
**1.0** crate (`ExactNum` software floats). This crate depends on `zenith-float`
only — not on its inner kernel package.

MSRV is **1.76** (matches optional `egui` 0.28).

## Usage

### SVG

```rust
use latex_rust::{latex_to_svg, MathFont, SvgOptions};

let font = MathFont::stix_two_math().unwrap();
let svg = latex_to_svg(r"e^{i\pi}+1=0", &font, &SvgOptions::new()).unwrap();
```

### PNG

Enable with `features = ["png"]`. `tiny-skia` rasterizes the same `MathBox` tree
as the SVG backend. SIMD is selected at runtime:

- On x86_64 with AVX2 — tiny-skia runs at peak performance automatically
- On Apple Silicon — tiny-skia uses the ARM NEON path, also fast
- No user configuration needed
- No compile flags required
- Works correctly on every supported architecture

Without the feature, `latex_to_png` / `render_png` return `Err(Unsupported)`.

```rust
# #[cfg(feature = "png")]
# {
use latex_rust::{latex_to_png, MathFont, PngOptions};

let font = MathFont::stix_two_math().unwrap();
let png = latex_to_png(r"\frac{1}{2}", &font, &PngOptions::new()).unwrap();
assert!(png.starts_with(b"\x89PNG"));
# }
```

### egui

Enable with `features = ["egui"]`. Glyphs become `egui::Mesh`; rules and color
boxes become `Shape::Rect`. No SVG intermediate. Callers should keep the
returned `Vec<Shape>` if the same expression is painted every frame (cache hit).

```rust
# #[cfg(feature = "egui")]
# {
use latex_rust::{latex_to_shapes, EguiOptions, MathFont};

let font = MathFont::stix_two_math().unwrap();
let (shapes, rect) =
    latex_to_shapes(r"x^2", &font, &EguiOptions::new(), egui::Pos2::ZERO, 1.0).unwrap();
assert!(!shapes.is_empty());
let _ = rect;
# }
```

## Supported LaTeX

Math mode only. Command and environment coverage is the capability inventory in
[`documents/latex-rust-build-sheet.md`](documents/latex-rust-build-sheet.md)
and the catalog [`data/symbols.tsv`](data/symbols.tsv). Look up a command with
`latex_rust::lookup`. Missing glyphs and unknown commands are `Err`.

Color: `named_color` / `parse_color_spec`. Channel values use `Dim`. `spot` and
unknown names return `Err`. SVG, PNG, and egui all take `Color::to_rgba8()`.

## Performance

Times below are median-of-batch averages from `cargo bench --features png,egui`
on this machine (release, zenith-float `Dim` layout). Re-run the bench on your
hardware; the targets are the build-sheet gates.

| Operation | Target | Measured |
|---|---|---|
| Parse `\frac{1}{2}` | < 50µs | 1.8µs |
| Parse full display equation | < 200µs | 3.3µs |
| Layout `\frac{1}{2}` | < 100µs | 13µs |
| Layout full display equation | < 500µs | 47µs |
| SVG `\frac{1}{2}` | < 500µs | 232µs |
| SVG full display equation | < 1ms | 951µs |
| PNG 144 DPI | < 5ms | 142µs |
| PNG 300 DPI | < 15ms | 350µs |
| egui inline (cache miss) | < 2ms | 216µs |
| egui inline (cache hit) | < 0.1ms | 29µs |

KaTeX cold start in a browser is typically **200–400ms** (JS parse + layout +
font). This crate’s first `MathFont::stix_two_math()` plus an SVG of a short
expression is on the order of the layout+SVG rows above after the face is loaded
(embedded STIX Two Math, no network). There is no JS runtime to warm up.

## Fonts

The crate embeds **STIX Two Math** 2.13 (SIL OFL 1.1) and loads metrics through
`ttf-parser` using integer font units converted to `Dim`. Glyph outlines become
SVG `<path>` elements (and PNG/egui meshes when those features are on).

## License

MIT OR Apache-2.0. STIX Two Math remains under the SIL Open Font License 1.1.
See `NOTICE`.