From b92770404f4a6742b162f63e1e4a08bfc48d73fd Mon Sep 17 00:00:00 2001 From: Ali Chraghi <63465728+alichraghi@users.noreply.github.com> Date: Thu, 26 May 2022 03:08:36 +0430 Subject: [PATCH] freetype: add a wrapper for outline functions --- freetype/examples/glyph-to-svg.zig | 28 ++++----- freetype/src/Outline.zig | 94 +++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 20 deletions(-) diff --git a/freetype/examples/glyph-to-svg.zig b/freetype/examples/glyph-to-svg.zig index bc488126..18a310c5 100644 --- a/freetype/examples/glyph-to-svg.zig +++ b/freetype/examples/glyph-to-svg.zig @@ -53,7 +53,7 @@ const OutlinePrinter = struct { pub fn extractOutline(self: *Self) !void { try self.path_stream.writer().writeAll(""); } @@ -83,28 +83,20 @@ const OutlinePrinter = struct { , .{ self.xMin, self.yMin, self.width, self.height, self.path_stream.getWritten() }); } - pub fn moveToFunction(to: [*c]const freetype.Vector, self_ptr: ?*anyopaque) callconv(.C) c_int { - var self = @ptrCast(*Self, @alignCast(std.meta.alignment(Self), self_ptr)); - self.path_stream.writer().print("M {d} {d}\t", .{ to.*.x, to.*.y }) catch unreachable; - return 0; + pub fn moveToFunction(self: *Self, to: freetype.Vector) freetype.Error!void { + self.path_stream.writer().print("M {d} {d}\t", .{ to.x, to.y }) catch unreachable; } - pub fn lineToFunction(to: [*c]const freetype.Vector, self_ptr: ?*anyopaque) callconv(.C) c_int { - var self = @ptrCast(*Self, @alignCast(std.meta.alignment(Self), self_ptr)); - self.path_stream.writer().print("L {d} {d}\t", .{ to.*.x, to.*.y }) catch unreachable; - return 0; + pub fn lineToFunction(self: *Self, to: freetype.Vector) freetype.Error!void { + self.path_stream.writer().print("L {d} {d}\t", .{ to.x, to.y }) catch unreachable; } - pub fn conicToFunction(control: [*c]const freetype.Vector, to: [*c]const freetype.Vector, self_ptr: ?*anyopaque) callconv(.C) c_int { - var self = @ptrCast(*Self, @alignCast(std.meta.alignment(Self), self_ptr)); - self.path_stream.writer().print("Q {d} {d}, {d} {d}\t", .{ control.*.x, control.*.y, to.*.x, to.*.y }) catch unreachable; - return 0; + pub fn conicToFunction(self: *Self, control: freetype.Vector, to: freetype.Vector) freetype.Error!void { + self.path_stream.writer().print("Q {d} {d}, {d} {d}\t", .{ control.x, control.y, to.x, to.y }) catch unreachable; } - pub fn cubicToFunction(control_0: [*c]const freetype.Vector, control_1: [*c]const freetype.Vector, to: [*c]const freetype.Vector, self_ptr: ?*anyopaque) callconv(.C) c_int { - var self = @ptrCast(*Self, @alignCast(std.meta.alignment(Self), self_ptr)); - self.path_stream.writer().print("C {d} {d}, {d} {d}, {d} {d}\t", .{ control_0.*.x, control_0.*.y, control_1.*.x, control_1.*.y, to.*.x, to.*.y }) catch unreachable; - return 0; + pub fn cubicToFunction(self: *Self, control_0: freetype.Vector, control_1: freetype.Vector, to: freetype.Vector) freetype.Error!void { + self.path_stream.writer().print("C {d} {d}, {d} {d}, {d} {d}\t", .{ control_0.x, control_0.y, control_1.x, control_1.y, to.x, to.y }) catch unreachable; } pub fn run(self: *Self, symbol: u8) !void { diff --git a/freetype/src/Outline.zig b/freetype/src/Outline.zig index f7b1eb2a..a78e42fa 100644 --- a/freetype/src/Outline.zig +++ b/freetype/src/Outline.zig @@ -4,6 +4,7 @@ const types = @import("types.zig"); const Glyph = @import("Glyph.zig"); const Error = @import("error.zig").Error; const convertError = @import("error.zig").convertError; +const errorToInt = @import("error.zig").errorToInt; const Outline = @This(); @@ -48,6 +49,95 @@ pub fn bbox(self: Outline) Error!types.BBox { return res; } -pub fn decompose(self: Outline, callbacks_ctx: anytype, callbacks: *c.FT_Outline_Funcs) Error!void { - try convertError(c.FT_Outline_Decompose(self.handle, callbacks, @ptrCast(?*anyopaque, callbacks_ctx))); +pub fn OutlineFuncs(comptime Context: type) type { + return struct { + move_to: fn (ctx: Context, to: types.Vector) Error!void, + line_to: fn (ctx: Context, to: types.Vector) Error!void, + conic_to: fn (ctx: Context, control: types.Vector, to: types.Vector) Error!void, + cubic_to: fn (ctx: Context, control_0: types.Vector, control_1: types.Vector, to: types.Vector) Error!void, + shift: c_int, + delta: isize, + }; +} + +pub fn OutlineFuncsWrapper(comptime Context: type) type { + return struct { + const Self = @This(); + ctx: Context, + callbacks: OutlineFuncs(Context), + + fn getSelf(ptr: ?*anyopaque) *Self { + return @ptrCast(*Self, @alignCast(@alignOf(Self), ptr)); + } + + fn castVec(vec: [*c]const c.FT_Vector) types.Vector { + return @intToPtr(*types.Vector, @ptrToInt(vec)).*; + } + + pub fn move_to(to: [*c]const c.FT_Vector, ctx: ?*anyopaque) callconv(.C) c_int { + const self = getSelf(ctx); + return if (self.callbacks.move_to(self.ctx, castVec(to))) |_| + 0 + else |err| + errorToInt(err); + } + + pub fn line_to(to: [*c]const c.FT_Vector, ctx: ?*anyopaque) callconv(.C) c_int { + const self = getSelf(ctx); + return if (self.callbacks.line_to(self.ctx, castVec(to))) |_| + 0 + else |err| + errorToInt(err); + } + + pub fn conic_to( + control: [*c]const c.FT_Vector, + to: [*c]const c.FT_Vector, + ctx: ?*anyopaque, + ) callconv(.C) c_int { + const self = getSelf(ctx); + return if (self.callbacks.conic_to( + self.ctx, + castVec(control), + castVec(to), + )) |_| + 0 + else |err| + errorToInt(err); + } + + pub fn cubic_to( + control_0: [*c]const c.FT_Vector, + control_1: [*c]const c.FT_Vector, + to: [*c]const c.FT_Vector, + ctx: ?*anyopaque, + ) callconv(.C) c_int { + const self = getSelf(ctx); + return if (self.callbacks.cubic_to( + self.ctx, + castVec(control_0), + castVec(control_1), + castVec(to), + )) |_| + 0 + else |err| + errorToInt(err); + } + }; +} + +pub fn decompose(self: Outline, ctx: anytype, callbacks: OutlineFuncs(@TypeOf(ctx))) Error!void { + var wrapper = OutlineFuncsWrapper(@TypeOf(ctx)){ .ctx = ctx, .callbacks = callbacks }; + try convertError(c.FT_Outline_Decompose( + self.handle, + &c.FT_Outline_Funcs{ + .move_to = @TypeOf(wrapper).move_to, + .line_to = @TypeOf(wrapper).line_to, + .conic_to = @TypeOf(wrapper).conic_to, + .cubic_to = @TypeOf(wrapper).cubic_to, + .shift = callbacks.shift, + .delta = callbacks.delta, + }, + &wrapper, + )); }