freetype: initial import @ 4e2b158

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Ali Chraghi 2022-05-22 23:50:21 -07:00 committed by Stephen Gutekanst
parent 0d2675507d
commit b50dade2fd
20 changed files with 2252 additions and 0 deletions

54
freetype/src/Bitmap.zig Normal file
View file

@ -0,0 +1,54 @@
const std = @import("std");
const c = @import("c.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const Bitmap = @This();
pub const PixelMode = enum {
none,
mono,
gray,
gray2,
gray4,
lcd,
lcd_v,
bgra,
};
handle: c.FT_Bitmap,
pub fn init(handle: c.FT_Bitmap) Bitmap {
return Bitmap{ .handle = handle };
}
pub fn width(self: Bitmap) u32 {
return self.handle.width;
}
pub fn pitch(self: Bitmap) i32 {
return self.handle.pitch;
}
pub fn rows(self: Bitmap) u32 {
return self.handle.rows;
}
pub fn pixelMode(self: Bitmap) PixelMode {
return switch (self.handle.pixel_mode) {
c.FT_PIXEL_MODE_NONE => .none,
c.FT_PIXEL_MODE_MONO => .mono,
c.FT_PIXEL_MODE_GRAY => .gray,
c.FT_PIXEL_MODE_GRAY2 => .gray2,
c.FT_PIXEL_MODE_GRAY4 => .gray4,
c.FT_PIXEL_MODE_LCD => .lcd,
c.FT_PIXEL_MODE_LCD_V => .lcd_v,
c.FT_PIXEL_MODE_BGRA => .bgra,
else => unreachable,
};
}
pub fn buffer(self: Bitmap) []u8 {
const buffer_size = std.math.absCast(self.pitch()) * self.rows();
return self.handle.buffer[0..buffer_size];
}

View file

@ -0,0 +1,35 @@
const std = @import("std");
const c = @import("c.zig");
const Bitmap = @import("Bitmap.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const BitmapGlyph = @This();
handle: c.FT_BitmapGlyph,
pub fn init(handle: c.FT_BitmapGlyph) BitmapGlyph {
return BitmapGlyph{ .handle = handle };
}
pub fn deinit(self: BitmapGlyph) void {
c.FT_Done_Glyph(@ptrCast(c.FT_Glyph, self.handle));
}
pub fn clone(self: BitmapGlyph) Error!BitmapGlyph {
var res = std.mem.zeroes(c.FT_Glyph);
try convertError(c.FT_Glyph_Copy(@ptrCast(c.FT_Glyph, self.handle), &res));
return BitmapGlyph.init(@ptrCast(c.FT_BitmapGlyph, res));
}
pub fn left(self: BitmapGlyph) i32 {
return self.handle.*.left;
}
pub fn top(self: BitmapGlyph) i32 {
return self.handle.*.top;
}
pub fn bitmap(self: BitmapGlyph) Bitmap {
return Bitmap.init(self.handle.*.bitmap);
}

267
freetype/src/Face.zig Normal file
View file

@ -0,0 +1,267 @@
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 convertError = @import("error.zig").convertError;
const utils = @import("utils.zig");
const Face = @This();
pub const SizeMetrics = c.FT_Size_Metrics;
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 {
convertError(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 convertError(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 convertError(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 convertError(c.FT_Set_Pixel_Sizes(self.handle, pixel_width, pixel_height));
}
pub fn loadGlyph(self: Face, index: u32, flags: LoadFlags) Error!void {
return convertError(c.FT_Load_Glyph(self.handle, index, flags.toBitFields()));
}
pub fn loadChar(self: Face, char: u32, flags: LoadFlags) Error!void {
return convertError(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, &m, &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 convertError(c.FT_Get_Kerning(self.handle, left_char_index, right_char_index, @enumToInt(mode), &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 {
const family = self.handle.*.family_name;
return if (family == null)
null
else
std.mem.span(family);
}
pub fn styleName(self: Face) ?[:0]const u8 {
const style = self.handle.*.style_name;
return if (style == null)
null
else
std.mem.span(style);
}
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 {
const size = self.handle.*.size;
return if (size == null)
null
else
size.*.metrics;
}
pub fn postscriptName(self: Face) ?[:0]const u8 {
const face_name = c.FT_Get_Postscript_Name(self.handle);
return if (face_name == null)
null
else
std.mem.span(face_name);
}

82
freetype/src/Glyph.zig Normal file
View file

@ -0,0 +1,82 @@
const std = @import("std");
const c = @import("c.zig");
const BitmapGlyph = @import("BitmapGlyph.zig");
const Stroker = @import("Stroker.zig");
const types = @import("types.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const Glyph = @This();
pub const BBox = c.FT_BBox;
pub const RenderMode = enum(u3) {
normal = c.FT_RENDER_MODE_NORMAL,
light = c.FT_RENDER_MODE_LIGHT,
mono = c.FT_RENDER_MODE_MONO,
lcd = c.FT_RENDER_MODE_LCD,
lcd_v = c.FT_RENDER_MODE_LCD_V,
sdf = c.FT_RENDER_MODE_SDF,
};
pub const BBoxMode = enum(u2) {
// https://freetype.org/freetype2/docs/reference/ft2-glyph_management.html#ft_glyph_bbox_mode
// both `unscaled` and `subpixel` constants are set to 0
unscaled_or_subpixels = c.FT_GLYPH_BBOX_UNSCALED,
gridfit = c.FT_GLYPH_BBOX_GRIDFIT,
truncate = c.FT_GLYPH_BBOX_TRUNCATE,
pixels = c.FT_GLYPH_BBOX_PIXELS,
};
handle: c.FT_Glyph,
pub fn init(handle: c.FT_Glyph) Glyph {
return Glyph{ .handle = handle };
}
pub fn deinit(self: Glyph) void {
c.FT_Done_Glyph(self.handle);
}
pub fn clone(self: Glyph) Error!Glyph {
var res = std.mem.zeroes(c.FT_Glyph);
try convertError(c.FT_Glyph_Copy(self.handle, &res));
return Glyph.init(res);
}
pub fn transform(self: Glyph, 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);
try convertError(c.FT_Glyph_Transform(self.handle, &m, &d));
}
pub fn getCBox(self: Glyph, bbox_mode: BBoxMode) BBox {
var res = std.mem.zeroes(BBox);
c.FT_Glyph_Get_CBox(self.handle, @enumToInt(bbox_mode), &res);
return res;
}
pub fn toBitmap(self: Glyph, render_mode: RenderMode, origin: ?types.Vector) Error!BitmapGlyph {
var res = self.handle;
var o = origin orelse std.mem.zeroes(types.Vector);
try convertError(c.FT_Glyph_To_Bitmap(&res, @enumToInt(render_mode), &o, 0));
return BitmapGlyph.init(@ptrCast(c.FT_BitmapGlyph, self.handle));
}
pub fn stroke(self: Glyph, stroker: Stroker) Error!Glyph {
var res = self.handle;
try convertError(c.FT_Glyph_Stroke(&res, stroker.handle, 0));
return Glyph.init(res);
}
pub fn strokeBorder(self: Glyph, stroker: Stroker, inside: bool) Error!Glyph {
var res = self.handle;
try convertError(c.FT_Glyph_StrokeBorder(&res, stroker.handle, if (inside) 1 else 0, 0));
return Glyph.init(res);
}
pub fn advanceX(self: Glyph) isize {
return self.handle.*.advance.x;
}
pub fn advanceY(self: Glyph) isize {
return self.handle.*.advance.y;
}

View file

@ -0,0 +1,79 @@
const std = @import("std");
const c = @import("c.zig");
const types = @import("types.zig");
const Glyph = @import("Glyph.zig");
const Outline = @import("Outline.zig");
const Bitmap = @import("Bitmap.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const GlyphSlot = @This();
pub const GlyphMetrics = c.FT_Glyph_Metrics;
pub const SubGlyphInfo = struct {
index: i32,
flags: u32,
arg1: i32,
arg2: i32,
transform: types.Matrix,
};
handle: c.FT_GlyphSlot,
pub fn init(handle: c.FT_GlyphSlot) GlyphSlot {
return GlyphSlot{ .handle = handle };
}
pub fn render(self: GlyphSlot, render_mode: Glyph.RenderMode) Error!void {
return convertError(c.FT_Render_Glyph(self.handle, @enumToInt(render_mode)));
}
pub fn subGlyphInfo(self: GlyphSlot, sub_index: u32) Error!SubGlyphInfo {
var info = std.mem.zeroes(SubGlyphInfo);
try convertError(c.FT_Get_SubGlyph_Info(self.handle, sub_index, &info.index, &info.flags, &info.arg1, &info.arg2, &info.transform));
return info;
}
pub fn glyph(self: GlyphSlot) Error!Glyph {
var out = std.mem.zeroes(c.FT_Glyph);
try convertError(c.FT_Get_Glyph(self.handle, &out));
return Glyph.init(out);
}
pub fn outline(self: GlyphSlot) ?Outline {
const out = self.handle.*.outline;
const format = self.handle.*.format;
return if (format == c.FT_GLYPH_FORMAT_OUTLINE)
Outline.init(out)
else
null;
}
pub fn bitmap(self: GlyphSlot) Bitmap {
return Bitmap.init(self.handle.*.bitmap);
}
pub fn bitmapLeft(self: GlyphSlot) i32 {
return self.handle.*.bitmap_left;
}
pub fn bitmapTop(self: GlyphSlot) i32 {
return self.handle.*.bitmap_top;
}
pub fn linearHoriAdvance(self: GlyphSlot) i64 {
return self.handle.*.linearHoriAdvance;
}
pub fn linearVertAdvance(self: GlyphSlot) i64 {
return self.handle.*.linearVertAdvance;
}
pub fn advance(self: GlyphSlot) types.Vector {
return self.handle.*.advance;
}
pub fn metrics(self: GlyphSlot) GlyphMetrics {
return self.handle.*.metrics;
}

60
freetype/src/Library.zig Normal file
View file

@ -0,0 +1,60 @@
const std = @import("std");
const c = @import("c.zig");
const types = @import("types.zig");
const Face = @import("Face.zig");
const Stroker = @import("Stroker.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const Library = @This();
pub const LcdFilter = enum(u5) {
none = c.FT_LCD_FILTER_NONE,
default = c.FT_LCD_FILTER_DEFAULT,
light = c.FT_LCD_FILTER_LIGHT,
legacy = c.FT_LCD_FILTER_LEGACY,
};
handle: c.FT_Library,
pub fn init() Error!Library {
var ft = std.mem.zeroes(Library);
try convertError(c.FT_Init_FreeType(&ft.handle));
return ft;
}
pub fn deinit(self: Library) void {
convertError(c.FT_Done_FreeType(self.handle)) catch |err| {
std.log.err("mach/freetype: Failed to deinitialize Library: {}", .{err});
};
}
pub fn newFace(self: Library, path: []const u8, face_index: i32) Error!Face {
return self.openFace(.{
.flags = .{ .path = true },
.data = .{ .path = path },
}, face_index);
}
pub fn newFaceMemory(self: Library, bytes: []const u8, face_index: i32) Error!Face {
return self.openFace(.{
.flags = .{ .memory = true },
.data = .{ .memory = bytes },
}, face_index);
}
pub fn openFace(self: Library, args: types.OpenArgs, face_index: i32) Error!Face {
var face = std.mem.zeroes(c.FT_Face);
try convertError(c.FT_Open_Face(self.handle, &args.toCInterface(), face_index, &face));
return Face.init(face);
}
pub fn newStroker(self: Library) Error!Stroker {
var stroker = std.mem.zeroes(c.FT_Stroker);
try convertError(c.FT_Stroker_New(self.handle, &stroker));
return Stroker.init(stroker);
}
pub fn setLcdFilter(self: Library, lcd_filter: LcdFilter) Error!void {
return convertError(c.FT_Library_SetLcdFilter(self.handle, @enumToInt(lcd_filter)));
}

22
freetype/src/Outline.zig Normal file
View file

@ -0,0 +1,22 @@
const c = @import("c.zig");
const types = @import("types.zig");
const Outline = @This();
handle: c.FT_Outline,
pub fn init(handle: c.FT_Outline) Outline {
return Outline{ .handle = handle };
}
pub fn points(self: Outline) []const types.Vector {
return self.handle.points[0..@intCast(u15, self.handle.n_points)];
}
pub fn tags(self: Outline) []const u8 {
return self.handle.tags[0..@intCast(u15, self.handle.n_points)];
}
pub fn contours(self: Outline) []const i16 {
return self.handle.contours[0..@intCast(u15, self.handle.n_contours)];
}

32
freetype/src/Stroker.zig Normal file
View file

@ -0,0 +1,32 @@
const c = @import("c.zig");
const Error = @import("error.zig").Error;
const convertError = @import("error.zig").convertError;
const Stroker = @This();
pub const StrokerLineCap = enum(u2) {
butt = c.FT_STROKER_LINECAP_BUTT,
round = c.FT_STROKER_LINECAP_ROUND,
square = c.FT_STROKER_LINECAP_SQUARE,
};
pub const StrokerLineJoin = enum(u2) {
round = c.FT_STROKER_LINEJOIN_ROUND,
bevel = c.FT_STROKER_LINEJOIN_BEVEL,
miterVariable = c.FT_STROKER_LINEJOIN_MITER_VARIABLE,
miterFixed = c.FT_STROKER_LINEJOIN_MITER_FIXED,
};
handle: c.FT_Stroker,
pub fn init(handle: c.FT_Stroker) Stroker {
return Stroker{ .handle = handle };
}
pub fn set(self: Stroker, radius: i32, line_cap: StrokerLineCap, line_join: StrokerLineJoin, miter_limit: i32) void {
c.FT_Stroker_Set(self.handle, radius, @enumToInt(line_cap), @enumToInt(line_join), miter_limit);
}
pub fn deinit(self: Stroker) void {
c.FT_Stroker_Done(self.handle);
}

8
freetype/src/c.zig Normal file
View file

@ -0,0 +1,8 @@
pub usingnamespace @cImport({
@cInclude("freetype/freetype.h");
@cInclude("freetype/ftlcdfil.h");
@cInclude("freetype/ftmodapi.h");
@cInclude("freetype/ftstroke.h");
@cInclude("freetype/ftsystem.h");
@cInclude("ft2build.h");
});

196
freetype/src/error.zig Normal file
View file

@ -0,0 +1,196 @@
const c = @import("c.zig");
pub const Error = error{
CannotOpenResource,
UnknownFileFormat,
InvalidFileFormat,
InvalidVersion,
LowerModuleVersion,
InvalidArgument,
UnimplementedFeature,
InvalidTable,
InvalidOffset,
ArrayTooLarge,
MissingModule,
MissingProperty,
InvalidGlyphIndex,
InvalidCharacterCode,
InvalidGlyphFormat,
CannotRenderGlyph,
InvalidOutline,
InvalidComposite,
TooManyHints,
InvalidPixelSize,
InvalidHandle,
InvalidLibraryHandle,
InvalidDriverHandle,
InvalidFaceHandle,
InvalidSizeHandle,
InvalidSlotHandle,
InvalidCharMapHandle,
InvalidCacheHandle,
InvalidStreamHandle,
TooManyDrivers,
TooManyExtensions,
OutOfMemory,
UnlistedObject,
CannotOpenStream,
InvalidStreamSeek,
InvalidStreamSkip,
InvalidStreamRead,
InvalidStreamOperation,
InvalidFrameOperation,
NestedFrameAccess,
InvalidFrameRead,
RasterUninitialized,
RasterCorrupted,
RasterOverflow,
RasterNegativeHeight,
TooManyCaches,
InvalidOpcode,
TooFewArguments,
StackOverflow,
CodeOverflow,
BadArgument,
DivideByZero,
InvalidReference,
DebugOpCode,
ENDFInExecStream,
NestedDEFS,
InvalidCodeRange,
ExecutionTooLong,
TooManyFunctionDefs,
TooManyInstructionDefs,
TableMissing,
HorizHeaderMissing,
LocationsMissing,
NameTableMissing,
CMapTableMissing,
HmtxTableMissing,
PostTableMissing,
InvalidHorizMetrics,
InvalidCharMapFormat,
InvalidPPem,
InvalidVertMetrics,
CouldNotFindContext,
InvalidPostTableFormat,
InvalidPostTable,
Syntax,
StackUnderflow,
Ignore,
NoUnicodeGlyphName,
MissingStartfontField,
MissingFontField,
MissingSizeField,
MissingFontboundingboxField,
MissingCharsField,
MissingStartcharField,
MissingEncodingField,
MissingBbxField,
BbxTooBig,
CorruptedFontHeader,
CorruptedFontGlyphs,
};
pub fn convertError(err: c_int) Error!void {
return switch (err) {
c.FT_Err_Ok => {},
c.FT_Err_Cannot_Open_Resource => Error.CannotOpenResource,
c.FT_Err_Unknown_File_Format => Error.UnknownFileFormat,
c.FT_Err_Invalid_File_Format => Error.InvalidFileFormat,
c.FT_Err_Invalid_Version => Error.InvalidVersion,
c.FT_Err_Lower_Module_Version => Error.LowerModuleVersion,
c.FT_Err_Invalid_Argument => Error.InvalidArgument,
c.FT_Err_Unimplemented_Feature => Error.UnimplementedFeature,
c.FT_Err_Invalid_Table => Error.InvalidTable,
c.FT_Err_Invalid_Offset => Error.InvalidOffset,
c.FT_Err_Array_Too_Large => Error.ArrayTooLarge,
c.FT_Err_Missing_Module => Error.MissingModule,
c.FT_Err_Missing_Property => Error.MissingProperty,
c.FT_Err_Invalid_Glyph_Index => Error.InvalidGlyphIndex,
c.FT_Err_Invalid_Character_Code => Error.InvalidCharacterCode,
c.FT_Err_Invalid_Glyph_Format => Error.InvalidGlyphFormat,
c.FT_Err_Cannot_Render_Glyph => Error.CannotRenderGlyph,
c.FT_Err_Invalid_Outline => Error.InvalidOutline,
c.FT_Err_Invalid_Composite => Error.InvalidComposite,
c.FT_Err_Too_Many_Hints => Error.TooManyHints,
c.FT_Err_Invalid_Pixel_Size => Error.InvalidPixelSize,
c.FT_Err_Invalid_Handle => Error.InvalidHandle,
c.FT_Err_Invalid_Library_Handle => Error.InvalidLibraryHandle,
c.FT_Err_Invalid_Driver_Handle => Error.InvalidDriverHandle,
c.FT_Err_Invalid_Face_Handle => Error.InvalidFaceHandle,
c.FT_Err_Invalid_Size_Handle => Error.InvalidSizeHandle,
c.FT_Err_Invalid_Slot_Handle => Error.InvalidSlotHandle,
c.FT_Err_Invalid_CharMap_Handle => Error.InvalidCharMapHandle,
c.FT_Err_Invalid_Cache_Handle => Error.InvalidCacheHandle,
c.FT_Err_Invalid_Stream_Handle => Error.InvalidStreamHandle,
c.FT_Err_Too_Many_Drivers => Error.TooManyDrivers,
c.FT_Err_Too_Many_Extensions => Error.TooManyExtensions,
c.FT_Err_Out_Of_Memory => Error.OutOfMemory,
c.FT_Err_Unlisted_Object => Error.UnlistedObject,
c.FT_Err_Cannot_Open_Stream => Error.CannotOpenStream,
c.FT_Err_Invalid_Stream_Seek => Error.InvalidStreamSeek,
c.FT_Err_Invalid_Stream_Skip => Error.InvalidStreamSkip,
c.FT_Err_Invalid_Stream_Read => Error.InvalidStreamRead,
c.FT_Err_Invalid_Stream_Operation => Error.InvalidStreamOperation,
c.FT_Err_Invalid_Frame_Operation => Error.InvalidFrameOperation,
c.FT_Err_Nested_Frame_Access => Error.NestedFrameAccess,
c.FT_Err_Invalid_Frame_Read => Error.InvalidFrameRead,
c.FT_Err_Raster_Uninitialized => Error.RasterUninitialized,
c.FT_Err_Raster_Corrupted => Error.RasterCorrupted,
c.FT_Err_Raster_Overflow => Error.RasterOverflow,
c.FT_Err_Raster_Negative_Height => Error.RasterNegativeHeight,
c.FT_Err_Too_Many_Caches => Error.TooManyCaches,
c.FT_Err_Invalid_Opcode => Error.InvalidOpcode,
c.FT_Err_Too_Few_Arguments => Error.TooFewArguments,
c.FT_Err_Stack_Overflow => Error.StackOverflow,
c.FT_Err_Code_Overflow => Error.CodeOverflow,
c.FT_Err_Bad_Argument => Error.BadArgument,
c.FT_Err_Divide_By_Zero => Error.DivideByZero,
c.FT_Err_Invalid_Reference => Error.InvalidReference,
c.FT_Err_Debug_OpCode => Error.DebugOpCode,
c.FT_Err_ENDF_In_Exec_Stream => Error.ENDFInExecStream,
c.FT_Err_Nested_DEFS => Error.NestedDEFS,
c.FT_Err_Invalid_CodeRange => Error.InvalidCodeRange,
c.FT_Err_Execution_Too_Long => Error.ExecutionTooLong,
c.FT_Err_Too_Many_Function_Defs => Error.TooManyFunctionDefs,
c.FT_Err_Too_Many_Instruction_Defs => Error.TooManyInstructionDefs,
c.FT_Err_Table_Missing => Error.TableMissing,
c.FT_Err_Horiz_Header_Missing => Error.HorizHeaderMissing,
c.FT_Err_Locations_Missing => Error.LocationsMissing,
c.FT_Err_Name_Table_Missing => Error.NameTableMissing,
c.FT_Err_CMap_Table_Missing => Error.CMapTableMissing,
c.FT_Err_Hmtx_Table_Missing => Error.HmtxTableMissing,
c.FT_Err_Post_Table_Missing => Error.PostTableMissing,
c.FT_Err_Invalid_Horiz_Metrics => Error.InvalidHorizMetrics,
c.FT_Err_Invalid_CharMap_Format => Error.InvalidCharMapFormat,
c.FT_Err_Invalid_PPem => Error.InvalidPPem,
c.FT_Err_Invalid_Vert_Metrics => Error.InvalidVertMetrics,
c.FT_Err_Could_Not_Find_Context => Error.CouldNotFindContext,
c.FT_Err_Invalid_Post_Table_Format => Error.InvalidPostTableFormat,
c.FT_Err_Invalid_Post_Table => Error.InvalidPostTable,
c.FT_Err_Syntax_Error => Error.Syntax,
c.FT_Err_Stack_Underflow => Error.StackUnderflow,
c.FT_Err_Ignore => Error.Ignore,
c.FT_Err_No_Unicode_Glyph_Name => Error.NoUnicodeGlyphName,
c.FT_Err_Missing_Startfont_Field => Error.MissingStartfontField,
c.FT_Err_Missing_Font_Field => Error.MissingFontField,
c.FT_Err_Missing_Size_Field => Error.MissingSizeField,
c.FT_Err_Missing_Fontboundingbox_Field => Error.MissingFontboundingboxField,
c.FT_Err_Missing_Chars_Field => Error.MissingCharsField,
c.FT_Err_Missing_Startchar_Field => Error.MissingStartcharField,
c.FT_Err_Missing_Encoding_Field => Error.MissingEncodingField,
c.FT_Err_Missing_Bbx_Field => Error.MissingBbxField,
c.FT_Err_Bbx_Too_Big => Error.BbxTooBig,
c.FT_Err_Corrupted_Font_Header => Error.CorruptedFontHeader,
c.FT_Err_Corrupted_Font_Glyphs => Error.CorruptedFontGlyphs,
else => unreachable,
};
}
test "error convertion" {
const expectError = @import("std").testing.expectError;
try convertError(c.FT_Err_Ok);
try expectError(Error.OutOfMemory, convertError(c.FT_Err_Out_Of_Memory));
}

26
freetype/src/main.zig Normal file
View file

@ -0,0 +1,26 @@
pub const Library = @import("Library.zig");
pub const Face = @import("Face.zig");
pub const GlyphSlot = @import("GlyphSlot.zig");
pub const Glyph = @import("Glyph.zig");
pub const BitmapGlyph = @import("BitmapGlyph.zig");
pub const Bitmap = @import("Bitmap.zig");
pub const Outline = @import("Outline.zig");
pub const Stroker = @import("Stroker.zig");
pub const Error = @import("error.zig").Error;
pub const C = @import("c.zig");
pub usingnamespace @import("types.zig");
test {
const refAllDecls = @import("std").testing.refAllDecls;
refAllDecls(@import("Library.zig"));
refAllDecls(@import("Face.zig"));
refAllDecls(@import("GlyphSlot.zig"));
refAllDecls(@import("Glyph.zig"));
refAllDecls(@import("BitmapGlyph.zig"));
refAllDecls(@import("Bitmap.zig"));
refAllDecls(@import("Outline.zig"));
refAllDecls(@import("Stroker.zig"));
refAllDecls(@import("types.zig"));
refAllDecls(@import("error.zig"));
refAllDecls(@import("utils.zig"));
}

56
freetype/src/types.zig Normal file
View file

@ -0,0 +1,56 @@
const std = @import("std");
const c = @import("c.zig");
const utils = @import("utils.zig");
pub const Vector = c.FT_Vector;
pub const Matrix = c.FT_Matrix;
pub const OpenFlags = packed struct {
memory: bool = false,
stream: bool = false,
path: bool = false,
driver: bool = false,
params: bool = false,
pub const Flag = enum(u5) {
memory = c.FT_OPEN_MEMORY,
stream = c.FT_OPEN_STREAM,
path = c.FT_OPEN_PATHNAME,
driver = c.FT_OPEN_DRIVER,
params = c.FT_OPEN_PARAMS,
};
pub fn toBitFields(flags: OpenFlags) u5 {
return utils.structToBitFields(u5, Flag, flags);
}
};
pub const OpenArgs = struct {
flags: OpenFlags,
data: union(enum) {
memory: []const u8,
path: []const u8,
stream: c.FT_Stream,
driver: c.FT_Module,
params: []const c.FT_Parameter,
},
pub fn toCInterface(self: OpenArgs) c.FT_Open_Args {
var oa = std.mem.zeroes(c.FT_Open_Args);
oa.flags = self.flags.toBitFields();
switch (self.data) {
.memory => |d| {
oa.memory_base = d.ptr;
oa.memory_size = @truncate(u31, d.len);
},
.path => |*d| oa.pathname = @intToPtr(*u8, @ptrToInt(d.ptr)),
.stream => |d| oa.stream = d,
.driver => |d| oa.driver = d,
.params => |*d| {
oa.params = @intToPtr(*c.FT_Parameter, @ptrToInt(d.ptr));
oa.num_params = @intCast(u31, d.len);
},
}
return oa;
}
};

48
freetype/src/utils.zig Normal file
View file

@ -0,0 +1,48 @@
const std = @import("std");
const meta = std.meta;
const mem = std.mem;
const testing = std.testing;
pub fn structToBitFields(comptime IntType: type, comptime EnumDataType: type, flags: anytype) IntType {
var value: IntType = 0;
inline for (comptime meta.fieldNames(EnumDataType)) |field_name| {
if (@field(flags, field_name)) {
value |= @enumToInt(@field(EnumDataType, field_name));
}
}
return value;
}
pub fn bitFieldsToStruct(comptime StructType: type, comptime EnumDataType: type, flags: anytype) StructType {
var value = mem.zeroes(StructType);
inline for (comptime meta.fieldNames(EnumDataType)) |field_name| {
if (flags & (@enumToInt(@field(EnumDataType, field_name))) != 0) {
@field(value, field_name) = true;
}
}
return value;
}
const TestEnum = enum(u16) {
filed_1 = (1 << 1),
filed_2 = (1 << 2),
filed_3 = (1 << 3),
};
const TestStruct = packed struct {
filed_1: bool = false,
filed_2: bool = false,
filed_3: bool = false,
};
test "struct fields to bit fields" {
try testing.expectEqual(@as(u16, (1 << 1) | (1 << 3)), structToBitFields(u16, TestEnum, TestStruct{
.filed_1 = true,
.filed_3 = true,
}));
try testing.expectEqual(@as(u16, 0), structToBitFields(u16, TestEnum, TestStruct{}));
}
test "bit fields to struct" {
try testing.expectEqual(TestStruct{ .filed_1 = true, .filed_2 = true, .filed_3 = false }, bitFieldsToStruct(TestStruct, TestEnum, (1 << 1) | (1 << 2)));
}