DVUI

fromTvgFile

the returned []PMA inside PMAImage is allocated with alloc the render_alloc is used for temporary allocations in the render process

Parameters

#
dbg_name:[]const u8
[]const u8
alloc:std.mem.Allocator
std.mem.Allocator
render_alloc:std.mem.Allocator
std.mem.Allocator
tvg_bytes:[]const u8
[]const u8
height:u32
u32
icon_opts:dvui.IconRenderOptions
dvui.IconRenderOptions

Source

Implementation

#
pub fn fromTvgFile(dbg_name: []const u8, alloc: std.mem.Allocator, render_alloc: std.mem.Allocator, tvg_bytes: []const u8, height: u32, icon_opts: dvui.IconRenderOptions) !PMAImage {
        if (comptime !dvui.useTvg) {
            comptime unreachable;
        }
        const ImageAdapter = struct {
            pixels: []u8,
            width: u32,
            height: u32,
            pub fn setPixel(self: *@This(), x: usize, y: usize, col: [4]u8) void {
                const idx = (y * self.width + x) * 4;
                for (0..4) |i| self.pixels[idx + i] = col[i];
            }
            pub fn getPixel(self: *@This(), x: usize, y: usize) [4]u8 {
                const idx = y * self.width + x;
                const slice = self.pixels[idx * 4 .. (idx + 1) * 4];
                var col: [4]u8 = undefined;
                for (&col, slice) |*a, s| a.* = s;
            }
            fn conv(dcol: dvui.Color) tvg.Color {
                return tvg.Color{
                    .r = @as(f32, dcol.r) / 255.0,
                    .g = @as(f32, dcol.g) / 255.0,
                    .b = @as(f32, dcol.b) / 255.0,
                    .a = @as(f32, dcol.a) / 255.0,
                };
            }
        };

        var width: u32 = @trunc(try dvui.iconWidth(dbg_name, tvg_bytes, @floatFromInt(height)));

        // height will be at least 1, but iconWidth could return < 1, truncated
        // to 0, which would fail rendering
        width = @max(width, 1);

        const img_raw_data = try alloc.alloc(u8, width * height * 4);

        @memset(img_raw_data, 0);
        var img = ImageAdapter{
            .pixels = img_raw_data,
            .width = width,
            .height = height,
        };
        var fb: std.Io.Reader = .fixed(tvg_bytes);

        var ow_stroke: ?tvg.Color = null;
        if (icon_opts.stroke_color) |cx| ow_stroke = ImageAdapter.conv(cx);
        var ow_fill: ?tvg.Color = null;
        var disable_fill = false;
        if (ow_fill != null and ow_fill.?.a == 0.0) disable_fill = true;
        if (icon_opts.fill_color) |cx| ow_fill = ImageAdapter.conv(cx);
        tvg.renderStream(dvui.io, render_alloc, &img, &fb, .{
            .overwrite_stroke_width = icon_opts.stroke_width,
            .overwrite_stroke = ow_stroke,
            .overwrite_fill = ow_fill,
            .disable_fill = disable_fill,
        }) catch |err| {
            dvui.log.warn("iconTexture Tinyvg error {any} rendering icon {s} at height {d}\n", .{ err, dbg_name, height });
            return dvui.TvgError.tvgError;
        };
        return PMAImage{
            .pma = std.mem.bytesAsSlice(PMA, img.pixels),
            .width = img.width,
            .height = img.height,
        };
    }