Skip to content

Commit

Permalink
harfbuzz: various improvements, Position -> GlyphPosition
Browse files Browse the repository at this point in the history
Fixes hexops/mach#1046

Signed-off-by: Stephen Gutekanst <[email protected]>
  • Loading branch information
emidoots committed Oct 4, 2023
1 parent 7dd97f0 commit 90b353a
Showing 1 changed file with 297 additions and 13 deletions.
310 changes: 297 additions & 13 deletions src/harfbuzz.zig
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,13 @@ pub const GlyphInfo = extern struct {
}
};

pub const Position = extern struct {
pub const GlyphPosition = extern struct {
x_advance: i32,
y_advance: i32,
x_offset: i32,
y_offset: i32,

/// Private / internal field.
@"var": i32,
};

Expand Down Expand Up @@ -528,10 +530,10 @@ pub const Buffer = struct {
return @ptrCast(c.hb_buffer_get_glyph_infos(@ptrCast(self.handle), &length)[0..length]);
}

pub fn getGlyphPositions(self: Buffer) ?[]Position {
pub fn getGlyphPositions(self: Buffer) ?[]GlyphPosition {
var length: u32 = 0;
return if (c.hb_buffer_get_glyph_positions(@ptrCast(self.handle), &length)) |positions|
@as([*]Position, @ptrCast(positions))[0..length]
@as([*]GlyphPosition, @ptrCast(positions))[0..length]
else
null;
}
Expand Down Expand Up @@ -608,11 +610,11 @@ pub const Face = struct {
c.hb_face_destroy(self.handle);
}

pub fn getGlyphcount(self: Face) u32 {
pub fn getGlyphCount(self: Face) u32 {
return c.hb_face_get_glyph_count(self.handle);
}

pub fn setGlyphcount(self: Face, count: u32) void {
pub fn setGlyphCount(self: Face, count: u32) void {
return c.hb_face_set_glyph_count(self.handle, count);
}

Expand Down Expand Up @@ -671,6 +673,16 @@ pub const Feature = extern struct {
pub const Font = struct {
handle: *c.hb_font_t,

// Font-wide extent values, measured in font units.
//
// .ascender: The height of typographic ascenders.
// .descender: The depth of typographic descenders.
// .line_gap: The suggested line-spacing gap.
//
// Note that typically .ascender is positive and .descender negative, in coordinate systems that
// grow up.
pub const Extents = c.hb_font_extents_t;

pub fn init(face: Face) Font {
return .{ .handle = c.hb_font_create(face.handle).? };
}
Expand Down Expand Up @@ -717,26 +729,298 @@ pub const Font = struct {
return Font{ .handle = c.hb_font_get_parent(self.handle) orelse return null };
}

pub fn setFace(self: Font, face: Face) void {
return c.hb_font_set_face(self.handle, face.handle);
}

pub fn Funcs(
comptime Context: type,
comptime FontData: type,
) type {
return struct {
handle: *c.hb_font_funcs_t,

const F = @This();

pub fn init(
comptime general: struct {
get_nominal_glyph: ?fn (
font: Font,
font_data: *FontData,
unicode: u21,
out_glyph: *u32,
ctx: *Context,
) bool,
get_nominal_glyphs: ?fn (
font: Font,
font_data: *FontData,
count: u32,
first_unicode: [*]const u32,
unicode_stride: u32,
first_glyph: [*]const u32,
glyph_stride: u32,
ctx: *Context,
) u32,
get_variation_glyph: ?fn (
font: Font,
font_data: *FontData,
unicode: u21,
variation_selector: u21,
out_glyph: *u32,
ctx: *Context,
) bool,
get_font_h_extents: ?fn (
font: Font,
font_data: *FontData,
out_metrics: *Font.Extents,
ctx: *Context,
) bool,
get_glyph_h_advances: ?fn (
font: Font,
font_data: *FontData,
count: u32,
first_glyph: [*]const u32,
glyph_stride: u32,
out_first_advance: [*]i32,
advance_stride: u32,
ctx: *Context,
) void,
},
) ?F {
const handle = c.hb_font_funcs_create() orelse return null;

const HB_NO_VERTICAL = false;
_ = HB_NO_VERTICAL;
const HB_NO_OT_SHAPE_FALLBACK = false;
_ = HB_NO_OT_SHAPE_FALLBACK;
const HB_NO_DRAW = false;
_ = HB_NO_DRAW;
const HB_NO_PAINT = false;
_ = HB_NO_PAINT;

if (general.get_nominal_glyph) |callback| c.hb_font_funcs_set_nominal_glyph_func(handle, (struct {
pub fn cCallback(
font: ?*c.hb_font_t,
font_data: ?*anyopaque,
unicode: c.hb_codepoint_t,
out_glyph: [*c]c.hb_codepoint_t,
user_data: ?*anyopaque,
) callconv(.C) c.hb_bool_t {
return if (callback(
Font{ .handle = font.? },
@ptrCast(font_data),
@intCast(unicode),
@ptrCast(out_glyph),
@ptrCast(user_data.?),
)) 1 else 0;
}
}).cCallback, null, null);

if (general.get_nominal_glyphs) |callback| c.hb_font_funcs_set_nominal_glyphs_func(handle, (struct {
pub fn cCallback(
font: ?*c.hb_font_t,
font_data: ?*anyopaque,
count: c_uint,
first_unicode: [*c]const c.hb_codepoint_t,
unicode_stride: u32,
first_glyph: [*c]const c.hb_codepoint_t,
glyph_stride: u32,
user_data: ?*anyopaque,
) callconv(.C) c_uint {
return callback(
Font{ .handle = font.? },
@ptrCast(font_data),
count,
first_unicode,
unicode_stride,
first_glyph,
glyph_stride,
@ptrCast(user_data.?),
);
}
}).cCallback, null, null);

if (general.get_variation_glyph) |callback| c.hb_font_funcs_set_variation_glyph_func(handle, (struct {
pub fn cCallback(
font: ?*c.hb_font_t,
font_data: ?*anyopaque,
unicode: c.hb_codepoint_t,
variation_selector: c.hb_codepoint_t,
out_glyph: [*c]c.hb_codepoint_t,
user_data: ?*anyopaque,
) callconv(.C) c.hb_bool_t {
return if (callback(
Font{ .handle = font.? },
@ptrCast(font_data),
@intCast(unicode),
@intCast(variation_selector),
@ptrCast(out_glyph),
@ptrCast(user_data.?),
)) 1 else 0;
}
}).cCallback, null, null);

if (general.get_font_h_extents) |callback| c.hb_font_funcs_set_font_h_extents_func(handle, (struct {
pub fn cCallback(
font: ?*c.hb_font_t,
font_data: ?*anyopaque,
out_metrics: [*c]Font.Extents,
user_data: ?*anyopaque,
) callconv(.C) c.hb_bool_t {
return if (callback(
Font{ .handle = font.? },
@ptrCast(font_data),
@ptrCast(out_metrics),
@ptrCast(user_data.?),
)) 1 else 0;
}
}).cCallback, null, null);

if (general.get_glyph_h_advances) |callback| c.hb_font_funcs_set_glyph_h_advances_func(handle, (struct {
pub fn cCallback(
font: ?*c.hb_font_t,
font_data: ?*anyopaque,
count: c_uint,
first_glyph: [*c]const c.hb_codepoint_t,
glyph_stride: u32,
out_first_advance: [*c]i32,
advance_stride: u32,
user_data: ?*anyopaque,
) callconv(.C) void {
return callback(
Font{ .handle = font.? },
@ptrCast(font_data),
count,
first_glyph,
glyph_stride,
out_first_advance,
advance_stride,
@ptrCast(user_data.?),
);
}
}).cCallback, null, null);

// #ifndef HB_NO_VERTICAL
// //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
// hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
// hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
// #endif

// #ifndef HB_NO_OT_SHAPE_FALLBACK
// hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
// #endif
// hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
// hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
// hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
// hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);

// #ifndef HB_NO_DRAW
// hb_font_funcs_set_draw_glyph_func (funcs, hb_ft_draw_glyph, nullptr, nullptr);
// #endif

// #ifndef HB_NO_PAINT
// #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
// hb_font_funcs_set_paint_glyph_func (funcs, hb_ft_paint_glyph, nullptr, nullptr);
// #endif
// #endif

c.hb_font_funcs_make_immutable(handle);

return F{
.handle = handle,
};
}

pub fn reference(f: F) F {
return .{
.handle = c.hb_font_funcs_reference(f.handle).?,
};
}

pub fn deinit(f: F) void {
c.hb_font_funcs_destroy(f.handle);
}
};
}

// funcs type: Funcs(Context, FontData)
pub fn setFuncs(
self: Font,
comptime Context: type,
comptime FontData: type,
ctx: *Context,
funcs: Funcs(Context, FontData),
destroy: fn (font_data: *FontData) void,
) void {
return c.hb_font_set_funcs(
self.handle,
funcs.handle,
ctx,
(struct {
pub fn cCallback(font_data: ?*anyopaque) callconv(.C) void {
destroy(@ptrCast(font_data));
}
}).cCallback,
);
}

pub fn setScale(self: Font, x_scale: i32, y_scale: i32) void {
c.hb_font_set_scale(self.handle, x_scale, y_scale);
}

pub fn getScale(self: Font) @Vector(2, i32) {
var x: c_int = 0;
var y: c_int = 0;
c.hb_font_get_scale(self.handle, &x, &y);
return .{ @intCast(x), @intCast(y) };
}

// A zero value means "no hinting in that direction"
pub fn setPPEM(self: Font, x: u32, y: u32) void {
c.hb_font_set_ppem(self.handle, x, y);
}

pub fn getPPEM(self: Font) @Vector(2, u32) {
var x: c_uint = 0;
var y: c_uint = 0;
c.hb_font_get_ppem(self.handle, &x, &y);
return .{ @intCast(x), @intCast(y) };
}

// Point size per EM. Used for optical-sizing in CoreText
// A value of zero means "not set".
pub fn setPTEM(self: Font, ptem: f32) void {
c.hb_font_set_ptem(self.handle, ptem);
}

pub fn getPTEM(self: Font) f32 {
return c.hb_font_get_ptem(self.handle);
}

pub fn getScale(self: Font) @Vector(2, i32) {
var x: c_int = 0;
var y: c_int = 0;
c.hb_font_get_scale(self.handle, &x, &y);
return .{ @intCast(x), @intCast(y) };
const SyntheticBold = struct {
x_embolden: f32,
y_embolden: f32,
in_place: bool,
};

pub fn setSyntheticBold(self: Font, v: SyntheticBold) void {
c.hb_font_set_synthetic_bold(self.handle, v.x_embolden, v.y_embolden, v.in_place);
}

pub fn setFace(self: Font, face: Face) void {
return c.hb_font_set_face(self.handle, face.handle);
pub fn getSyntheticBold(self: Font) SyntheticBold {
var v: SyntheticBold = undefined;
var in_place: c.hb_bool_t = undefined;
c.hb_font_get_synthetic_bold(self.handle, &v.x_embolden, &v.y_embolden, &in_place);
v.in_place = in_place > 0;
return v;
}

pub fn setSyntheticSlant(self: Font, slant: f32) void {
c.hb_font_set_synthetic_slant(self.handle, slant);
}

pub fn getSyntheticSlant(self: Font) f32 {
return c.hb_font_get_synthetic_slant(self.handle);
}

pub fn shape(self: Font, buf: Buffer, features: ?[]const Feature) void {
Expand Down Expand Up @@ -1004,6 +1288,6 @@ fn matchStructs(comptime A: type, comptime B: type) !void {
}

test "structs" {
try matchStructs(Position, c.hb_glyph_position_t);
try matchStructs(GlyphPosition, c.hb_glyph_position_t);
try matchStructs(GlyphInfo, c.hb_glyph_info_t);
}

0 comments on commit 90b353a

Please sign in to comment.