Zig bindings for the famous Skia 2D Graphics Library.
This repository provides Zig bindings to the Skia C API. It builds Skia for multiple platforms and exposes the raw C headers to be used directly in Zig projects. No wrappers are provided—this is a low-level binding to the C layer only.
This repository is using the Skia fork from the Mono project, as they actively maintain a C wrapper for Skia (which is C++ only). We need C wrappers to bridge to Zig.
- Pre-built Skia binaries
- Exposes the raw Skia C API headers to Zig
- Easy to import and use directly from Zig code without any dependencies or extra build steps
Warning: This wrapper is in a very early stage and is not stable for production use. Also not all features and plaforms are implemented.
- Skia build for Windows x86_64
- Skia build for macOS x86_64
- Skia build for macOS Apple Silicon
- Skia build for Linux
- Import the
skia-zig
package into your project:
zig fetch --save https://github.com/basdp/skia-zig/releases/latest/download/skia-zig-package.zip
- Add the dependency to your
build.zig
file, somewhere belowb.addExecutable(...)
or whatever you are building:
const skia_dep = b.dependency("skia-zig", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("skia-zig", skia_dep.module("skia-zig"));
- You can now import
skia-zig
in your Zig code:
const skia = @import("skia-zig");
pub fn main() !void {
const gr_glinterface = skia.gr_glinterface_create_native_interface();
defer skia.gr_glinterface_unref(gr_glinterface);
const gr_context = skia.gr_direct_context_make_gl(gr_glinterface) orelse return error.SkiaCreateContextFailed;
defer skia.gr_direct_context_free_gpu_resources(gr_context);
const gl_info = skia.gr_gl_framebufferinfo_t{
.fFBOID = 0,
.fFormat = gl.RGBA8,
};
const samples: c_int = ... // get from GL or something
const stencil_bits: c_int = ... // get from GL or something
const backendRenderTarget = skia.gr_backendrendertarget_new_gl(640, 480, samples, stencil_bits, &gl_info) orelse return error.SkiaCreateRenderTargetFailed;
const color_type = skia.RGBA_8888_SK_COLORTYPE;
const colorspace = null;
const props = null;
const surface = skia.sk_surface_new_backend_render_target(@ptrCast(gr_context), backendRenderTarget, skia.BOTTOM_LEFT_GR_SURFACE_ORIGIN, color_type, colorspace, props) orelse return error.SkiaCreateSurfaceFailed;
defer skia.sk_surface_unref(surface);
const canvas = skia.sk_surface_get_canvas(surface) orelse unreachable;
while (/* app is running */) {
skia.sk_canvas_clear(canvas, 0xffffffff);
const fill = skia.sk_paint_new() orelse return error.SkiaCreatePaintFailed;
defer skia.sk_paint_delete(fill);
skia.sk_paint_set_color(fill, 0xff0000ff);
skia.sk_canvas_draw_paint(canvas, fill);
// Your Skia drawing here
skia.sk_canvas_flush(canvas);
}
}
Skia requires the msvc
ABI on Windows, so make sure you target that ABI. There are two possible
options to do so (only one of these is necessary):
-
Set the target from the command line while building:
zig build -Dtarget=x86_64-windows-msvc
-
Or better yet; replace the
const target = ...
line in yourbuild.zig
file:const target = b.standardTargetOptions(.{ .default_target = .{ .abi = if (b.graph.host.result.os.tag == .windows) .msvc else null, } });