Skip to content

Commit

Permalink
Automatic width and height properties on images (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
pfgithub authored Nov 6, 2024
1 parent 8354b13 commit e11e75a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
8 changes: 6 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
.version = "0.0.0",
.dependencies = .{
.supermd = .{
.url = "git+https://github.com/kristoff-it/supermd#a034ec48c8a01b26de50f479090716d3ed2152c9",
.hash = "122058e6f4ebd493d1c7f7c1e21549d2b2e5d9a1921dba758f3558d88a34a70384be",
.url = "git+https://github.com/kristoff-it/supermd#c47273684d3236881fdc9f90fbf66965389d88bd",
.hash = "1220f5265c5f99c621f3b2d822723ba1b79297b4c809fcee98c7d48947002458bf7c",
},
.scripty = .{
.url = "git+https://github.com/kristoff-it/scripty#df8c11380f9e9bec34809f2242fb116d27cf39d6",
Expand Down Expand Up @@ -39,6 +39,10 @@
.hash = "1220f2d8402bb7bbc4786b9c0aad73910929ea209cbd3b063842371d68abfed33c1e",
.lazy = true,
},
.wuffs = .{
.url = "git+https://github.com/allyourcodebase/wuffs#818c8ad6607dd5c1ee571362fdb9813b744ee548",
.hash = "1220e4ee09c4fa2d90a9cc7f34f14e04be55a779c84d486696fa9f9ab98ade35409d",
},
},
.paths = .{"."},
}
2 changes: 2 additions & 0 deletions build/tools.zig
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub fn build(b: *std.Build) !void {
const syntax = b.dependency("flow-syntax", mode);
const ts = syntax.builder.dependency("tree-sitter", mode);
const treez = ts.module("treez");
const wuffs = b.dependency("wuffs", mode);

const zine = b.addModule("zine", .{
.root_source_file = b.path("src/root.zig"),
Expand Down Expand Up @@ -97,6 +98,7 @@ pub fn build(b: *std.Build) !void {
layout.root_module.addImport("zeit", zeit);
layout.root_module.addImport("syntax", syntax.module("syntax"));
layout.root_module.addImport("treez", treez);
layout.root_module.addImport("wuffs", wuffs.module("wuffs"));
layout.linkLibrary(ts.artifact("tree-sitter"));

b.installArtifact(layout);
Expand Down
75 changes: 74 additions & 1 deletion src/exes/layout/cache.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const join = zine.join;
const context = zine.context;
const Allocator = std.mem.Allocator;
const DepWriter = zine.DepWriter;
const wuffs = @import("wuffs");

const log = std.log.scoped(.layout_cache);

Expand Down Expand Up @@ -957,7 +958,7 @@ fn loadPage(
directive.kind.code.src = .{ .url = buf.items };
},
inline else => |val, tag| {
const res = switch (val.src.?) {
const res: context.Value = switch (val.src.?) {
.url => continue,
.self_page => blk: {
if (@hasField(@TypeOf(val), "alternative")) {
Expand Down Expand Up @@ -1138,6 +1139,16 @@ fn loadPage(
a._meta.kind,
);
@field(directive.kind, @tagName(tag)).src = .{ .url = url };
if(directive.kind == .image) blk: {
const image_handle = std.fs.cwd().openFile(a._meta.path, .{}) catch break :blk;
defer image_handle.close();
var image_header_buf: [2048]u8 = undefined;
const image_header_len = image_handle.readAll(&image_header_buf) catch break :blk;
const image_header = image_header_buf[0..image_header_len];

const img_size = getImageSize(image_header) catch break :blk;
directive.kind.image.size = .{.w = img_size.w, .h = img_size.h};
}
},
}
},
Expand All @@ -1146,6 +1157,68 @@ fn loadPage(
return page;
}

const max_align = @alignOf(std.c.max_align_t);
fn allocDecoder(
comptime name: []const u8,
) !struct { []align(max_align) u8, *wuffs.wuffs_base__image_decoder } {
const size = @field(wuffs, "sizeof__wuffs_" ++ name ++ "__decoder")();
const init_fn = @field(wuffs, "wuffs_" ++ name ++ "__decoder__initialize");
const upcast_fn = @field(wuffs, "wuffs_" ++ name ++ "__decoder__upcast_as__wuffs_base__image_decoder");

const decoder_raw = try gpa.alignedAlloc(u8, max_align, size);
errdefer gpa.free(decoder_raw);
for (decoder_raw) |*byte| byte.* = 0;

try wrapErr(init_fn(@ptrCast(decoder_raw), size, wuffs.WUFFS_VERSION, wuffs.WUFFS_INITIALIZE__ALREADY_ZEROED));

const upcasted = upcast_fn(@ptrCast(decoder_raw)).?;
return .{ decoder_raw, upcasted };
}
fn wrapErr(status: wuffs.wuffs_base__status) !void {
if (wuffs.wuffs_base__status__message(&status)) |_| {
return error.WuffsError;
}
}
const Size = struct {w: i64, h: i64};
fn getImageSize(image_src: []const u8) !Size {
var g_src = wuffs.wuffs_base__ptr_u8__reader(@constCast(image_src.ptr), image_src.len, true);

const g_fourcc = wuffs.wuffs_base__magic_number_guess_fourcc(
wuffs.wuffs_base__io_buffer__reader_slice(&g_src),
g_src.meta.closed,
);
if (g_fourcc < 0) return error.CouldNotGuessFileFormat;

const decoder_raw, const g_image_decoder = switch (g_fourcc) {
wuffs.WUFFS_BASE__FOURCC__BMP => try allocDecoder("bmp"),
wuffs.WUFFS_BASE__FOURCC__GIF => try allocDecoder("gif"),
wuffs.WUFFS_BASE__FOURCC__JPEG => try allocDecoder("jpeg"),
wuffs.WUFFS_BASE__FOURCC__NPBM => try allocDecoder("netpbm"),
wuffs.WUFFS_BASE__FOURCC__NIE => try allocDecoder("nie"),
wuffs.WUFFS_BASE__FOURCC__PNG => try allocDecoder("png"),
wuffs.WUFFS_BASE__FOURCC__QOI => try allocDecoder("qoi"),
wuffs.WUFFS_BASE__FOURCC__TGA => try allocDecoder("tga"),
wuffs.WUFFS_BASE__FOURCC__WBMP => try allocDecoder("wbmp"),
wuffs.WUFFS_BASE__FOURCC__WEBP => try allocDecoder("webp"),
else => {
return error.UnsupportedImageFormat;
},
};
defer gpa.free(decoder_raw);

var g_image_config = std.mem.zeroes(wuffs.wuffs_base__image_config);
try wrapErr(wuffs.wuffs_base__image_decoder__decode_image_config(
g_image_decoder,
&g_image_config,
&g_src,
));

const g_width = wuffs.wuffs_base__pixel_config__width(&g_image_config.pixcfg);
const g_height = wuffs.wuffs_base__pixel_config__height(&g_image_config.pixcfg);

return .{.w = std.math.cast(i64, g_width) orelse return error.Cast, .h = std.math.cast(i64, g_height) orelse return error.Cast};
}

pub fn fatal(comptime fmt: []const u8, args: anytype) noreturn {
std.debug.print(fmt, args);
std.process.exit(1);
Expand Down
1 change: 1 addition & 0 deletions src/render/html.zig
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ fn renderDirective(
if (directive.title) |t| try w.print(" title=\"{s}\"", .{t});
try w.print(" src=\"{s}\"", .{img.src.?.url});
if (img.alt) |alt| try w.print(" alt=\"{s}\"", .{alt});
if(img.size) |size| try w.print(" width=\"{d}\" height=\"{d}\"", .{size.w, size.h});
try w.print(">", .{});
if (img.linked) |l| if (l) try w.print("</a>", .{});
if (caption != null) try w.print("\n<figcaption>", .{});
Expand Down

0 comments on commit e11e75a

Please sign in to comment.