272 lines
7.4 KiB
Zig
272 lines
7.4 KiB
Zig
const std = @import("std");
|
|
const c = @import("c.zig");
|
|
const types = @import("types.zig");
|
|
const GlyphSlot = @import("GlyphSlot.zig");
|
|
const Library = @import("Library.zig");
|
|
const Error = @import("error.zig").Error;
|
|
const intToError = @import("error.zig").intToError;
|
|
const utils = @import("utils.zig");
|
|
|
|
const Face = @This();
|
|
|
|
pub const SizeMetrics = extern struct {
|
|
x_ppem: u16,
|
|
y_ppem: u16,
|
|
x_scale: c_long,
|
|
y_scale: c_long,
|
|
ascender: c_long,
|
|
descender: c_long,
|
|
height: c_long,
|
|
max_advance: c_long,
|
|
};
|
|
pub const KerningMode = enum(u2) {
|
|
default = c.FT_KERNING_DEFAULT,
|
|
unfitted = c.FT_KERNING_UNFITTED,
|
|
unscaled = c.FT_KERNING_UNSCALED,
|
|
};
|
|
pub const LoadFlags = packed struct {
|
|
no_scale: bool = false,
|
|
no_hinting: bool = false,
|
|
render: bool = false,
|
|
no_bitmap: bool = false,
|
|
vertical_layout: bool = false,
|
|
force_autohint: bool = false,
|
|
crop_bitmap: bool = false,
|
|
pedantic: bool = false,
|
|
ignore_global_advance_with: bool = false,
|
|
no_recurse: bool = false,
|
|
ignore_transform: bool = false,
|
|
monochrome: bool = false,
|
|
linear_design: bool = false,
|
|
no_autohint: bool = false,
|
|
target_normal: bool = false,
|
|
target_light: bool = false,
|
|
target_mono: bool = false,
|
|
target_lcd: bool = false,
|
|
target_lcd_v: bool = false,
|
|
color: bool = false,
|
|
|
|
pub const Flag = enum(u21) {
|
|
no_scale = c.FT_LOAD_NO_SCALE,
|
|
no_hinting = c.FT_LOAD_NO_HINTING,
|
|
render = c.FT_LOAD_RENDER,
|
|
no_bitmap = c.FT_LOAD_NO_BITMAP,
|
|
vertical_layout = c.FT_LOAD_VERTICAL_LAYOUT,
|
|
force_autohint = c.FT_LOAD_FORCE_AUTOHINT,
|
|
crop_bitmap = c.FT_LOAD_CROP_BITMAP,
|
|
pedantic = c.FT_LOAD_PEDANTIC,
|
|
ignore_global_advance_with = c.FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH,
|
|
no_recurse = c.FT_LOAD_NO_RECURSE,
|
|
ignore_transform = c.FT_LOAD_IGNORE_TRANSFORM,
|
|
monochrome = c.FT_LOAD_MONOCHROME,
|
|
linear_design = c.FT_LOAD_LINEAR_DESIGN,
|
|
no_autohint = c.FT_LOAD_NO_AUTOHINT,
|
|
target_normal = c.FT_LOAD_TARGET_NORMAL,
|
|
target_light = c.FT_LOAD_TARGET_LIGHT,
|
|
target_mono = c.FT_LOAD_TARGET_MONO,
|
|
target_lcd = c.FT_LOAD_TARGET_LCD,
|
|
target_lcd_v = c.FT_LOAD_TARGET_LCD_V,
|
|
color = c.FT_LOAD_COLOR,
|
|
};
|
|
|
|
pub fn toBitFields(flags: LoadFlags) u21 {
|
|
return utils.structToBitFields(u21, Flag, flags);
|
|
}
|
|
};
|
|
pub const StyleFlags = packed struct {
|
|
bold: bool = false,
|
|
italic: bool = false,
|
|
|
|
pub const Flag = enum(u2) {
|
|
bold = c.FT_STYLE_FLAG_BOLD,
|
|
italic = c.FT_STYLE_FLAG_ITALIC,
|
|
};
|
|
|
|
pub fn toBitFields(flags: StyleFlags) u2 {
|
|
return utils.structToBitFields(u2, StyleFlags, Flag, flags);
|
|
}
|
|
};
|
|
|
|
handle: c.FT_Face,
|
|
glyph: GlyphSlot,
|
|
|
|
pub fn init(handle: c.FT_Face) Face {
|
|
return Face{
|
|
.handle = handle,
|
|
.glyph = GlyphSlot.init(handle.*.glyph),
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: Face) void {
|
|
intToError(c.FT_Done_Face(self.handle)) catch |err| {
|
|
std.log.err("mach/freetype: Failed to destroy Face: {}", .{err});
|
|
};
|
|
}
|
|
|
|
pub fn attachFile(self: Face, path: []const u8) Error!void {
|
|
return self.attachStream(.{
|
|
.flags = .{ .path = true },
|
|
.data = .{ .path = path },
|
|
});
|
|
}
|
|
|
|
pub fn attachMemory(self: Face, bytes: []const u8) Error!void {
|
|
return self.attachStream(.{
|
|
.flags = .{ .memory = true },
|
|
.data = .{ .memory = bytes },
|
|
});
|
|
}
|
|
|
|
pub fn attachStream(self: Face, args: types.OpenArgs) Error!void {
|
|
return intToError(c.FT_Attach_Stream(self.handle, &args.toCInterface()));
|
|
}
|
|
|
|
pub fn setCharSize(self: Face, pt_width: i32, pt_height: i32, horz_resolution: u16, vert_resolution: u16) Error!void {
|
|
return intToError(c.FT_Set_Char_Size(self.handle, pt_width, pt_height, horz_resolution, vert_resolution));
|
|
}
|
|
|
|
pub fn setPixelSizes(self: Face, pixel_width: u32, pixel_height: u32) Error!void {
|
|
return intToError(c.FT_Set_Pixel_Sizes(self.handle, pixel_width, pixel_height));
|
|
}
|
|
|
|
pub fn loadGlyph(self: Face, index: u32, flags: LoadFlags) Error!void {
|
|
return intToError(c.FT_Load_Glyph(self.handle, index, flags.toBitFields()));
|
|
}
|
|
|
|
pub fn loadChar(self: Face, char: u32, flags: LoadFlags) Error!void {
|
|
return intToError(c.FT_Load_Char(self.handle, char, flags.toBitFields()));
|
|
}
|
|
|
|
pub fn setTransform(self: Face, matrix: ?types.Matrix, delta: ?types.Vector) Error!void {
|
|
var m = matrix orelse std.mem.zeroes(types.Matrix);
|
|
var d = delta orelse std.mem.zeroes(types.Vector);
|
|
return c.FT_Set_Transform(self.handle, @ptrCast(*c.FT_Matrix, &m), @ptrCast(*c.FT_Vector, &d));
|
|
}
|
|
|
|
pub fn getCharIndex(self: Face, index: u32) ?u32 {
|
|
const i = c.FT_Get_Char_Index(self.handle, index);
|
|
return if (i == 0) null else i;
|
|
}
|
|
|
|
pub fn getKerning(self: Face, left_char_index: u32, right_char_index: u32, mode: KerningMode) Error!types.Vector {
|
|
var vec = std.mem.zeroes(types.Vector);
|
|
try intToError(c.FT_Get_Kerning(self.handle, left_char_index, right_char_index, @enumToInt(mode), @ptrCast(*c.FT_Vector, &vec)));
|
|
return vec;
|
|
}
|
|
|
|
pub fn hasHorizontal(self: Face) bool {
|
|
return c.FT_HAS_HORIZONTAL(self.handle);
|
|
}
|
|
|
|
pub fn hasVertical(self: Face) bool {
|
|
return c.FT_HAS_VERTICAL(self.handle);
|
|
}
|
|
|
|
pub fn hasKerning(self: Face) bool {
|
|
return c.FT_HAS_KERNING(self.handle);
|
|
}
|
|
|
|
pub fn hasFixedSizes(self: Face) bool {
|
|
return c.FT_HAS_FIXED_SIZES(self.handle);
|
|
}
|
|
|
|
pub fn hasGlyphNames(self: Face) bool {
|
|
return c.FT_HAS_GLYPH_NAMES(self.handle);
|
|
}
|
|
|
|
pub fn hasColor(self: Face) bool {
|
|
return c.FT_HAS_COLOR(self.handle);
|
|
}
|
|
|
|
pub fn isScalable(self: Face) bool {
|
|
return c.FT_IS_SCALABLE(self.handle);
|
|
}
|
|
|
|
pub fn isSfnt(self: Face) bool {
|
|
return c.FT_IS_SFNT(self.handle);
|
|
}
|
|
|
|
pub fn isFixedWidth(self: Face) bool {
|
|
return c.FT_IS_FIXED_WIDTH(self.handle);
|
|
}
|
|
|
|
pub fn isCidKeyed(self: Face) bool {
|
|
return c.FT_IS_CID_KEYED(self.handle);
|
|
}
|
|
|
|
pub fn isTricky(self: Face) bool {
|
|
return c.FT_IS_TRICKY(self.handle);
|
|
}
|
|
|
|
pub fn ascender(self: Face) i16 {
|
|
return self.handle.*.ascender;
|
|
}
|
|
|
|
pub fn descender(self: Face) i16 {
|
|
return self.handle.*.descender;
|
|
}
|
|
|
|
pub fn emSize(self: Face) u16 {
|
|
return self.handle.*.units_per_EM;
|
|
}
|
|
|
|
pub fn height(self: Face) i16 {
|
|
return self.handle.*.height;
|
|
}
|
|
|
|
pub fn maxAdvanceWidth(self: Face) i16 {
|
|
return self.handle.*.max_advance_width;
|
|
}
|
|
|
|
pub fn maxAdvanceHeight(self: Face) i16 {
|
|
return self.handle.*.max_advance_height;
|
|
}
|
|
|
|
pub fn underlinePosition(self: Face) i16 {
|
|
return self.handle.*.underline_position;
|
|
}
|
|
|
|
pub fn underlineThickness(self: Face) i16 {
|
|
return self.handle.*.underline_thickness;
|
|
}
|
|
|
|
pub fn numFaces(self: Face) i64 {
|
|
return self.handle.*.num_faces;
|
|
}
|
|
|
|
pub fn numGlyphs(self: Face) i64 {
|
|
return self.handle.*.num_glyphs;
|
|
}
|
|
|
|
pub fn familyName(self: Face) ?[:0]const u8 {
|
|
return if (self.handle.*.family_name) |family|
|
|
std.mem.span(family)
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn styleName(self: Face) ?[:0]const u8 {
|
|
return if (self.handle.*.style_name) |style_name|
|
|
std.mem.span(style_name)
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn styleFlags(self: Face) StyleFlags {
|
|
const flags = self.handle.*.style_flags;
|
|
return utils.bitFieldsToStruct(StyleFlags, StyleFlags.Flag, flags);
|
|
}
|
|
|
|
pub fn sizeMetrics(self: Face) ?SizeMetrics {
|
|
return if (self.handle.*.size) |size|
|
|
@ptrCast(*SizeMetrics, &size.*.metrics).*
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn postscriptName(self: Face) ?[:0]const u8 {
|
|
return if (c.FT_Get_Postscript_Name(self.handle)) |face_name|
|
|
std.mem.span(face_name)
|
|
else
|
|
null;
|
|
}
|