diff options
| -rw-r--r-- | src/main.zig | 50 | ||||
| -rw-r--r-- | src/pangocairo.zig | 203 | 
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;      };  }; | 
