~novakane/zig-fcft-example

cf26b658f23e4c2e7dd97dfeab699f3f56a2ecfa — Hugo Machet 2 months ago f72d704
code: Cleanup
2 files changed, 59 insertions(+), 65 deletions(-)

M src/Font.zig
M src/main.zig
M src/Font.zig => src/Font.zig +8 -9
@@ 16,18 16,17 @@

const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
const ArrayListUnmanaged = std.ArrayListUnmanaged;

const fcft = @import("fcft");

const ctx = &@import("main.zig").ctx;
pub const Font = @This();

fonts: *fcft.Font,

pub fn init(alloc: Allocator, fonts: []const u8) !Font {
    var list = try getFontsList(alloc, fonts);
    errdefer list.deinit(alloc);
pub fn init(fonts: []const u8) !Font {
    var list = try getFontsList(fonts);
    errdefer list.deinit(ctx.gpa);

    const fcft_fonts = try fcft.Font.fromName(list.items[0..], null);
    errdefer fcft_fonts.destroy();


@@ 40,13 39,13 @@ pub fn deinit(font: Font) void {
    font.fonts.destroy();
}

fn getFontsList(alloc: Allocator, fonts: []const u8) !ArrayListUnmanaged([*:0]const u8) {
    var list = try ArrayListUnmanaged([*:0]const u8).initCapacity(alloc, 2);
    errdefer list.deinit(alloc);
fn getFontsList(fonts: []const u8) !std.ArrayListUnmanaged([*:0]const u8) {
    var list = try std.ArrayListUnmanaged([*:0]const u8).initCapacity(ctx.gpa, 2);
    errdefer list.deinit(ctx.gpa);

    var it = mem.tokenize(u8, fonts, ",");
    while (it.next()) |font| {
        try list.append(alloc, try alloc.dupeZ(u8, font));
        try list.append(ctx.gpa, try ctx.gpa.dupeZ(u8, font));
    }

    return list;

M src/main.zig => src/main.zig +51 -56
@@ 16,13 16,13 @@

const std = @import("std");
const fmt = std.fmt;
const io = std.io;
const mem = std.mem;
const os = std.os;
const unicode = std.unicode;
const Allocator = std.mem.Allocator;

const fcft = @import("fcft");
const pixman = @import("pixman");
const Image = pixman.Image;
const wayland = @import("wayland");
const wl = wayland.client.wl;
const xdg = wayland.client.xdg;


@@ 47,7 47,7 @@ const usage =
;

const Context = struct {
    gpa: Allocator = undefined,
    gpa: mem.Allocator = undefined,

    compositor: ?*wl.Compositor = null,
    shm: ?*wl.Shm = null,


@@ 87,6 87,7 @@ pub fn main() anyerror!void {
    var arena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
    defer arena.deinit();
    const alloc = arena.allocator();
    ctx.gpa = alloc;

    // Initialize fcft.
    _ = fcft.init(.auto, false, .debug);


@@ 94,7 95,41 @@ pub fn main() anyerror!void {
    // valgrind happy.
    defer fcft.fini();

    try parseFlags();
    // Parse cli options.
    // https://github.com/ziglang/zig/issues/7807
    const argv: [][*:0]const u8 = os.argv;
    const result = flags.parse(argv[1..], &[_]flags.Flag{
        .{ .name = "-h", .kind = .boolean },
        .{ .name = "-text", .kind = .arg },
        .{ .name = "-font", .kind = .arg },
        .{ .name = "-bg", .kind = .arg },
        .{ .name = "-fg", .kind = .arg },
    }) catch {
        try io.getStdErr().writeAll(usage);
        os.exit(1);
    };
    if (result.args.len != 0) {
        log.err("Unknown option '{s}'", .{result.args[0]});
        io.getStdErr().writeAll(usage) catch {};
        os.exit(1);
    }

    if (result.boolFlag("-h")) {
        try io.getStdOut().writeAll(usage);
        os.exit(0);
    }
    if (result.argFlag("-text")) |raw| {
        default_text = raw;
    }
    if (result.argFlag("-font")) |raw| {
        default_font = raw;
    }
    if (result.argFlag("-bg")) |raw| {
        default_bg = raw;
    }
    if (result.argFlag("-fg")) |raw| {
        default_fg = raw;
    }

    // Convert text string to unicode.
    var codepoint_it = (try unicode.Utf8View.init(default_text)).iterator();


@@ 111,14 146,13 @@ pub fn main() anyerror!void {
    graphemes = try zgrapheme.utf32Segmenter(alloc, default_text);

    // Initialize font and fallbacks.
    ctx.font = try Font.init(alloc, default_font);
    ctx.font = try Font.init(default_font);
    // Remember to deinit it if you don't use an arena allocator:
    // e.g. defer ctx.font.deinit();

    // Initialize all Wayland related stuffs.
    const display = wl.Display.connect(null) catch {
        std.debug.print("Unable to connect to Wayland server.\n", .{});
        os.exit(1);
        fatal("Unable to connect to Wayland server.\n", .{});
    };
    defer display.disconnect();
    const registry = try display.getRegistry();


@@ 142,7 176,6 @@ pub fn main() anyerror!void {
    }

    // Initialize the remainder of context.
    ctx.gpa = alloc;
    ctx.shm.?.setListener(*Context, shmListener, &ctx);
    ctx.wm_base.?.setListener(*Context, xdgShellListener, &ctx);



@@ 177,7 210,7 @@ pub fn main() anyerror!void {
    var blocked = os.system.empty_sigset;
    os.linux.sigaddset(&blocked, os.SIG.INT);
    os.linux.sigaddset(&blocked, os.SIG.QUIT);
    _ = os.linux.sigprocmask(os.SIG.BLOCK, &blocked, &mask);
    _ = os.system.sigprocmask(os.SIG.BLOCK, &blocked, &mask);

    const act = os.Sigaction{
        .handler = .{


@@ 287,7 320,7 @@ fn xdgSurfaceListener(xdg_surface: *xdg.Surface, event: xdg.Surface.Event, surfa

            // Background
            var bg = parseRgba(default_bg) catch return;
            _ = Image.fillRectangles(
            _ = pixman.Image.fillRectangles(
                .src,
                buffer.pixman_image.?,
                &bg,


@@ 302,7 335,7 @@ fn xdgSurfaceListener(xdg_surface: *xdg.Surface, event: xdg.Surface.Event, surfa

            // Foreground
            var fg = parseRgba(default_fg) catch return;
            const color = Image.createSolidFill(&fg).?;
            const color = pixman.Image.createSolidFill(&fg).?;
            defer _ = color.unref();

            // Render text


@@ 357,7 390,7 @@ fn renderGlyphs(
    buffer: *Buffer,
    x: *i32,
    y: *const i32,
    color: *Image,
    color: *pixman.Image,
    len: usize,
    glyphs: [*]*const fcft.Glyph,
    kerns: ?[]c_long,


@@ 373,10 406,10 @@ fn renderGlyphs(
            if (kerns) |kern| ctx.gpa.destroy(kern.ptr);
        }

        switch (Image.getFormat(glyph.pix)) {
        switch (pixman.Image.getFormat(glyph.pix)) {
            // Glyph is a pre-rendered image. (e.g. a color emoji)
            .a8r8g8b8 => {
                Image.composite32(
                pixman.Image.composite32(
                    .over,
                    glyph.pix,
                    null,


@@ 393,7 426,7 @@ fn renderGlyphs(
            },
            // Glyph is an alpha mask.
            else => {
                Image.composite32(
                pixman.Image.composite32(
                    .over,
                    color,
                    glyph.pix,


@@ 418,7 451,7 @@ fn renderChars(
    text: []const u32,
    buffer: *Buffer,
    y: *i32,
    color: *Image,
    color: *pixman.Image,
) !void {
    const font = ctx.font.fonts;



@@ 446,7 479,7 @@ fn renderChars(
    renderGlyphs(buffer, &x, y, color, text.len, glyphs.ptr, kerns);
}

fn renderGraphemes(buffer: *Buffer, y: *i32, color: *Image) !void {
fn renderGraphemes(buffer: *Buffer, y: *i32, color: *pixman.Image) !void {
    if ((fcft.capabilities() & fcft.Capabilities.text_run_shaping) == 0) {
        const text_err = "fcft compiled without text-run shaping support";
        const err = try ctx.gpa.alloc(u32, text_err.len);


@@ 475,7 508,7 @@ fn renderGraphemes(buffer: *Buffer, y: *i32, color: *Image) !void {
}

/// Render text using fcft text run.
pub fn renderShaped(buffer: *Buffer, y: *i32, color: *Image) !void {
pub fn renderShaped(buffer: *Buffer, y: *i32, color: *pixman.Image) !void {
    if ((fcft.capabilities() & fcft.Capabilities.text_run_shaping) == 0) {
        const text_err = "fcft compiled without text-run shaping support";
        const err = try ctx.gpa.alloc(u32, text_err.len);


@@ 518,44 551,6 @@ fn parseRgba(s: []const u8) anyerror!pixman.Color {
    };
}

/// Parse cli options.
fn parseFlags() !void {
    // https://github.com/ziglang/zig/issues/7807
    const argv: [][*:0]const u8 = os.argv;
    const result = flags.parse(argv[1..], &[_]flags.Flag{
        .{ .name = "-h", .kind = .boolean },
        .{ .name = "-text", .kind = .arg },
        .{ .name = "-font", .kind = .arg },
        .{ .name = "-bg", .kind = .arg },
        .{ .name = "-fg", .kind = .arg },
    }) catch {
        try std.io.getStdErr().writeAll(usage);
        os.exit(1);
    };
    if (result.args.len != 0) {
        log.err("Unknown option '{s}'", .{result.args[0]});
        std.io.getStdErr().writeAll(usage) catch {};
        os.exit(1);
    }

    if (result.boolFlag("-h")) {
        try std.io.getStdOut().writeAll(usage);
        os.exit(0);
    }
    if (result.argFlag("-text")) |raw| {
        default_text = raw;
    }
    if (result.argFlag("-font")) |raw| {
        default_font = raw;
    }
    if (result.argFlag("-bg")) |raw| {
        default_bg = raw;
    }
    if (result.argFlag("-fg")) |raw| {
        default_fg = raw;
    }
}

fn fatal(comptime format: []const u8, args: anytype) noreturn {
    log.err(format, args);
    os.exit(1);