aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-09-14 23:58:53 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2024-09-18 00:07:35 +0300
commitb3996a9109a32eb83f877ba7cd1b1271c5cbe975 (patch)
tree79a3bc45f54ba8b4eac4254f926cb84f62a9dd45
parentb7cded32c304b1fb1b383267277814fdce2199ac (diff)
downloadzigway-b3996a9109a32eb83f877ba7cd1b1271c5cbe975.tar.gz
zigway-b3996a9109a32eb83f877ba7cd1b1271c5cbe975.zip
improve pango and cairo bindings
-rw-r--r--src/main.zig50
-rw-r--r--src/pangocairo.zig203
2 files changed, 141 insertions, 112 deletions
diff --git a/src/main.zig b/src/main.zig
index 436e14d..ebf2ac6 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -27,7 +27,9 @@ const WindowBuffer = struct {
/// Backing data slice from memory mapping for this buffer
map: []u8,
/// Cairo surface for painting with cairo
- c_surface: cairo.Surface,
+ cr_surface: *cairo.Surface,
+ /// Cairo context
+ cr_ctx: *cairo.Context,
/// Are we being read by the compositor right now?
busy: bool = false,
};
@@ -48,7 +50,7 @@ pub const Window = struct {
/// Memory mapped for both buffers
buffers_map: []align(mem.page_size) u8 = undefined,
/// Pango font description for rendering our text
- font: pango.FontDescription,
+ font_dsc: *pango.FontDescription,
/// This window's title
title: [*:0]const u8,
/// Width in pixels
@@ -74,15 +76,15 @@ pub const Window = struct {
.allocator = allocator,
.wl_surface = try compositor.createSurface(),
.title = title,
- // .font = try pango.FontDescription.fromString("monospace 24"),
- .font = try pango.FontDescription.create(),
+ // .font_dsc = try pango.FontDescription.fromString("monospace 24"),
+ .font_dsc = try pango.FontDescription.create(),
};
win.xdg_surface = try wm_base.getXdgSurface(win.wl_surface);
win.xdg_toplevel = try win.xdg_surface.getToplevel();
- win.font.setFamily("monospace");
- win.font.setWeight(600);
- win.font.setSizePt(18);
+ win.font_dsc.setFamily("monospace");
+ win.font_dsc.setWeight(600);
+ win.font_dsc.setSizePt(18);
try win.allocBuffers();
@@ -102,7 +104,7 @@ pub const Window = struct {
/// Destroy this window and all its associated resources
pub fn destroy(win: *Window) void {
win.destroyBuffers();
- win.font.destroy();
+ win.font_dsc.destroy();
win.xdg_toplevel.destroy();
win.xdg_surface.destroy();
win.wl_surface.destroy();
@@ -111,8 +113,8 @@ pub const Window = struct {
/// Allocate new buffers for this window
fn allocBuffers(win: *Window) !void {
- const c_format = cairo.Format.argb32;
- const stride = cairo.Surface.formatStrideForWidth(c_format, win.width);
+ const cr_format = cairo.Format.argb32;
+ const stride = cr_format.strideForWidth(win.width);
const buffer_size = stride * win.height;
const total_size = buffer_size * 2; // we need two buffers
@@ -142,23 +144,25 @@ pub const Window = struct {
const bsize: usize = @intCast(buffer_size);
buffer.busy = false;
buffer.map = win.buffers_map[bsize *% i .. bsize *% (i + 1)];
- buffer.c_surface = try cairo.Surface.createImageForData(
+ buffer.cr_surface = try cairo.Surface.createImageForData(
buffer.map,
- c_format,
+ cr_format,
win.width,
win.height,
stride,
);
+ buffer.cr_ctx = try cairo.Context.create(buffer.cr_surface);
buffer.wl_buffer.setListener(*WindowBuffer, bufferListener, buffer);
}
}
/// Destroy this window's buffers
fn destroyBuffers(win: *Window) void {
- win.buffers[0].c_surface.destroy();
- win.buffers[1].c_surface.destroy();
- win.buffers[0].wl_buffer.destroy();
- win.buffers[1].wl_buffer.destroy();
+ inline for (&win.buffers) |*buffer| {
+ buffer.cr_ctx.destroy();
+ buffer.cr_surface.destroy();
+ buffer.wl_buffer.destroy();
+ }
posix.munmap(win.buffers_map);
}
@@ -190,14 +194,14 @@ pub const Window = struct {
}
}
- const layout = try pango.Layout.createForCairo(&buffer.c_surface);
+ const layout = try pango.Layout.createForCairo(buffer.cr_ctx);
defer layout.unref();
- buffer.c_surface.setSourceRgba(1, 1, 1, 1);
+ buffer.cr_ctx.setSourceRgba(1, 1, 1, 1);
- layout.setFont(win.font);
+ layout.setFontDescription(win.font_dsc);
layout.setText("Hello, wayland!", -1);
- buffer.c_surface.moveTo(5, 5);
- layout.show(&buffer.c_surface);
+ buffer.cr_ctx.moveTo(5, 5);
+ buffer.cr_ctx.showPangoLayout(layout);
var fps_buf: [32]u8 = undefined;
const fps_output = std.fmt.bufPrintZ(
@@ -206,8 +210,8 @@ pub const Window = struct {
.{win.current_fps},
) catch unreachable;
layout.setText(fps_output, -1);
- buffer.c_surface.moveTo(5, 40);
- layout.show(&buffer.c_surface);
+ buffer.cr_ctx.moveTo(5, 40);
+ buffer.cr_ctx.showPangoLayout(layout);
buffer.busy = true;
return buffer.wl_buffer;
diff --git a/src/pangocairo.zig b/src/pangocairo.zig
index 3995ba7..24bbfd6 100644
--- a/src/pangocairo.zig
+++ b/src/pangocairo.zig
@@ -3,140 +3,165 @@ const c = @cImport({
});
pub const pango = struct {
- pub const Layout = struct {
- layout: *c.PangoLayout,
-
- pub fn createForCairo(s: *cairo.Surface) !Layout {
- const layout = c.pango_cairo_create_layout(
- s.cairo,
- ) orelse return error.PangoCairoError;
- return .{ .layout = layout };
- }
+ pub const scale = c.PANGO_SCALE;
- pub fn setFont(l: Layout, f: FontDescription) void {
- c.pango_layout_set_font_description(l.layout, f.font);
+ pub const Layout = opaque {
+ extern fn pango_cairo_create_layout(s: *cairo.Context) ?*Layout;
+ pub fn createForCairo(s: *cairo.Context) !*Layout {
+ return pango_cairo_create_layout(s) orelse return error.OutOfMemory;
}
- pub fn setFontFromString(l: Layout, font: [*:0]const u8) !void {
- const pfont = c.pango_font_description_from_string(
- font,
- ) orelse return error.BadFont;
- defer c.pango_font_description_free(pfont);
- c.pango_layout_set_font_description(l.layout, pfont);
- }
+ extern fn pango_layout_set_font_description(l: *Layout, f: *FontDescription) void;
+ pub const setFontDescription = pango_layout_set_font_description;
- pub fn setText(l: Layout, text: [*:0]const u8, len: i32) void {
- c.pango_layout_set_text(l.layout, text, len);
- }
-
- pub fn show(l: Layout, s: *cairo.Surface) void {
- c.pango_cairo_show_layout(s.cairo, l.layout);
- }
+ extern fn pango_layout_set_text(l: *Layout, text: [*:0]const u8, len: i32) void;
+ pub const setText = pango_layout_set_text;
- pub fn unref(l: Layout) void {
- c.g_object_unref(l.layout);
+ pub fn unref(l: *Layout) void {
+ c.g_object_unref(l);
}
};
- pub const FontDescription = struct {
- font: *c.PangoFontDescription,
-
- pub fn create() !FontDescription {
- const font = c.pango_font_description_new() orelse return error.PangoError;
- return .{ .font = font };
+ pub const FontDescription = opaque {
+ extern fn pango_font_description_new() ?*FontDescription;
+ pub fn create() !*FontDescription {
+ return pango_font_description_new() orelse return error.OutOfMemory;
}
- pub fn fromString(str: [*:0]const u8) !FontDescription {
- const font = c.pango_font_description_from_string(str) orelse return error.PangoError;
- return .{ .font= font };
+ extern fn pango_font_description_from_string(str: [*:0]const u8) ?*FontDescription;
+ pub fn fromString(str: [*:0]const u8) !*FontDescription {
+ return c.pango_font_description_from_string(str) orelse return error.OutOfMemory;
}
- pub fn setFamily(f: FontDescription, name: [*:0]const u8) void {
- c.pango_font_description_set_family(f.font, name);
- }
+ extern fn pango_font_description_set_family(
+ f: *FontDescription,
+ name: [*:0]const u8,
+ ) void;
+ pub const setFamily = pango_font_description_set_family;
- pub fn setWeight(f: FontDescription, weight: u32) void {
- c.pango_font_description_set_weight(f.font, weight);
- }
+ extern fn pango_font_description_set_weight(f: *FontDescription, weight: u32) void;
+ pub const setWeight = pango_font_description_set_weight;
- pub fn setSize(f: FontDescription, size: i32) void {
- c.pango_font_description_set_size(f.font, size);
- }
+ extern fn pango_font_description_set_size(f: *FontDescription, size: i32) void;
+ pub const setSize = pango_font_description_set_size;
- pub fn setSizePt(f: FontDescription, pt: i32) void {
- c.pango_font_description_set_size(f.font, pt * c.PANGO_SCALE);
+ pub fn setSizePt(f: *FontDescription, pt: i32) void {
+ f.setSize(pt * scale);
}
- pub fn destroy(f: FontDescription) void {
- c.pango_font_description_free(f.font);
- }
+ extern fn pango_font_description_free(f: *FontDescription) void;
+ pub const destroy = pango_font_description_free;
};
};
pub const cairo = struct {
+ pub const Error = error{
+ Unknown,
+ NullPtr,
+ NoMemory,
+ ReadError,
+ InvalidContent,
+ InvalidFormat,
+ InvalidVisual,
+ };
+ fn statusToError(status: c_int) Error!void {
+ switch (status) {
+ c.CAIRO_STATUS_SUCCESS => return,
+ c.CAIRO_STATUS_NULL_POINTER => return Error.NullPtr,
+ c.CAIRO_STATUS_NO_MEMORY => return Error.NoMemory,
+ c.CAIRO_STATUS_READ_ERROR => return Error.ReadError,
+ c.CAIRO_STATUS_INVALID_CONTENT => return Error.InvalidContent,
+ c.CAIRO_STATUS_INVALID_FORMAT => return Error.InvalidFormat,
+ c.CAIRO_STATUS_INVALID_VISUAL => return Error.InvalidVisual,
+ else => return Error.Unknown,
+ }
+ }
+
pub const Format = enum(c_int) {
invalid = -1,
argb32,
rgb24,
+
+ extern fn cairo_format_stride_for_width(format: Format, width: i32) i32;
+ pub const strideForWidth = cairo_format_stride_for_width;
};
- pub const Surface = struct {
- cairo: *c.cairo_t,
- surface: *c.cairo_surface_t,
+ pub const Context = opaque {
+ extern fn cairo_status(ctx: ?*Context) c_int;
+ fn checkStatus(ctx: ?*Context) Error!void {
+ return statusToError(cairo_status(ctx));
+ }
+
+ extern fn cairo_create(surface: *Surface) ?*Context;
+ pub fn create(surface: *Surface) !*Context {
+ const ctx = cairo_create(surface);
+ try checkStatus(ctx);
+ return ctx orelse unreachable;
+ }
+
+ extern fn cairo_move_to(ctx: *Context, x: f64, y: f64) void;
+ pub const moveTo = cairo_move_to;
+
+ extern fn cairo_set_source_rgba(ctx: *Context, green: f64, blue: f64, red: f64, alpha: f64) void;
+ pub const setSourceRgba = cairo_set_source_rgba;
- pub fn formatStrideForWidth(format: Format, width: i32) i32 {
- return c.cairo_format_stride_for_width(@intFromEnum(format), width);
+ extern fn cairo_paint(ctx: *Context) void;
+ pub const paint = cairo_paint;
+
+ extern fn pango_cairo_show_layout(ctx: *Context, layout: *pango.Layout) void;
+ pub const showPangoLayout = pango_cairo_show_layout;
+
+ extern fn cairo_destroy(ctx: *Context) void;
+ pub const destroy = cairo_destroy;
+ };
+
+ pub const Surface = opaque {
+ extern fn cairo_surface_status(surface: ?*Surface) c_int;
+ fn checkStatus(surface: ?*Surface) Error!void {
+ return statusToError(cairo_surface_status(surface));
}
- pub fn createImage(format: Format, width: i32, height: i32) !Surface {
- const surface = c.cairo_image_surface_create(
- @intFromEnum(format),
+ extern fn cairo_image_surface_create(
+ format: Format,
+ width: i32,
+ height: i32,
+ ) ?*Surface;
+ pub fn createImage(format: Format, width: i32, height: i32) Error!*Surface {
+ const surface = cairo_image_surface_create(
+ format,
width,
height,
- ) orelse return error.CairoError;
- const cr = c.cairo_create(surface) orelse return error.CairoError;
- return .{ .cairo = cr, .surface = surface };
+ );
+ try checkStatus(surface);
+ return surface orelse unreachable;
}
+ extern fn cairo_image_surface_create_for_data(
+ data: [*c]u8,
+ format: Format,
+ width: i32,
+ height: i32,
+ stride: i32,
+ ) ?*Surface;
pub fn createImageForData(
data: []u8,
format: Format,
width: i32,
height: i32,
stride: i32,
- ) !Surface {
- const surface = c.cairo_image_surface_create_for_data(
+ ) Error!*Surface {
+ const s = cairo_image_surface_create_for_data(
data.ptr,
- @intFromEnum(format),
+ format,
width,
height,
stride,
- ) orelse return error.CairoError;
- const cr = c.cairo_create(surface) orelse return error.CairoError;
- return .{ .cairo = cr, .surface = surface };
+ );
+ try checkStatus(s);
+ return s orelse unreachable;
}
- pub fn moveTo(s: Surface, x: f64, y: f64) void {
- c.cairo_move_to(s.cairo, x, y);
- }
-
- pub fn setSourceRgba(
- s: Surface,
- red: f64,
- green: f64,
- blue: f64,
- alpha: f64,
- ) void {
- c.cairo_set_source_rgba(s.cairo, red, green, blue, alpha);
- }
-
- pub fn paint(s: Surface) void {
- c.cairo_paint(s.cairo);
- }
-
- pub fn destroy(s: Surface) void {
- c.cairo_destroy(s.cairo);
- c.cairo_surface_destroy(s.surface);
- }
+ extern fn cairo_surface_destroy(s: *Surface) void;
+ pub const destroy = cairo_surface_destroy;
};
};