diff --git a/build.py b/build.py index 4389e53..3850864 100644 --- a/build.py +++ b/build.py @@ -46,7 +46,7 @@ def build_pages(): def copy_native(): - src = NATIVE / "zig-out" / "lib" / "gingerbread.wasm" + src = NATIVE / "zig-out" / "bin" / "gingerbread.wasm" dest = BUILD / "native" / "gingerbread.wasm" dest.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(src, dest) @@ -64,6 +64,7 @@ def watch(): server = livereload.Server() server.watch(WEB, func=build, delay="forever") server.watch(BUILD) + server.watch(NATIVE, func=build) server.serve(root="build") diff --git a/native/build.zig b/native/build.zig index 9103918..8f6f9e9 100644 --- a/native/build.zig +++ b/native/build.zig @@ -1,63 +1,86 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { - const rel_opts = b.standardReleaseOptions(); +pub fn build(b: *std.Build) void { const target: std.zig.CrossTarget = .{ .cpu_arch = .wasm32, .os_tag = .wasi }; - //const target = b.standardTargetOptions(.{}); - - const libpotrace = b.addStaticLibrary("potrace", null); - const libpotrace_flags = [_][]const u8{"-std=gnu17", "-DHAVE_CONFIG_H"}; - libpotrace.setTarget(target); - libpotrace.setBuildMode(rel_opts); - libpotrace.linkSystemLibrary("c"); - libpotrace.addIncludePath("lib/potrace-1.16/src"); - libpotrace.addIncludePath("lib/potrace-config"); - libpotrace.addCSourceFile("lib/potrace-1.16/src/curve.c", &libpotrace_flags); - libpotrace.addCSourceFile("lib/potrace-1.16/src/trace.c", &libpotrace_flags); - libpotrace.addCSourceFile("lib/potrace-1.16/src/decompose.c", &libpotrace_flags); - libpotrace.addCSourceFile("lib/potrace-1.16/src/potracelib.c", &libpotrace_flags); - - const libclipper2 = b.addStaticLibrary("clipper2", null); - const libclipper2_flags = [_][]const u8{"-std=gnu++17", "-fno-exceptions", "-Dthrow=abort"}; - libclipper2.setTarget(target); - libclipper2.setBuildMode(rel_opts); + const optimize = b.standardOptimizeOption(.{}); + + const libpotrace = b.addStaticLibrary(.{ + .name = "potrace", + .target = target, + .optimize = optimize, + }); + const libpotrace_flags = .{ "-std=gnu17", "-DHAVE_CONFIG_H" }; + libpotrace.linkLibC(); + libpotrace.addIncludePath(.{ .path = "lib/potrace-1.16/src" }); + libpotrace.addIncludePath(.{ .path = "lib/potrace-config" }); + libpotrace.addCSourceFile(.{ .file = .{ .path = "lib/potrace-1.16/src/curve.c" }, .flags = &libpotrace_flags }); + libpotrace.addCSourceFile(.{ .file = .{ .path = "lib/potrace-1.16/src/trace.c" }, .flags = &libpotrace_flags }); + libpotrace.addCSourceFile(.{ .file = .{ .path = "lib/potrace-1.16/src/decompose.c" }, .flags = &libpotrace_flags }); + libpotrace.addCSourceFile(.{ .file = .{ .path = "lib/potrace-1.16/src/potracelib.c" }, .flags = &libpotrace_flags }); + + const libclipper2 = b.addStaticLibrary(.{ + .name = "clipper2", + .target = target, + .optimize = optimize, + .link_libc = true, + }); + const libclipper2_flags = .{ "-std=gnu++17", "-fno-exceptions", "-Dthrow=abort" }; + libclipper2.linkLibC(); libclipper2.linkSystemLibrary("c++"); - libclipper2.addIncludePath("lib/clipper2/CPP/Clipper2Lib"); - libclipper2.addIncludePath("src"); - libclipper2.addCSourceFile("lib/clipper2/CPP/Clipper2Lib/clipper.engine.cpp", &libclipper2_flags); - libclipper2.addCSourceFile("lib/clipper2/CPP/Clipper2Lib/clipper.offset.cpp", &libclipper2_flags); - libclipper2.addCSourceFile("src/clipperwrapper.cpp", &libclipper2_flags); - - if (target.cpu_arch != null and target.cpu_arch.? == .wasm32) { - const libgingerbread = b.addSharedLibrary("gingerbread", "src/gingerbread.zig", b.version(1, 0, 0)); - libgingerbread.wasi_exec_model = std.builtin.WasiExecModel.reactor; - libgingerbread.setBuildMode(rel_opts); - libgingerbread.setTarget(target); - libgingerbread.linkSystemLibrary("c"); - libgingerbread.linkLibrary(libpotrace); - libgingerbread.linkLibrary(libclipper2); - libgingerbread.addIncludePath("src"); - libgingerbread.addIncludePath("lib/potrace-1.16/src"); - - libgingerbread.install(); - } - - const main = b.addTest("src/tests.zig"); - main.setBuildMode(rel_opts); - main.setTarget(target); - main.linkSystemLibrary("c"); - main.linkLibrary(libpotrace); - main.linkLibrary(libclipper2); - main.addIncludePath("src/"); - main.addIncludePath("lib/potrace-1.16/src"); - main.addIncludePath("lib/potrace-config"); - main.addIncludePath("lib/stb"); - main.addCSourceFile("src/load_image.c", &[_][]const u8{"-std=gnu17",}); - - //main.install(); - - const test_step = b.step("test", "Test the program"); - test_step.dependOn(&main.step); - b.default_step.dependOn(test_step); + libclipper2.addIncludePath(.{ .path = "lib/clipper2/CPP/Clipper2Lib" }); + libclipper2.addIncludePath(.{ .path = "src" }); + libclipper2.addCSourceFile(.{ + .file = .{ .path = "lib/clipper2/CPP/Clipper2Lib/clipper.engine.cpp" }, + .flags = &libclipper2_flags, + }); + libclipper2.addCSourceFile(.{ + .file = .{ .path = "lib/clipper2/CPP/Clipper2Lib/clipper.offset.cpp" }, + .flags = &libclipper2_flags, + }); + libclipper2.addCSourceFile(.{ + .file = .{ .path = "src/clipperwrapper.cpp" }, + .flags = &libclipper2_flags, + }); + + const libgingerbread = b.addExecutable(.{ + .name = "gingerbread", + .root_source_file = .{ .path = "src/gingerbread.zig" }, + .version = .{ .major = 1, .minor = 0, .patch = 0 }, + .target = target, + .optimize = optimize, + }); + libgingerbread.entry = .disabled; + libgingerbread.rdynamic = true; + libgingerbread.wasi_exec_model = std.builtin.WasiExecModel.reactor; + libgingerbread.strip = false; + libgingerbread.linkLibC(); + libgingerbread.linkLibrary(libpotrace); + libgingerbread.linkLibrary(libclipper2); + libgingerbread.addIncludePath(.{ .path = "src" }); + libgingerbread.addIncludePath(.{ .path = "lib/potrace-1.16/src" }); + + b.installArtifact(libgingerbread); + + // const main = b.addTest(.{ + // .name = "main", + // .root_source_file = .{ .path = "src/tests.zig" }, + // .target = target, + // .optimize = optimize, + // .link_libc = true, + // }); + // main.linkLibrary(libpotrace); + // main.linkLibrary(libclipper2); + // main.addIncludePath(.{ .path = "src/" }); + // main.addIncludePath(.{ .path = "lib/potrace-1.16/src" }); + // main.addIncludePath(.{ .path = "lib/potrace-config" }); + // main.addIncludePath(.{ .path = "lib/stb" }); + // main.addCSourceFile(.{ .file = .{ .path = "src/load_image.c" }, .flags = &.{ + // "-std=gnu17", + // } }); + + // //main.install(); + + // const test_step = b.step("test", "Test the program"); + // test_step.dependOn(&main.step); + // b.default_step.dependOn(test_step); } diff --git a/native/src/clipper.zig b/native/src/clipper.zig index 63abedd..bf6fbb0 100644 --- a/native/src/clipper.zig +++ b/native/src/clipper.zig @@ -7,7 +7,6 @@ const geometry = @import("geometry.zig"); const Point = geometry.Point; const Poly = geometry.Poly; - const PathD = struct { ptr: *c.pathd_t, @@ -31,7 +30,7 @@ const PathD = struct { pub fn get(self: PathD, index: usize) Point { const val = c.PathD_at(self.ptr, index); - return .{.x = val.x, .y = val.y}; + return .{ .x = val.x, .y = val.y }; } pub const Iterator = struct { @@ -76,8 +75,8 @@ const PathD = struct { pub fn svg_path(self: PathD) void { var it = self.iterator(); while (it.next()) |pt| { - var letter = if (it.n == 1) "M" else "L"; - print("{s} {d:3.3},{d:3.3} ", .{letter, pt.x, pt.y}); + const letter = if (it.n == 1) "M" else "L"; + print("{s} {d:3.3},{d:3.3} ", .{ letter, pt.x, pt.y }); } print("\n", .{}); } @@ -124,7 +123,7 @@ const PathList = struct { pub fn get(self: PathList, index: usize) PathD { const val = c.PathsD_at(self.ptr, index).?; - return .{.ptr = val}; + return .{ .ptr = val }; } pub const Iterator = struct { @@ -170,7 +169,7 @@ const PathList = struct { } pub fn to_poly(self: PathList, allocator: std.mem.Allocator) !Poly { - var outline = try self.get(0).to_points(allocator); + const outline = try self.get(0).to_points(allocator); var holes = try std.ArrayList([]Point).initCapacity(allocator, self.len() - 1); // The first path is the outline, subsequent paths are holes, so skip @@ -184,7 +183,7 @@ const PathList = struct { return .{ .allocator = allocator, .outline = outline, - .holes = holes.toOwnedSlice(), + .holes = try holes.toOwnedSlice(), }; } }; @@ -205,15 +204,15 @@ pub const FillRule = enum(u8) { }; pub fn boolean_op(clip_type: ClipType, fill_rule: FillRule, subjects: PathList, clips: PathList, decimal_precision: i32) PathList { - var solution_ptr = c.clipper2_boolean_op( - @enumToInt(clip_type), - @enumToInt(fill_rule), + const solution_ptr = c.clipper2_boolean_op( + @intFromEnum(clip_type), + @intFromEnum(fill_rule), subjects.ptr, clips.ptr, decimal_precision, ).?; - return .{.ptr = solution_ptr}; + return .{ .ptr = solution_ptr }; } pub const Options = struct { @@ -258,30 +257,29 @@ pub fn simplify_poly(allocator: std.mem.Allocator, poly: Poly) !Poly { return try result.to_poly(allocator); } - test "PathD" { var pathd = PathD.init(); defer pathd.deinit(); try testing.expect(pathd.len() == 0); - pathd.append(Point {.x = 1, .y = 2}); - pathd.append(Point {.x = 3, .y = 4}); + pathd.append(Point{ .x = 1, .y = 2 }); + pathd.append(Point{ .x = 3, .y = 4 }); try testing.expect(pathd.len() == 2); var it = pathd.iterator(); - try testing.expect(std.meta.eql(it.next().?, Point {.x = 1, .y = 2})); - try testing.expect(std.meta.eql(it.next().?, Point {.x = 3, .y = 4})); + try testing.expect(std.meta.eql(it.next().?, Point{ .x = 1, .y = 2 })); + try testing.expect(std.meta.eql(it.next().?, Point{ .x = 3, .y = 4 })); try testing.expect(it.next() == null); // Converting to and from points - var points = try pathd.to_points(std.testing.allocator); + const points = try pathd.to_points(std.testing.allocator); defer std.testing.allocator.free(points); try testing.expect(points.len == 2); - try testing.expect(std.meta.eql(points[0], Point {.x = 1, .y = 2})); - try testing.expect(std.meta.eql(points[1], Point {.x = 3, .y = 4})); + try testing.expect(std.meta.eql(points[0], Point{ .x = 1, .y = 2 })); + try testing.expect(std.meta.eql(points[1], Point{ .x = 3, .y = 4 })); var pathd2 = PathD.from_points(points); defer pathd2.deinit(); @@ -304,7 +302,7 @@ test "PathList" { try testing.expect(pathsd.len() == 0); var pathd = PathD.init(); - pathd.append(Point {.x = 1, .y = 2}); + pathd.append(Point{ .x = 1, .y = 2 }); pathsd.append(pathd); pathd.deinit(); @@ -321,12 +319,12 @@ test "PathList to Poly" { defer pathsd.deinit(); var outline = PathD.init(); - outline.append(Point {.x = 1, .y = 2}); + outline.append(Point{ .x = 1, .y = 2 }); pathsd.append(outline); outline.deinit(); var hole = PathD.init(); - hole.append(Point {.x = 3, .y = 4}); + hole.append(Point{ .x = 3, .y = 4 }); pathsd.append(hole); hole.deinit(); @@ -343,13 +341,23 @@ test "PathList to Poly" { test "boolean op" { var subjects = PathList.init(); defer subjects.deinit(); - var subject = PathD.from_points(&[_]Point{.{.x = 0, .y = 0}, .{.x = 100, .y = 0}, .{.x = 100, .y = 100}, .{.x = 0, .y = 100},}); + var subject = PathD.from_points(&[_]Point{ + .{ .x = 0, .y = 0 }, + .{ .x = 100, .y = 0 }, + .{ .x = 100, .y = 100 }, + .{ .x = 0, .y = 100 }, + }); subjects.append(subject); subject.deinit(); var clips = PathList.init(); defer clips.deinit(); - var clip = PathD.from_points(&[_]Point{.{.x = 25, .y = 25}, .{.x = 75, .y = 25}, .{.x = 75, .y = 75}, .{.x = 25, .y = 75},}); + var clip = PathD.from_points(&[_]Point{ + .{ .x = 25, .y = 25 }, + .{ .x = 75, .y = 25 }, + .{ .x = 75, .y = 75 }, + .{ .x = 25, .y = 75 }, + }); clips.append(clip); clip.deinit(); @@ -367,14 +375,24 @@ test "simplify poly" { var hole = std.ArrayList(Point).init(a); var holes = std.ArrayList([]Point).init(a); - try outline.appendSlice(&[_]Point{.{.x = 0, .y = 0}, .{.x = 100, .y = 0}, .{.x = 100, .y = 100}, .{.x = 0, .y = 100},}); - try hole.appendSlice(&[_]Point{.{.x = 25, .y = 25}, .{.x = 75, .y = 25}, .{.x = 75, .y = 75}, .{.x = 25, .y = 75},}); - try holes.append(hole.toOwnedSlice()); - - var poly = Poly { + try outline.appendSlice(&[_]Point{ + .{ .x = 0, .y = 0 }, + .{ .x = 100, .y = 0 }, + .{ .x = 100, .y = 100 }, + .{ .x = 0, .y = 100 }, + }); + try hole.appendSlice(&[_]Point{ + .{ .x = 25, .y = 25 }, + .{ .x = 75, .y = 25 }, + .{ .x = 75, .y = 75 }, + .{ .x = 25, .y = 75 }, + }); + try holes.append(try hole.toOwnedSlice()); + + var poly = Poly{ .allocator = a, - .outline = outline.toOwnedSlice(), - .holes = holes.toOwnedSlice(), + .outline = try outline.toOwnedSlice(), + .holes = try holes.toOwnedSlice(), }; defer poly.deinit(); @@ -394,7 +412,7 @@ test "simplify poly" { print("Result: {?}\n", .{poly}); - for (poly.outline) |_, i| { + for (poly.outline, 0..) |_, i| { try testing.expect(std.meta.eql(poly.outline[i], simplified.outline[i])); } } diff --git a/native/src/geometry.zig b/native/src/geometry.zig index d9c0565..a4cbe58 100644 --- a/native/src/geometry.zig +++ b/native/src/geometry.zig @@ -28,10 +28,10 @@ pub const Poly = struct { for (self.holes) |hole| { try holes.append(try self.allocator.dupe(Point, hole)); } - return Poly { + return Poly{ .allocator = self.allocator, .outline = outline, - .holes = holes.toOwnedSlice(), + .holes = try holes.toOwnedSlice(), }; } @@ -58,7 +58,7 @@ pub const Poly = struct { // joins hole edges to outer polygon. pub fn fracture(self: Poly, allocator: std.mem.Allocator) !Poly { // If there's no holes there's no need to do anything. - if(self.holes.len == 0) { + if (self.holes.len == 0) { return try self.copy(); } @@ -74,7 +74,7 @@ pub const Poly = struct { // Start by gathering the edges of the outline. The edges of the outline // are already "connected", where the edges of the holes will start // "unconnected" and get iteratively connected to the outside. - var outline_edges = try Edge.from_points(allocator, self.outline); + const outline_edges = try Edge.from_points(allocator, self.outline); defer allocator.free(outline_edges); try edges.ensureUnusedCapacity(outline_edges.len); @@ -90,10 +90,10 @@ pub const Poly = struct { var num_unconnected: usize = 0; for (self.holes) |hole| { - var hole_edges = try Edge.from_points(allocator, hole); + const hole_edges = try Edge.from_points(allocator, hole); defer allocator.free(hole_edges); - var x_min: f64 = std.math.f64_max; + var x_min: f64 = std.math.floatMax(f64); try edges.ensureUnusedCapacity(hole_edges.len); for (hole_edges) |edge| { try edges.append(edge); @@ -113,7 +113,7 @@ pub const Poly = struct { // Connect all holes to the outline. while (num_unconnected > 0) { - var x_min: f64 = std.math.f64_max; + var x_min: f64 = std.math.floatMax(f64); var leftmost: ?*Edge = null; // find the left-most unconnected hole edge and merge with the outline @@ -124,7 +124,7 @@ pub const Poly = struct { } } - var num_processed = try leftmost.?.connect_hole_to_outline(allocator, &edges); + const num_processed = try leftmost.?.connect_hole_to_outline(allocator, &edges); if (num_processed > num_unconnected) { return error.HoleConnectionOverflow; @@ -138,15 +138,15 @@ pub const Poly = struct { } pub fn svg_path(self: Poly) void { - for (self.outline) |pt, n| { - var letter = if (n == 0) "M" else "L"; - print("{s} {d:3.3},{d:3.3} ", .{letter, pt.x, pt.y}); + for (self.outline, 0..) |pt, n| { + const letter = if (n == 0) "M" else "L"; + print("{s} {d:3.3},{d:3.3} ", .{ letter, pt.x, pt.y }); } print("\n", .{}); for (self.holes) |hole| { - for (hole) |pt, n| { - var letter = if (n == 0) "M" else "L"; - print("{s} {d:3.3},{d:3.3} ", .{letter, pt.x, pt.y}); + for (hole, 0..) |pt, n| { + const letter = if (n == 0) "M" else "L"; + print("{s} {d:3.3},{d:3.3} ", .{ letter, pt.x, pt.y }); } } } @@ -159,17 +159,17 @@ pub const Poly = struct { try writer.print("Poly outline={d} holes={d}:\n", .{ self.outline.len, self.holes.len }); try tab(writer, tabs + 1); try writer.writeAll("Outline: "); - for (self.outline) |pt, n| { + for (self.outline, 0..) |pt, n| { try writer.print("{?}", .{pt}); if (n < self.outline.len - 1) { try writer.writeAll(", "); } } try writer.writeAll("\n"); - for (self.holes) |hole, i| { + for (self.holes, 0..) |hole, i| { try tab(writer, tabs + 1); try writer.print("Hole {d}: ", .{i}); - for (hole) |pt, n| { + for (hole, 0..) |pt, n| { try writer.print("{?}", .{pt}); if (n < self.outline.len - 1) { try writer.writeAll(", "); @@ -213,8 +213,8 @@ const Edge = struct { fn from_points(allocator: std.mem.Allocator, pts: []Point) ![]*Edge { var edges = try std.ArrayList(*Edge).initCapacity(allocator, pts.len); - for (pts) |pt, i| { - var edge = try allocator.create(Edge); + for (pts, 0..) |pt, i| { + const edge = try allocator.create(Edge); edge.* = .{ .p1 = pt, @@ -223,7 +223,7 @@ const Edge = struct { }; if (i > 0) { - edges.items[i-1].next = edge; + edges.items[i - 1].next = edge; } try edges.append(edge); @@ -238,17 +238,19 @@ const Edge = struct { fn to_poly(allocator: std.mem.Allocator, edges: []*Edge) !Poly { var outline = try std.ArrayList(Point).initCapacity(allocator, edges.len); - var root = edges[0]; + const root = edges[0]; var e = root; while (e.next != root) : (e = e.next.?) { - if(!e.connected) { print("warning: unconnected edge at index {d}.\n", .{outline.items.len}); } + if (!e.connected) { + print("warning: unconnected edge at index {d}.\n", .{outline.items.len}); + } try outline.append(e.p1); } try outline.append(e.p1); - return Poly { + return Poly{ .allocator = allocator, - .outline = outline.toOwnedSlice(), + .outline = try outline.toOwnedSlice(), .holes = &[_][]Point{}, }; } @@ -271,15 +273,15 @@ const Edge = struct { // Break this edge into two, splitting at the given (x, y). fn split(self: *Edge, allocator: std.mem.Allocator, x: f64, y: f64) !*Edge { - var after = try allocator.create(Edge); + const after = try allocator.create(Edge); after.* = .{ .connected = self.connected, - .p1 = .{.x = x, .y = y}, + .p1 = .{ .x = x, .y = y }, .p2 = self.p2, .next = self.next, }; - self.p2 = .{.x = x, .y = y}; + self.p2 = .{ .x = x, .y = y }; self.next = after; return after; @@ -292,13 +294,13 @@ const Edge = struct { // Split the nearest connected edge at the x-intersection, creating a // spot for the hole's edges to be connected in. - var split_after = try nearest.edge.split(allocator, nearest.x_intersect, self.p1.y); + const split_after = try nearest.edge.split(allocator, nearest.x_intersect, self.p1.y); // Connects the outline's edge to the hole's first edge var bridge_before = try allocator.create(Edge); bridge_before.* = .{ .connected = true, - .p1 = .{.x = nearest.x_intersect, .y = self.p1.y}, + .p1 = .{ .x = nearest.x_intersect, .y = self.p1.y }, .p2 = self.p1, }; @@ -307,7 +309,7 @@ const Edge = struct { bridge_after.* = .{ .connected = true, .p1 = self.p1, - .p2 = .{.x = nearest.x_intersect, .y = self.p1.y}, + .p2 = .{ .x = nearest.x_intersect, .y = self.p1.y }, }; try edges.append(bridge_before); @@ -335,16 +337,15 @@ const Edge = struct { return count + 1; } - // Find the nearest connected edge that this edge could be connected to. // An edge is connectable if this edge's "y" is contained within the // extents of the edge. "Nearest" is determined by the distance from this // edge to the point on the other edge where they would intersect // (the x_intersect). - fn find_nearest_connectable_edge(self: *Edge, edges: []*Edge) !struct {edge: *Edge, x_intersect: f64} { + fn find_nearest_connectable_edge(self: *Edge, edges: []*Edge) !struct { edge: *Edge, x_intersect: f64 } { var nearest: ?*Edge = null; var nearest_x_intersect: f64 = 0; - var nearest_dist: f64 = std.math.f64_max; + var nearest_dist: f64 = std.math.floatMax(f64); for (edges) |e| { if (!e.connected) { @@ -359,13 +360,13 @@ const Edge = struct { // Check if is this a horizontal edge to avoid divide by zero when // calculating the x_intersect. - if( e.p1.y == e.p2.y ) { - x_intersect = @max( e.p1.x, e.p2.x ); + if (e.p1.y == e.p2.y) { + x_intersect = @max(e.p1.x, e.p2.x); } else { x_intersect = e.p1.x + ((e.p2.x - e.p1.x) * (self.p1.y - e.p1.y) / (e.p2.y - e.p1.y)); } - var dist: f64 = self.p1.x - x_intersect; + const dist: f64 = self.p1.x - x_intersect; if (dist >= 0 and dist < nearest_dist) { nearest_dist = dist; @@ -374,17 +375,16 @@ const Edge = struct { } } - return .{.edge = nearest.?, .x_intersect = nearest_x_intersect}; + return .{ .edge = nearest.?, .x_intersect = nearest_x_intersect }; } pub fn format(self: Edge, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { _ = fmt; _ = options; - try writer.print("Edge p1={?} p2={?}, next=0x{x}, connected={?}", .{self.p1, self.p2, @ptrToInt(self.next), self.connected}); + try writer.print("Edge p1={?} p2={?}, next=0x{x}, connected={?}", .{ self.p1, self.p2, @intFromPtr(self.next), self.connected }); } }; - fn tab(writer: anytype, times: usize) !void { var n: usize = 0; while (n < times) : (n += 1) { diff --git a/native/src/gingerbread.zig b/native/src/gingerbread.zig index b5cc0f0..e4e341a 100644 --- a/native/src/gingerbread.zig +++ b/native/src/gingerbread.zig @@ -31,7 +31,7 @@ fn trace(allocator: std.mem.Allocator, layer_name: []const u8, scale_factor: f64 for (polylist.items) |*poly| { try poly.simplify(); - var fractured = try poly.fracture(allocator); + const fractured = try poly.fracture(allocator); poly.deinit(); poly.* = fractured; @@ -93,7 +93,7 @@ export fn conversion_add_poly_point( y: f64, scale_factor: f64, ) void { - pcb.add_xx_poly_point(.{.x = x, .y = y}, scale_factor, conversion_buffer.?.writer()) catch @panic("memory"); + pcb.add_xx_poly_point(.{ .x = x, .y = y }, scale_factor, conversion_buffer.?.writer()) catch @panic("memory"); } export fn conversion_end_poly(layer: u32, width: f32, fill: bool) void { @@ -102,7 +102,7 @@ export fn conversion_end_poly(layer: u32, width: f32, fill: bool) void { else => "Unknown", }; - print("layer number: {d}, layer name: {s}\n", .{layer, layer_name}); + print("layer number: {d}, layer name: {s}\n", .{ layer, layer_name }); pcb.end_xx_poly(layer_name, width, fill, conversion_buffer.?.writer()) catch @panic("memory"); } @@ -113,5 +113,5 @@ export fn conversion_add_drill(x: f64, y: f64, d: f64, scale_factor: f64) void { export fn conversion_finish() wasm.StringResult { pcb.end_pcb(&conversion_buffer.?.writer()) catch @panic("memory"); - return wasm.return_string(conversion_buffer.?.toOwnedSlice()); + return wasm.return_string(conversion_buffer.?.toOwnedSlice() catch @panic("memory")); } diff --git a/native/src/potrace.zig b/native/src/potrace.zig index fc4d9ef..22c5b36 100644 --- a/native/src/potrace.zig +++ b/native/src/potrace.zig @@ -22,7 +22,7 @@ pub fn pixel_at(image: Image, x: usize, y: usize) []u8 { pub fn luminosity(px: []u8) u32 { const avg: u32 = (px[0] + px[1] + px[2]) / 3; - if(px.len == 4) { + if (px.len == 4) { return avg * px[3] / 255; } return avg; @@ -34,7 +34,7 @@ pub fn luminosity2(image: Image, x: usize, y: usize) u32 { avg += image.pixels[idx + 1]; avg += image.pixels[idx + 2]; avg /= 3; - if(image.channels == 4) { + if (image.channels == 4) { return avg * image.pixels[idx + 3] / 255; } return avg; @@ -54,19 +54,15 @@ pub const Bitmap = struct { const dy = try Bitmap.dy_for_width(image.w); const size_in_words = dy * image.h; - var bitmap = Bitmap { - .allocator = allocator, - .data = try allocator.alloc(c.potrace_word, size_in_words), - .bm = c.potrace_bitmap_t { - .w = @intCast(c_int, image.w), - .h = @intCast(c_int, image.h), - .dy = @intCast(c_int, dy), - .map = null, - } - }; + var bitmap = Bitmap{ .allocator = allocator, .data = try allocator.alloc(c.potrace_word, size_in_words), .bm = c.potrace_bitmap_t{ + .w = @as(c_int, @intCast(image.w)), + .h = @as(c_int, @intCast(image.h)), + .dy = @as(c_int, @intCast(dy)), + .map = null, + } }; - std.mem.set(c.potrace_word, bitmap.data, 0); - bitmap.bm.map = @ptrCast([*c]c.potrace_word, bitmap.data); + @memset(bitmap.data, 0); + bitmap.bm.map = @as([*c]c.potrace_word, @ptrCast(bitmap.data)); var y: usize = 0; while (y < image.h) : (y += 1) { @@ -89,16 +85,16 @@ pub const Bitmap = struct { } pub fn trace(self: *Bitmap) !Trace { - var params = c.potrace_param_default(); + const params = c.potrace_param_default(); defer c.potrace_param_free(params); - var state = c.potrace_trace(params, &self.bm).?; + const state = c.potrace_trace(params, &self.bm).?; if (state.*.status != c.POTRACE_STATUS_OK) { return error.TraceFailed; } - return .{.state = state}; + return .{ .state = state }; } inline fn dy_for_width(w: usize) !usize { @@ -111,7 +107,7 @@ pub const Bitmap = struct { } inline fn index_for(self: *Bitmap, x: usize, y: usize) usize { - return (y * @intCast(usize, self.bm.dy)) + (x / @bitSizeOf(c.potrace_word)); + return (y * @as(usize, @intCast(self.bm.dy))) + (x / @bitSizeOf(c.potrace_word)); } pub inline fn put(self: *Bitmap, x: usize, y: usize, b: bool) void { @@ -134,13 +130,13 @@ pub const Trace = struct { current: ?*c.potrace_path_t, pub fn init(plist: *c.potrace_path_t) Iterator { - return Iterator { + return Iterator{ .current = plist, }; } pub fn next(self: *Iterator) ?*c.potrace_path_t { - var p = self.current; + const p = self.current; if (self.current) |current| { self.current = current.next; } @@ -155,13 +151,13 @@ pub const Trace = struct { var it = Iterator.init(self.state.plist); while (it.next()) |path| { - var points = try path_to_points(allocator, path, bezier_resolution); - if(path.sign == "+"[0]) { + const points = try path_to_points(allocator, path, bezier_resolution); + if (path.sign == "+"[0]) { if (outline) |outline_points| { try polys.append(.{ .allocator = allocator, .outline = outline_points, - .holes = holes.toOwnedSlice(), + .holes = try holes.toOwnedSlice(), }); } outline = points; @@ -174,14 +170,11 @@ pub const Trace = struct { try polys.append(.{ .allocator = allocator, .outline = outline_points, - .holes = holes.toOwnedSlice(), + .holes = try holes.toOwnedSlice(), }); } - return .{ - .allocator = allocator, - .items = polys.toOwnedSlice() - }; + return .{ .allocator = allocator, .items = try polys.toOwnedSlice() }; } // // TODO: change to format @@ -212,33 +205,35 @@ pub const Trace = struct { // } }; - fn path_to_points(allocator: std.mem.Allocator, path: *c.potrace_path_t, bezier_resolution: f32) ![]Point { var out = std.ArrayList(Point).init(allocator); var n: usize = 0; - var curve = path.*.curve; - var last = @intCast(usize, curve.n) - 1; - var start_point = curve.c[last][2]; + const curve = path.*.curve; + var last = @as(usize, @intCast(curve.n)) - 1; + const start_point = curve.c[last][2]; - try out.append(.{.x = start_point.x, .y = start_point.y}); + try out.append(.{ .x = start_point.x, .y = start_point.y }); - while (n < path.*.curve.n) : ({last = n; n += 1;}) { + while (n < path.*.curve.n) : ({ + last = n; + n += 1; + }) { switch (curve.tag[n]) { c.POTRACE_CORNER => { - try out.append(.{.x = curve.c[n][1].x, .y = curve.c[n][1].y}); - try out.append(.{.x = curve.c[n][2].x, .y = curve.c[n][2].y}); + try out.append(.{ .x = curve.c[n][1].x, .y = curve.c[n][1].y }); + try out.append(.{ .x = curve.c[n][2].x, .y = curve.c[n][2].y }); }, c.POTRACE_CURVETO => { var b = bezier.Approximator.init( - .{.x = curve.c[last][2].x, .y = curve.c[last][2].y}, - .{.x = curve.c[n][0].x, .y = curve.c[n][0].y}, - .{.x = curve.c[n][1].x, .y = curve.c[n][1].y}, - .{.x = curve.c[n][2].x, .y = curve.c[n][2].y}, + .{ .x = curve.c[last][2].x, .y = curve.c[last][2].y }, + .{ .x = curve.c[n][0].x, .y = curve.c[n][0].y }, + .{ .x = curve.c[n][1].x, .y = curve.c[n][1].y }, + .{ .x = curve.c[n][2].x, .y = curve.c[n][2].y }, bezier_resolution, ); while (b.next()) |p| { - try out.append(.{.x = p.x, .y = p.y}); + try out.append(.{ .x = p.x, .y = p.y }); } }, else => {}, @@ -249,9 +244,9 @@ fn path_to_points(allocator: std.mem.Allocator, path: *c.potrace_path_t, bezier_ } pub fn load_example_image() !c.image_t { - var image = c.load_image("resources/example-100px.png"); + const image = c.load_image("resources/example-100px.png"); try testing.expect(image.w > 0 and image.h > 0); - print("example-100px.png: w={d} h={d} channels={d}\n", .{image.w, image.h, image.channels}); + print("example-100px.png: w={d} h={d} channels={d}\n", .{ image.w, image.h, image.channels }); return image; } @@ -260,7 +255,7 @@ pub fn free_example_image(img: c.image_t) void { } pub fn load_example_bitmap(allocator: std.mem.Allocator) !Bitmap { - var image = try load_example_image(); + const image = try load_example_image(); defer free_example_image(image); return Bitmap.from_image(allocator, image); } @@ -273,7 +268,7 @@ test "trace png" { var bitmap = try load_example_bitmap(std.testing.allocator); defer bitmap.deinit(); - print("Bitmap w: {d}, h: {d}, dy: {d}\n", .{bitmap.bm.w, bitmap.bm.h, bitmap.bm.dy}); + print("Bitmap w: {d}, h: {d}, dy: {d}\n", .{ bitmap.bm.w, bitmap.bm.h, bitmap.bm.dy }); var trace = try bitmap.trace(); defer trace.deinit(); diff --git a/native/src/wasm.zig b/native/src/wasm.zig index 8a7699e..925d87a 100644 --- a/native/src/wasm.zig +++ b/native/src/wasm.zig @@ -6,8 +6,8 @@ pub const allocator = std.heap.c_allocator; // https://github.com/mbrock/wisp/blob/master/core/wasm.zig#L349 export fn z_allocate(n: u32) u32 { const buf = allocator.alloc(u8, n) catch return 0; - print("allocated {d} bytes @ {d}\n", .{ n, @ptrToInt(buf.ptr) }); - return @intCast(u32, @ptrToInt(buf.ptr)); + print("allocated {d} bytes @ {d}\n", .{ n, @intFromPtr(buf.ptr) }); + return @as(u32, @intCast(@intFromPtr(buf.ptr))); } export fn z_free_zero(x: [*:0]u8) void { @@ -19,15 +19,15 @@ export fn z_free(x: [*]u8, n: usize) void { } export fn z_print_memory(a: [*]u8, n: u32) void { - const span = std.mem.span(a[0..n]); + const span = a[0..n]; print("{*}: {any}\n", .{ a, span }); } pub fn return_string(str: []u8) u32 { var result: []u32 = allocator.alloc(u32, 2) catch return 0; - result[0] = @intCast(u32, @ptrToInt(str.ptr)); - result[1] = @intCast(u32, str.len); - return @intCast(u32, @ptrToInt(result.ptr)); + result[0] = @as(u32, @intCast(@intFromPtr(str.ptr))); + result[1] = @as(u32, @intCast(str.len)); + return @as(u32, @intCast(@intFromPtr(result.ptr))); } pub const StringResult = @typeInfo(@TypeOf(return_string)).Fn.return_type.?;