# thorvg-rs

> **⚠️ Work in progress** — This crate is under active development and not yet ready for production use. APIs may change without notice.

Rust bindings for [ThorVG](https://github.com/thorvg/thorvg), a production-ready vector graphics engine supporting SVG, Lottie animations, shapes, text, gradients, effects, and more.

## Crates

| Crate | Description |
|-------|-------------|
| [`thorvg-sys`](thorvg-sys/) | Raw FFI bindings generated by bindgen |
| [`thorvg`](thorvg/) | Safe, idiomatic Rust wrapper |

## Quick Start

```rust
use thorvg::{Thorvg, ColorSpace};

let engine = Thorvg::init(0).unwrap();

let mut canvas = engine.sw_canvas(Default::default()).unwrap();
let mut buffer = vec![0u32; 800 * 600];
// SAFETY: `buffer` outlives `canvas`; not moved or reallocated until set_target is called again
unsafe {
    canvas.set_target(&mut buffer, 800, 800, 600, ColorSpace::ABGR8888).unwrap();
}

let mut shape = engine.shape().unwrap();
shape.append_rect(thorvg::Rect::new(10.0, 10.0, 200.0, 150.0).corner_radius(10.0)).unwrap();
shape.set_fill_color(thorvg::Rgba::new(255, 0, 0, 255)).unwrap();

canvas.add(shape).unwrap();
canvas.draw(true).unwrap();
canvas.sync().unwrap();
// buffer now contains rendered pixels
```

## Features

### `thorvg` (safe wrapper)

| Feature | Default | Description |
|---------|---------|-------------|
| `std` | ✅ | Enables `std::path::Path`-taking wrappers (`Picture::load`, `Text::load_font`); implies `file-io` |
| `vendored` | ✅ | Build ThorVG from source via the `cc` crate |
| `lottie` | ✅ | Lottie animation loader |
| `svg` | ✅ | SVG loader |
| `png` | ✅ | Built-in PNG loader (lodepng, no system dep) |
| `fonts` | ✅ | SFNT / OTF / TTF font loaders |
| `expressions` | ✅ | Lottie expressions via JerryScript (~200 KB RAM) |
| `threads` | ✅ | Multi-threaded TaskScheduler (`std::thread`) |
| `file-io` | ✅ | Compiles ThorVG's filesystem I/O code path (without `std`, only the byte-slice-taking `load_data` / `load_from_str` variants are exposed) |

`vendored`, `lottie`, `svg`, `png`, `fonts`, `expressions`,
`threads`, and `file-io` are pass-throughs to the corresponding
`thorvg-sys` features.  `std` is wrapper-only — it enables
`thorvg-sys/file-io` plus the path-taking wrapper APIs.

### Desktop (default — everything enabled)

```toml
[dependencies]
thorvg = "0.3"
```

### Embedded / `no_std` (pick only what you need)

```toml
[dependencies]
thorvg = { version = "0.3", default-features = false, features = ["vendored", "lottie", "svg"] }
```

This gives you Lottie + SVG playback with no threads, no JerryScript,
no PNG/font loaders — suitable for microcontrollers with limited RAM.

## Cross-Compilation

ThorVG is compiled from C++ source using the [`cc`](https://crates.io/crates/cc) crate, which
picks up the correct cross-compiler from Cargo's target environment.
No meson or ninja required.

Tested targets:

| Target | Runtime | Notes |
|--------|---------|-------|
| `x86_64-unknown-linux-gnu` | system libc | Desktop default |
| `xtensa-esp32s3-espidf` | ESP-IDF | SDK provides libc |
| `xtensa-esp32-espidf` | ESP-IDF | SDK provides libc |
| `riscv32imc-esp-espidf` | ESP-IDF | SDK provides libc |
| `riscv32imac-unknown-none-elf` | bare-metal | Vendored picolibc — see [`thorvg-sys/docs/bare_metal.md`](thorvg-sys/docs/bare_metal.md) |

On `target_os == "none"` targets, `thorvg-sys` vendors and compiles
[picolibc](https://github.com/picolibc/picolibc) as the libc; the
cross toolchain's `libstdc++` / `libgcc` / `libm` are still used.
Wired architectures today: `riscv32`, `riscv64`, `aarch64`, `x86`,
`x86_64`, `powerpc[64]`, `mips[64]`, `sparc[64]`, `m68k`, `msp430`.
See the [bare-metal docs](thorvg-sys/docs/bare_metal.md) for the
build pipeline, runtime stubs, and how to override them.

## API Coverage

157 of the 161 ThorVG C API functions are wrapped (~98%).  Unwrapped:
the four `tvg_paint_ref` / `tvg_paint_unref` / `tvg_paint_get_ref` /
`tvg_paint_get_parent` refcount-and-parent helpers (ownership is
already modelled in the Rust types).

- **Canvas** — `SwCanvas` (software, fully wired).  `GlCanvas` and
  `WgCanvas` type wrappers exist for API parity, but the vendored
  build strips the GPU engine — they are not yet runtime-usable
- **Paint** — opacity, visibility, transforms, clipping, masking, blending, hit-testing
- **Shape** — paths, rectangles, circles, fill, stroke, gradients, trim path
- **Gradient** — linear, radial, color stops, spread, transforms
- **Picture** — load SVG / PNG / Lottie / raw from file or memory
  (JPG and WebP loaders exist in the upstream tree but are not
  compiled by `thorvg-sys`)
- **Scene** — grouping, effects (blur, drop shadow, fill, tint, tritone)
- **Text** — font loading, styling, wrapping, metrics, outline
- **Animation** — frame control, segments, duration
- **LottieAnimation** — slots, markers, tweening, expressions, quality
- **Saver** — export paint/animation to file
- **Accessor** — scene tree traversal with callbacks

## `no_std` Support

Both crates are `no_std` compatible. The safe wrapper requires `alloc`.
File I/O APIs (`Picture::load`, `Text::load_font`, `Saver::save`) are
gated behind the `std` feature. All rendering, shapes, gradients,
scenes, and canvas operations work in `no_std`.

For `target_os == "none"` targets, `thorvg-sys` ships its own libc
(vendored picolibc) — see [`thorvg-sys/docs/bare_metal.md`](thorvg-sys/docs/bare_metal.md).

## Examples

```bash
cargo run --example shapes
cargo run --example stroke
cargo run --example gradient
cargo run --example scene
cargo run --example transforms
cargo run --example blending
cargo run --example opacity
cargo run --example clipping
cargo run --example masking
cargo run --example scene_effects
cargo run --example paths
cargo run --example picture_svg
cargo run --example paint_order
cargo run --example render_to_buffer
```

All examples output PNG files in the current directory.

## Building

ThorVG is vendored as a git submodule and compiled automatically via
the [`cc`](https://crates.io/crates/cc) crate.  You need a C++ compiler
(any `g++` or `clang++` will do) plus `libclang` for
[`bindgen`](https://rust-lang.github.io/rust-bindgen/requirements.html)
(typically packaged as `libclang-dev` / `clang-devel` / `llvm` on macOS).

```bash
git clone --recurse-submodules https://github.com/goyox86/thorvg-rs
cd thorvg-rs
cargo build
```

No meson, ninja, or pkg-config required for vendored builds.

## Development

Requires [just](https://github.com/casey/just) for task running:

```bash
just ci-quick    # fmt, clippy, test, no_std check
just ci          # full CI: above + AddressSanitizer + ThreadSanitizer
just test-asan   # run tests under AddressSanitizer
just examples    # run all 14 examples
just --list      # show all recipes
```

## Acknowledgments

This project provides Rust bindings to [ThorVG](https://github.com/thorvg/thorvg), created and maintained by the [ThorVG project](https://www.thorvg.org/) contributors. ThorVG is a [Linux Foundation](https://www.linuxfoundation.org/) project. All vector graphics rendering is performed by the ThorVG engine — this crate is a thin binding layer.

This project is not affiliated with, endorsed by, or sponsored by the ThorVG project or the Linux Foundation.

Special thanks to [Hermet Park](https://github.com/hermet) and all [ThorVG contributors](https://github.com/thorvg/thorvg/graphs/contributors) for building such an excellent, lightweight, and well-designed vector graphics engine with a clean C API that made these bindings possible.

## License

MIT — same as [ThorVG](https://github.com/thorvg/thorvg/blob/main/LICENSE).
