| Crates.io | skia-rs-safe |
| lib.rs | skia-rs-safe |
| version | 0.2.0 |
| created_at | 2026-01-02 23:07:20.02963+00 |
| updated_at | 2026-01-03 18:48:42.874283+00 |
| description | High-level safe Rust API for skia-rs - A pure Rust implementation of Skia |
| homepage | https://github.com/pegasusheavy/skia-rs |
| repository | https://github.com/pegasusheavy/skia-rs |
| max_upload_size | |
| id | 2019317 |
| size | 149,753 |
A 100% Rust implementation of the Skia 2D graphics library
Getting Started • Features • Examples • Documentation • Contributing
skia-rs is a pure Rust reimplementation of Google's Skia 2D graphics library. It aims to provide complete API compatibility with the original Skia while leveraging Rust's safety, performance, and ergonomics.
Add skia-rs-safe to your Cargo.toml:
[dependencies]
skia-rs-safe = "0.1"
Or use individual crates for more control:
[dependencies]
skia-rs-core = "0.1" # Core types: Point, Rect, Matrix, Color
skia-rs-path = "0.1" # Path geometry and operations
skia-rs-paint = "0.1" # Paint, shaders, filters
skia-rs-canvas = "0.1" # Canvas and surface
use skia_rs_canvas::Surface;
use skia_rs_core::{Color, Rect};
use skia_rs_paint::{Paint, Style};
fn main() {
// Create a 800x600 RGBA surface
let mut surface = Surface::new_raster_n32_premul(800, 600)
.expect("Failed to create surface");
// Get a canvas to draw on
let canvas = surface.canvas();
// Clear with a dark background
canvas.clear(Color::from_rgb(18, 18, 26));
// Create a paint with an orange color
let mut paint = Paint::new();
paint.set_anti_alias(true);
paint.set_color(Color::from_rgb(255, 107, 53));
paint.set_style(Style::Fill);
// Draw a rounded rectangle
let rect = Rect::from_xywh(100.0, 100.0, 600.0, 400.0);
canvas.draw_round_rect(&rect, 20.0, 20.0, &paint);
// Draw some text
paint.set_color(Color::WHITE);
canvas.draw_string("Hello, skia-rs!", 150.0, 320.0, &paint);
}
skia-rs/
├── skia-rs-core # Foundation: types, geometry, color
├── skia-rs-path # Path geometry and operations
├── skia-rs-paint # Paint, shaders, effects
├── skia-rs-canvas # Canvas, surface, recording
├── skia-rs-text # Text layout and rendering
├── skia-rs-codec # Image encoding/decoding
├── skia-rs-gpu # GPU backends
├── skia-rs-svg # SVG parsing and rendering
├── skia-rs-pdf # PDF generation
├── skia-rs-ffi # C FFI bindings
└── skia-rs-safe # High-level unified API
The skia-rs-safe crate supports feature flags:
| Feature | Default | Description |
|---|---|---|
codec |
✅ | Image encoding/decoding (PNG, JPEG, GIF, WebP) |
svg |
✅ | SVG parsing and rendering |
pdf |
❌ | PDF document generation |
gpu |
❌ | GPU backends (wgpu) |
# All features
skia-rs-safe = { version = "0.1", features = ["codec", "svg", "pdf", "gpu"] }
# Minimal (no codecs or extras)
skia-rs-safe = { version = "0.1", default-features = false }
skia-rs includes a comprehensive benchmark suite. Key performance highlights:
| Operation | Performance |
|---|---|
| Rectangle fill (1000×1000) | 224 ns |
| Clear (1000×1000) | 189 ns |
| Anti-aliased line | 502 ns |
| Path boolean union | 12.4 µs |
| SVG path parsing | 890 ns |
Run benchmarks locally:
cargo bench -p skia-rs-bench
use skia_rs_canvas::Surface;
use skia_rs_core::{Color, Rect, Point};
use skia_rs_paint::{Paint, Style};
use skia_rs_path::PathBuilder;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut surface = Surface::new_raster_n32_premul(400, 400)?;
let canvas = surface.canvas();
canvas.clear(Color::WHITE);
// Draw a circle
let mut paint = Paint::new();
paint.set_color(Color::from_rgb(66, 133, 244));
paint.set_anti_alias(true);
canvas.draw_circle(Point::new(200.0, 200.0), 80.0, &paint);
// Draw a custom path
let path = PathBuilder::new()
.move_to(100.0, 300.0)
.quad_to(200.0, 250.0, 300.0, 300.0)
.build();
paint.set_color(Color::from_rgb(234, 67, 53));
paint.set_style(Style::Stroke);
paint.set_stroke_width(4.0);
canvas.draw_path(&path, &paint);
Ok(())
}
use skia_rs_paint::{Paint, LinearGradient, TileMode};
use skia_rs_core::{Point, Color4f};
let gradient = LinearGradient::new(
Point::new(0.0, 0.0),
Point::new(400.0, 0.0),
&[Color4f::RED, Color4f::BLUE],
None,
TileMode::Clamp,
);
let mut paint = Paint::new();
paint.set_shader(gradient);
canvas.draw_rect(&rect, &paint);
use skia_rs_codec::{Image, ImageFormat};
// Load an image
let image = Image::from_file("input.png")?;
// Draw it
canvas.draw_image(&image, 0.0, 0.0, None);
// Save to file
surface.save_png("output.png")?;
skia-rs provides C bindings for use from other languages:
#include "skia-rs.h"
sk_surface_t* surface = sk_surface_new_raster_n32_premul(800, 600);
sk_canvas_t* canvas = sk_surface_get_canvas(surface);
sk_paint_t* paint = sk_paint_new();
sk_paint_set_color(paint, 0xFFFF6B35);
sk_paint_set_antialias(paint, true);
sk_rect_t rect = { 100, 100, 700, 500 };
sk_canvas_draw_rect(canvas, &rect, paint);
sk_paint_delete(paint);
sk_surface_delete(surface);
Build the FFI library:
cargo build -p skia-rs-ffi --release
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
# Clone the repository
git clone https://github.com/pegasusheavy/skia-rs.git
cd skia-rs
# Build all crates
cargo build --workspace
# Run tests
cargo test --workspace
# Run benchmarks
cargo bench -p skia-rs-bench
# Run fuzzing (requires nightly)
cd fuzz && cargo +nightly fuzz run fuzz_path
See TODO.md for the complete development roadmap.
v0.1.0 (Current):
v0.2.0 (Planned):
Licensed under either of:
at your option.