font/freetype: API to load font table

This commit is contained in:
Mitchell Hashimoto
2024-05-28 09:48:01 -07:00
parent 9f885ff64f
commit 8920f45fd8
4 changed files with 66 additions and 0 deletions

View File

@ -1,7 +1,9 @@
const std = @import("std"); const std = @import("std");
const Allocator = std.mem.Allocator;
const c = @import("c.zig"); const c = @import("c.zig");
const errors = @import("errors.zig"); const errors = @import("errors.zig");
const Library = @import("Library.zig"); const Library = @import("Library.zig");
const Tag = @import("tag.zig").Tag;
const Error = errors.Error; const Error = errors.Error;
const intToError = errors.intToError; const intToError = errors.intToError;
@ -102,6 +104,31 @@ pub const Face = struct {
return if (intToError(res)) |_| name else |err| err; return if (intToError(res)) |_| name else |err| err;
} }
/// Load any SFNT font table into client memory.
pub fn loadSfntTable(
self: Face,
alloc: Allocator,
tag: Tag,
) (Allocator.Error || Error)!?[]u8 {
const tag_u64: u64 = @intCast(@as(u32, @bitCast(tag)));
// Get the length of the table in bytes
var len: c_ulong = 0;
var res = c.FT_Load_Sfnt_Table(self.handle, tag_u64, 0, null, &len);
_ = intToError(res) catch |err| return err;
// If our length is zero we don't have a table.
if (len == 0) return null;
// Allocate a buffer to hold the table and load it
const buf = try alloc.alloc(u8, len);
errdefer alloc.free(buf);
res = c.FT_Load_Sfnt_Table(self.handle, tag_u64, 0, buf.ptr, &len);
_ = intToError(res) catch |err| return err;
return buf;
}
/// Retrieve the font variation descriptor for a font. /// Retrieve the font variation descriptor for a font.
pub fn getMMVar(self: Face) Error!*c.FT_MM_Var { pub fn getMMVar(self: Face) Error!*c.FT_MM_Var {
var result: *c.FT_MM_Var = undefined; var result: *c.FT_MM_Var = undefined;

View File

@ -4,6 +4,7 @@ pub const Library = @import("Library.zig");
pub usingnamespace @import("computations.zig"); pub usingnamespace @import("computations.zig");
pub usingnamespace @import("errors.zig"); pub usingnamespace @import("errors.zig");
pub usingnamespace @import("face.zig"); pub usingnamespace @import("face.zig");
pub usingnamespace @import("tag.zig");
test { test {
@import("std").testing.refAllDecls(@This()); @import("std").testing.refAllDecls(@This());

17
pkg/freetype/tag.zig Normal file
View File

@ -0,0 +1,17 @@
/// FT_Tag
pub const Tag = packed struct(u32) {
d: u8,
c: u8,
b: u8,
a: u8,
pub fn init(v: *const [4]u8) Tag {
return .{ .a = v[0], .b = v[1], .c = v[2], .d = v[3] };
}
/// Converts the ID to a string. The return value is only valid
/// for the lifetime of the self pointer.
pub fn str(self: Tag) [4]u8 {
return .{ self.a, self.b, self.c, self.d };
}
};

View File

@ -631,6 +631,11 @@ pub const Face = struct {
const div = @as(f32, @floatFromInt(mul)) / 64; const div = @as(f32, @floatFromInt(mul)) / 64;
return @ceil(div); return @ceil(div);
} }
/// Copy the font table data for the given tag.
pub fn copyTable(self: Face, alloc: Allocator, tag: *const [4]u8) !?[]u8 {
return try self.face.loadSfntTable(alloc, freetype.Tag.init(tag));
}
}; };
test { test {
@ -763,3 +768,19 @@ test "mono to rgba" {
// glyph 3 is mono in Noto // glyph 3 is mono in Noto
_ = try ft_font.renderGlyph(alloc, &atlas, 3, .{}); _ = try ft_font.renderGlyph(alloc, &atlas, 3, .{});
} }
test "svg font table" {
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontJuliaMono;
var lib = try font.Library.init();
defer lib.deinit();
var face = try Face.init(lib, testFont, .{ .size = .{ .points = 12 } });
defer face.deinit();
const table = (try face.copyTable(alloc, "SVG ")).?;
defer alloc.free(table);
try testing.expectEqual(430, table.len);
}