1909 lines
63 KiB
Zig
1909 lines
63 KiB
Zig
pub const c = @cImport({
|
|
@cInclude("freetype/ftadvanc.h");
|
|
@cInclude("freetype/ftbbox.h");
|
|
@cInclude("freetype/ftbitmap.h");
|
|
@cInclude("freetype/ftcolor.h");
|
|
@cInclude("freetype/ftlcdfil.h");
|
|
@cInclude("freetype/ftsizes.h");
|
|
@cInclude("freetype/ftstroke.h");
|
|
@cInclude("freetype/fttrigon.h");
|
|
@cInclude("freetype/ftsynth.h");
|
|
});
|
|
|
|
pub const Affine23 = c.FT_Affine23;
|
|
pub const BBox = c.FT_BBox;
|
|
pub const BitmapSize = c.FT_Bitmap_Size;
|
|
pub const CharMap = c.FT_CharMapRec;
|
|
pub const ClipBox = c.FT_ClipBox;
|
|
pub const Color = c.FT_Color;
|
|
pub const ColorIndex = c.FT_ColorIndex;
|
|
pub const ColorLine = c.FT_ColorLine;
|
|
pub const ColorStop = c.FT_ColorStop;
|
|
pub const ColorStopIterator = c.FT_ColorStopIterator;
|
|
pub const Generic = c.FT_Generic;
|
|
pub const GlyphMetrics = c.FT_Glyph_Metrics;
|
|
pub const LayerIterator = c.FT_LayerIterator;
|
|
pub const Matrix = c.FT_Matrix;
|
|
pub const OpaquePaint = c.FT_OpaquePaint;
|
|
pub const PaintColrGlyph = c.FT_PaintColrGlyph;
|
|
pub const PaintColrLayers = c.FT_PaintColrLayers;
|
|
pub const PaintComposite = c.FT_PaintComposite;
|
|
pub const PaintGlyph = c.FT_PaintGlyph;
|
|
pub const PaintLinearGradient = c.FT_PaintLinearGradient;
|
|
pub const PaintRadialGradient = c.FT_PaintRadialGradient;
|
|
pub const PaintRotate = c.FT_PaintRotate;
|
|
pub const PaintScale = c.FT_PaintScale;
|
|
pub const PaintSkew = c.FT_PaintSkew;
|
|
pub const PaintSolid = c.FT_PaintSolid;
|
|
pub const PaintSweepGradient = c.FT_PaintSweepGradient;
|
|
pub const PaintTransform = c.FT_PaintTransform;
|
|
pub const PaintTranslate = c.FT_PaintTranslate;
|
|
pub const SizeMetrics = c.FT_Size_Metrics;
|
|
pub const SizeRequest = c.FT_Size_RequestRec;
|
|
pub const Span = c.FT_Span;
|
|
pub const Vector = c.FT_Vector;
|
|
|
|
pub const angle_pi = c.FT_ANGLE_PI;
|
|
pub const angle_2pi = c.FT_ANGLE_2PI;
|
|
pub const angle_pi2 = c.FT_ANGLE_PI2;
|
|
pub const angle_pi4 = c.FT_ANGLE_PI4;
|
|
|
|
pub const BBoxMode = enum(u2) {
|
|
// https://freetype.org/freetype2/docs/reference/ft2-glyph_management.html#ft_glyph_bbox_mode
|
|
// both `unscaled` and `subpixel` 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,
|
|
};
|
|
|
|
pub const Border = enum(u1) {
|
|
left,
|
|
right,
|
|
};
|
|
|
|
pub const CompositeMode = enum(u5) {
|
|
clear = c.FT_COLR_COMPOSITE_CLEAR,
|
|
src = c.FT_COLR_COMPOSITE_SRC,
|
|
dest = c.FT_COLR_COMPOSITE_DEST,
|
|
src_over = c.FT_COLR_COMPOSITE_SRC_OVER,
|
|
dest_over = c.FT_COLR_COMPOSITE_DEST_OVER,
|
|
src_in = c.FT_COLR_COMPOSITE_SRC_IN,
|
|
dest_in = c.FT_COLR_COMPOSITE_DEST_IN,
|
|
src_out = c.FT_COLR_COMPOSITE_SRC_OUT,
|
|
dest_out = c.FT_COLR_COMPOSITE_DEST_OUT,
|
|
src_atop = c.FT_COLR_COMPOSITE_SRC_ATOP,
|
|
dest_atop = c.FT_COLR_COMPOSITE_DEST_ATOP,
|
|
xor = c.FT_COLR_COMPOSITE_XOR,
|
|
plus = c.FT_COLR_COMPOSITE_PLUS,
|
|
screen = c.FT_COLR_COMPOSITE_SCREEN,
|
|
overlay = c.FT_COLR_COMPOSITE_OVERLAY,
|
|
darken = c.FT_COLR_COMPOSITE_DARKEN,
|
|
lighten = c.FT_COLR_COMPOSITE_LIGHTEN,
|
|
color_dodge = c.FT_COLR_COMPOSITE_COLOR_DODGE,
|
|
color_burn = c.FT_COLR_COMPOSITE_COLOR_BURN,
|
|
hard_light = c.FT_COLR_COMPOSITE_HARD_LIGHT,
|
|
soft_light = c.FT_COLR_COMPOSITE_SOFT_LIGHT,
|
|
difference = c.FT_COLR_COMPOSITE_DIFFERENCE,
|
|
exclusion = c.FT_COLR_COMPOSITE_EXCLUSION,
|
|
multiply = c.FT_COLR_COMPOSITE_MULTIPLY,
|
|
hsl_hue = c.FT_COLR_COMPOSITE_HSL_HUE,
|
|
hsl_saturation = c.FT_COLR_COMPOSITE_HSL_SATURATION,
|
|
hsl_color = c.FT_COLR_COMPOSITE_HSL_COLOR,
|
|
hsl_luminosity = c.FT_COLR_COMPOSITE_HSL_LUMINOSITY,
|
|
};
|
|
|
|
pub const Encoding = enum(u31) {
|
|
none = c.FT_ENCODING_NONE,
|
|
ms_symbol = c.FT_ENCODING_MS_SYMBOL,
|
|
unicode = c.FT_ENCODING_UNICODE,
|
|
sjis = c.FT_ENCODING_SJIS,
|
|
prc = c.FT_ENCODING_PRC,
|
|
big5 = c.FT_ENCODING_BIG5,
|
|
wansung = c.FT_ENCODING_WANSUNG,
|
|
johab = c.FT_ENCODING_JOHAB,
|
|
adobe_standard = c.FT_ENCODING_ADOBE_STANDARD,
|
|
adobe_expert = c.FT_ENCODING_ADOBE_EXPERT,
|
|
adobe_custom = c.FT_ENCODING_ADOBE_CUSTOM,
|
|
adobe_latin_1 = c.FT_ENCODING_ADOBE_LATIN_1,
|
|
old_latin_2 = c.FT_ENCODING_OLD_LATIN_2,
|
|
apple_roman = c.FT_ENCODING_APPLE_ROMAN,
|
|
};
|
|
|
|
pub const GlyphFormat = enum(u32) {
|
|
none = c.FT_GLYPH_FORMAT_NONE,
|
|
composite = c.FT_GLYPH_FORMAT_COMPOSITE,
|
|
bitmap = c.FT_GLYPH_FORMAT_BITMAP,
|
|
outline = c.FT_GLYPH_FORMAT_OUTLINE,
|
|
plotter = c.FT_GLYPH_FORMAT_PLOTTER,
|
|
svg = c.FT_GLYPH_FORMAT_SVG,
|
|
};
|
|
|
|
pub const KerningMode = enum(u2) {
|
|
default = c.FT_KERNING_DEFAULT,
|
|
unfitted = c.FT_KERNING_UNFITTED,
|
|
unscaled = c.FT_KERNING_UNSCALED,
|
|
};
|
|
|
|
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,
|
|
};
|
|
|
|
pub const LineCap = enum(u2) {
|
|
butt = c.FT_STROKER_LINECAP_BUTT,
|
|
round = c.FT_STROKER_LINECAP_ROUND,
|
|
square = c.FT_STROKER_LINECAP_SQUARE,
|
|
};
|
|
|
|
pub const LineJoin = enum(u2) {
|
|
round = c.FT_STROKER_LINEJOIN_ROUND,
|
|
bevel = c.FT_STROKER_LINEJOIN_BEVEL,
|
|
miter_variable = c.FT_STROKER_LINEJOIN_MITER_VARIABLE,
|
|
miter_fixed = c.FT_STROKER_LINEJOIN_MITER_FIXED,
|
|
};
|
|
|
|
pub const PaintExtend = enum(u2) {
|
|
pad = c.FT_COLR_PAINT_EXTEND_PAD,
|
|
repeat = c.FT_COLR_PAINT_EXTEND_REPEAT,
|
|
reflect = c.FT_COLR_PAINT_EXTEND_REFLECT,
|
|
};
|
|
|
|
pub const PaintFormat = enum(u8) {
|
|
color_layers = c.FT_COLR_PAINTFORMAT_COLR_LAYERS,
|
|
solid = c.FT_COLR_PAINTFORMAT_SOLID,
|
|
linear_gradient = c.FT_COLR_PAINTFORMAT_LINEAR_GRADIENT,
|
|
radial_gradient = c.FT_COLR_PAINTFORMAT_RADIAL_GRADIENT,
|
|
sweep_gradient = c.FT_COLR_PAINTFORMAT_SWEEP_GRADIENT,
|
|
glyph = c.FT_COLR_PAINTFORMAT_GLYPH,
|
|
color_glyph = c.FT_COLR_PAINTFORMAT_COLR_GLYPH,
|
|
transform = c.FT_COLR_PAINTFORMAT_TRANSFORM,
|
|
translate = c.FT_COLR_PAINTFORMAT_TRANSLATE,
|
|
scale = c.FT_COLR_PAINTFORMAT_SCALE,
|
|
rotate = c.FT_COLR_PAINTFORMAT_ROTATE,
|
|
skew = c.FT_COLR_PAINTFORMAT_SKEW,
|
|
composite = c.FT_COLR_PAINTFORMAT_COMPOSITE,
|
|
};
|
|
|
|
pub const PixelMode = enum(u3) {
|
|
none = c.FT_PIXEL_MODE_NONE,
|
|
mono = c.FT_PIXEL_MODE_MONO,
|
|
gray = c.FT_PIXEL_MODE_GRAY,
|
|
gray2 = c.FT_PIXEL_MODE_GRAY2,
|
|
gray4 = c.FT_PIXEL_MODE_GRAY4,
|
|
lcd = c.FT_PIXEL_MODE_LCD,
|
|
lcd_v = c.FT_PIXEL_MODE_LCD_V,
|
|
bgra = c.FT_PIXEL_MODE_BGRA,
|
|
};
|
|
|
|
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 RootTransform = enum(u1) {
|
|
include_root_transform = c.FT_COLOR_INCLUDE_ROOT_TRANSFORM,
|
|
no_root_transform = c.FT_COLOR_NO_ROOT_TRANSFORM,
|
|
};
|
|
|
|
pub const SizeRequestType = enum(u3) {
|
|
nominal = c.FT_SIZE_REQUEST_TYPE_NOMINAL,
|
|
real_dim = c.FT_SIZE_REQUEST_TYPE_REAL_DIM,
|
|
bbox = c.FT_SIZE_REQUEST_TYPE_BBOX,
|
|
cell = c.FT_SIZE_REQUEST_TYPE_CELL,
|
|
scales = c.FT_SIZE_REQUEST_TYPE_SCALES,
|
|
max = c.FT_SIZE_REQUEST_TYPE_MAX,
|
|
};
|
|
|
|
pub const Paint = union(PaintFormat) {
|
|
color_layers: PaintColrLayers,
|
|
solid: PaintSolid,
|
|
linear_gradient: PaintLinearGradient,
|
|
radial_gradient: PaintRadialGradient,
|
|
sweep_gradient: PaintSweepGradient,
|
|
glyph: PaintGlyph,
|
|
color_glyph: PaintColrGlyph,
|
|
transform: PaintTransform,
|
|
translate: PaintTranslate,
|
|
scale: PaintScale,
|
|
rotate: PaintRotate,
|
|
skew: PaintSkew,
|
|
composite: PaintComposite,
|
|
};
|
|
|
|
pub const FaceFlags = packed struct(c_long) {
|
|
scalable: bool = false,
|
|
fixed_sizes: bool = false,
|
|
fixed_width: bool = false,
|
|
sfnt: bool = false,
|
|
horizontal: bool = false,
|
|
vertical: bool = false,
|
|
kerning: bool = false,
|
|
fast_glyphs: bool = false,
|
|
multiple_masters: bool = false,
|
|
glyph_names: bool = false,
|
|
external_stream: bool = false,
|
|
hinter: bool = false,
|
|
cid_keyed: bool = false,
|
|
tricky: bool = false,
|
|
color: bool = false,
|
|
variation: bool = false,
|
|
svg: bool = false,
|
|
sbix: bool = false,
|
|
sbix_overlay: bool = false,
|
|
_padding: if (@sizeOf(c_long) == 4) u13 else u45 = 0,
|
|
};
|
|
|
|
pub const FSType = packed struct(c_ushort) {
|
|
installable_embedding: bool = false,
|
|
restriced_license_embedding: bool = false,
|
|
preview_and_print_embedding: bool = false,
|
|
editable_embedding: bool = false,
|
|
_padding: u4 = 0,
|
|
no_subsetting: bool = false,
|
|
bitmap_embedding_only: bool = false,
|
|
_padding0: u6 = 0,
|
|
};
|
|
|
|
pub const LoadFlags = packed struct(c_int) {
|
|
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,
|
|
_padding: u1 = 0,
|
|
target_normal: bool = false,
|
|
target_light: bool = false,
|
|
target_mono: bool = false,
|
|
target_lcd: bool = false,
|
|
target_lcd_v: bool = false,
|
|
color: bool = false,
|
|
compute_metrics: bool = false,
|
|
bitmap_metrics_only: bool = false,
|
|
_padding0: u9 = 0,
|
|
};
|
|
|
|
pub const OpenFlags = packed struct(c_int) {
|
|
memory: bool = false,
|
|
stream: bool = false,
|
|
path: bool = false,
|
|
driver: bool = false,
|
|
params: bool = false,
|
|
_padding: u27 = 0,
|
|
};
|
|
|
|
pub const PaletteFlags = packed struct(c_ushort) {
|
|
for_light_background: bool = false,
|
|
for_dark_background: bool = false,
|
|
_padding: u14 = 0,
|
|
};
|
|
|
|
pub const StyleFlags = packed struct(c_long) {
|
|
italic: bool = false,
|
|
bold: bool = false,
|
|
_padding: if (@sizeOf(c_long) == 4) u30 else u62 = 0,
|
|
};
|
|
|
|
pub const Bitmap = struct {
|
|
handle: c.FT_Bitmap,
|
|
|
|
pub fn init() Bitmap {
|
|
var b: c.FT_Bitmap = undefined;
|
|
c.FT_Bitmap_Init(&b);
|
|
return .{ .handle = b };
|
|
}
|
|
|
|
pub fn deinit(self: *Bitmap, lib: Library) void {
|
|
_ = c.FT_Bitmap_Done(lib.handle, &self.handle);
|
|
}
|
|
|
|
pub fn copy(self: Bitmap, lib: Library) Error!Bitmap {
|
|
var b: c.FT_Bitmap = undefined;
|
|
try intToError(c.FT_Bitmap_Copy(lib.handle, &self.handle, &b));
|
|
return Bitmap{ .handle = b };
|
|
}
|
|
|
|
pub fn embolden(self: *Bitmap, lib: Library, x_strength: i32, y_strength: i32) Error!void {
|
|
try intToError(c.FT_Bitmap_Embolden(lib.handle, &self.handle, x_strength, y_strength));
|
|
}
|
|
|
|
pub fn convert(self: Bitmap, lib: Library, alignment: u29) Error!Bitmap {
|
|
var b: c.FT_Bitmap = undefined;
|
|
try intToError(c.FT_Bitmap_Convert(lib.handle, &self.handle, &b, alignment));
|
|
return Bitmap{ .handle = b };
|
|
}
|
|
|
|
pub fn blend(self: *Bitmap, lib: Library, source_offset: Vector, target_offset: *Vector, color: Color) Error!void {
|
|
var b: c.FT_Bitmap = undefined;
|
|
c.FT_Bitmap_Init(&b);
|
|
try intToError(c.FT_Bitmap_Blend(lib.handle, &self.handle, source_offset, &b, target_offset, color));
|
|
}
|
|
|
|
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 @enumFromInt(self.handle.pixel_mode);
|
|
}
|
|
|
|
pub fn buffer(self: Bitmap) ?[]const u8 {
|
|
const buffer_size = @abs(self.pitch()) * self.rows();
|
|
return if (self.handle.buffer == null)
|
|
// freetype returns a null pointer for zero-length allocations
|
|
// https://github.com/hexops-graveyard/freetype/blob/bbd80a52b7b749140ec87d24b6c767c5063be356/freetype/src/base/ftutil.c#L135
|
|
null
|
|
else
|
|
self.handle.buffer[0..buffer_size];
|
|
}
|
|
};
|
|
|
|
pub const BitmapGlyph = struct {
|
|
handle: c.FT_BitmapGlyph,
|
|
|
|
pub fn deinit(self: BitmapGlyph) void {
|
|
c.FT_Done_Glyph(@ptrCast(self.handle));
|
|
}
|
|
|
|
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 .{ .handle = self.handle.*.bitmap };
|
|
}
|
|
};
|
|
|
|
pub const Face = struct {
|
|
pub const CharmapIterator = struct {
|
|
face: Face,
|
|
index: u32,
|
|
charcode: u32,
|
|
|
|
pub fn init(face: Face) CharmapIterator {
|
|
var i: u32 = 0;
|
|
const cc = c.FT_Get_First_Char(face.handle, &i);
|
|
return .{
|
|
.face = face,
|
|
.index = i,
|
|
.charcode = @intCast(cc),
|
|
};
|
|
}
|
|
|
|
pub fn next(self: *CharmapIterator) ?u32 {
|
|
self.charcode = @intCast(c.FT_Get_Next_Char(self.face.handle, self.charcode, &self.index));
|
|
return if (self.index != 0)
|
|
self.charcode
|
|
else
|
|
null;
|
|
}
|
|
};
|
|
|
|
handle: c.FT_Face,
|
|
|
|
pub fn deinit(self: Face) void {
|
|
_ = c.FT_Done_Face(self.handle);
|
|
}
|
|
|
|
pub fn attachFile(self: Face, path: [*:0]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: OpenArgs) Error!void {
|
|
return intToError(c.FT_Attach_Stream(self.handle, &args.cast()));
|
|
}
|
|
|
|
pub fn loadGlyph(self: Face, index: u32, flags: LoadFlags) Error!void {
|
|
return intToError(c.FT_Load_Glyph(self.handle, index, @bitCast(flags)));
|
|
}
|
|
|
|
pub fn loadChar(self: Face, char: u32, flags: LoadFlags) Error!void {
|
|
return intToError(c.FT_Load_Char(self.handle, char, @bitCast(flags)));
|
|
}
|
|
|
|
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 requestSize(self: Face, req: SizeRequest) Error!void {
|
|
var req_mut = req;
|
|
return intToError(c.FT_Request_Size(self.handle, &req_mut));
|
|
}
|
|
|
|
pub fn selectSize(self: Face, strike_index: i32) Error!void {
|
|
return intToError(c.FT_Select_Size(self.handle, strike_index));
|
|
}
|
|
|
|
pub fn setTransform(self: Face, matrix: ?Matrix, delta: ?Vector) Error!void {
|
|
var matrix_mut = matrix;
|
|
var delta_mut = delta;
|
|
return c.FT_Set_Transform(self.handle, if (matrix_mut) |*m| m else null, if (delta_mut) |*d| d else null);
|
|
}
|
|
|
|
pub fn getTransform(self: Face) std.meta.Tuple(&.{ Matrix, Vector }) {
|
|
var matrix: Matrix = undefined;
|
|
var delta: Vector = undefined;
|
|
c.FT_Get_Transform(self.handle, &matrix, &delta);
|
|
return .{ matrix, delta };
|
|
}
|
|
|
|
pub fn getCharIndex(self: Face, char: u32) ?u32 {
|
|
const i = c.FT_Get_Char_Index(self.handle, char);
|
|
return if (i == 0) null else i;
|
|
}
|
|
|
|
pub fn getNameIndex(self: Face, name: [:0]const u8) ?u32 {
|
|
const i = c.FT_Get_Name_Index(self.handle, name.ptr);
|
|
return if (i == 0) null else i;
|
|
}
|
|
|
|
pub fn getKerning(self: Face, left_char_index: u32, right_char_index: u32, mode: KerningMode) Error!Vector {
|
|
var kerning: Vector = undefined;
|
|
try intToError(c.FT_Get_Kerning(self.handle, left_char_index, right_char_index, @intFromEnum(mode), &kerning));
|
|
return kerning;
|
|
}
|
|
|
|
pub fn getTrackKerning(self: Face, point_size: i32, degree: i32) Error!i32 {
|
|
const kerning: c_long = 0;
|
|
try intToError(c.FT_Get_Track_Kerning(self.handle, point_size, degree, kerning));
|
|
return @intCast(kerning);
|
|
}
|
|
|
|
pub fn getGlyphName(self: Face, index: u32, buf: []u8) Error!void {
|
|
try intToError(c.FT_Get_Glyph_Name(self.handle, index, buf.ptr, @intCast(buf.len)));
|
|
}
|
|
|
|
pub fn getPostscriptName(self: Face) ?[:0]const u8 {
|
|
return if (c.FT_Get_Postscript_Name(self.handle)) |face_name|
|
|
std.mem.span(@as([*:0]const u8, @ptrCast(face_name)))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn iterateCharmap(self: Face) CharmapIterator {
|
|
return CharmapIterator.init(self);
|
|
}
|
|
|
|
pub fn selectCharmap(self: Face, encoding: Encoding) Error!void {
|
|
return intToError(c.FT_Select_Charmap(self.handle, @intFromEnum(encoding)));
|
|
}
|
|
|
|
pub fn setCharmap(self: Face, char_map: *CharMap) Error!void {
|
|
return intToError(c.FT_Set_Charmap(self.handle, char_map));
|
|
}
|
|
|
|
pub fn getFSTypeFlags(self: Face) FSType {
|
|
return @bitCast(c.FT_Get_FSType_Flags(self.handle));
|
|
}
|
|
|
|
pub fn getCharVariantIndex(self: Face, char: u32, variant_selector: u32) ?u32 {
|
|
return switch (c.FT_Face_GetCharVariantIndex(self.handle, char, variant_selector)) {
|
|
0 => null,
|
|
else => |i| i,
|
|
};
|
|
}
|
|
|
|
pub fn getCharVariantIsDefault(self: Face, char: u32, variant_selector: u32) ?bool {
|
|
return switch (c.FT_Face_GetCharVariantIsDefault(self.handle, char, variant_selector)) {
|
|
-1 => null,
|
|
0 => false,
|
|
1 => true,
|
|
else => unreachable,
|
|
};
|
|
}
|
|
|
|
pub fn getVariantSelectors(self: Face) ?[]u32 {
|
|
return if (c.FT_Face_GetVariantSelectors(self.handle)) |chars|
|
|
@ptrCast(std.mem.sliceTo(@as([*:0]u32, @ptrCast(chars)), 0))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn getVariantsOfChar(self: Face, char: u32) ?[]u32 {
|
|
return if (c.FT_Face_GetVariantsOfChar(self.handle, char)) |variants|
|
|
@ptrCast(std.mem.sliceTo(@as([*:0]u32, @ptrCast(variants)), 0))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn getCharsOfVariant(self: Face, variant_selector: u32) ?[]u32 {
|
|
return if (c.FT_Face_GetCharsOfVariant(self.handle, variant_selector)) |chars|
|
|
@ptrCast(std.mem.sliceTo(@as([*:0]u32, @ptrCast(chars)), 0))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn getPaletteData(self: Face) Error!PaletteData {
|
|
var p: c.FT_Palette_Data = undefined;
|
|
try intToError(c.FT_Palette_Data_Get(self.handle, &p));
|
|
return PaletteData{ .handle = p };
|
|
}
|
|
|
|
fn selectPalette(self: Face, index: u16) Error!?[]const Color {
|
|
var color: [*:0]Color = undefined;
|
|
try intToError(c.FT_Palette_Select(self.handle, index, &color));
|
|
const pd = try getPaletteData();
|
|
return self.color[0..pd.numPaletteEntries()];
|
|
}
|
|
|
|
pub fn setPaletteForegroundColor(self: Face, color: Color) Error!void {
|
|
try intToError(c.FT_Palette_Set_Foreground_Color(self.handle, color));
|
|
}
|
|
|
|
pub fn getGlyphLayersIterator(self: Face, glyph_index: u32) GlyphLayersIterator {
|
|
return GlyphLayersIterator.init(self, glyph_index);
|
|
}
|
|
|
|
pub fn getColorGlyphPaint(self: Face, base_glyph: u32, root_transform: RootTransform) ?Paint {
|
|
var opaque_paint: OpaquePaint = undefined;
|
|
if (c.FT_Get_Color_Glyph_Paint(self.handle, base_glyph, @intFromEnum(root_transform), &opaque_paint) == 0)
|
|
return null;
|
|
return self.getPaint(opaque_paint);
|
|
}
|
|
|
|
pub fn getColorGlyphClibBox(self: Face, base_glyph: u32) ?ClipBox {
|
|
var clib_box: ClipBox = undefined;
|
|
if (c.FT_Get_Color_Glyph_ClipBox(self.handle, base_glyph, &clib_box) == 0)
|
|
return null;
|
|
return clib_box;
|
|
}
|
|
|
|
pub fn getPaint(self: Face, opaque_paint: OpaquePaint) ?Paint {
|
|
var p: c.FT_COLR_Paint = undefined;
|
|
if (c.FT_Get_Paint(self.handle, opaque_paint, &p) == 0)
|
|
return null;
|
|
return switch (@as(PaintFormat, @enumFromInt(p.format))) {
|
|
.color_layers => Paint{ .color_layers = p.u.colr_layers },
|
|
.glyph => Paint{ .glyph = p.u.glyph },
|
|
.solid => Paint{ .solid = p.u.solid },
|
|
.linear_gradient => Paint{ .linear_gradient = p.u.linear_gradient },
|
|
.radial_gradient => Paint{ .radial_gradient = p.u.radial_gradient },
|
|
.sweep_gradient => Paint{ .sweep_gradient = p.u.sweep_gradient },
|
|
.transform => Paint{ .transform = p.u.transform },
|
|
.translate => Paint{ .translate = p.u.translate },
|
|
.scale => Paint{ .scale = p.u.scale },
|
|
.rotate => Paint{ .rotate = p.u.rotate },
|
|
.skew => Paint{ .skew = p.u.skew },
|
|
.composite => Paint{ .composite = p.u.composite },
|
|
.color_glyph => Paint{ .color_glyph = p.u.colr_glyph },
|
|
};
|
|
}
|
|
|
|
pub fn newSize(self: Face) Error!Size {
|
|
var s: c.FT_Size = undefined;
|
|
try intToError(c.FT_New_Size(self.handle, &s));
|
|
return Size{ .handle = s };
|
|
}
|
|
|
|
pub fn numFaces(self: Face) u32 {
|
|
return @intCast(self.handle.*.num_faces);
|
|
}
|
|
|
|
pub fn faceIndex(self: Face) u32 {
|
|
return @intCast(self.handle.*.face_index);
|
|
}
|
|
|
|
pub fn faceFlags(self: Face) FaceFlags {
|
|
return @bitCast(self.handle.*.face_flags);
|
|
}
|
|
|
|
pub fn styleFlags(self: Face) StyleFlags {
|
|
return @bitCast(self.handle.*.style_flags);
|
|
}
|
|
|
|
pub fn numGlyphs(self: Face) u32 {
|
|
return @intCast(self.handle.*.num_glyphs);
|
|
}
|
|
|
|
pub fn familyName(self: Face) ?[:0]const u8 {
|
|
return if (self.handle.*.family_name) |family|
|
|
std.mem.span(@as([*:0]const u8, @ptrCast(family)))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn styleName(self: Face) ?[:0]const u8 {
|
|
return if (self.handle.*.style_name) |style_name|
|
|
std.mem.span(@as([*:0]const u8, @ptrCast(style_name)))
|
|
else
|
|
null;
|
|
}
|
|
|
|
pub fn numFixedSizes(self: Face) u32 {
|
|
return @intCast(self.handle.*.num_fixed_sizes);
|
|
}
|
|
|
|
pub fn availableSizes(self: Face) []BitmapSize {
|
|
return if (self.handle.*.available_sizes != null)
|
|
self.handle.*.available_sizes[0..self.numFixedSizes()]
|
|
else
|
|
&.{};
|
|
}
|
|
|
|
pub fn getAdvance(self: Face, glyph_index: u32, load_flags: LoadFlags) Error!i32 {
|
|
var a: c_long = 0;
|
|
try intToError(c.FT_Get_Advance(self.handle, glyph_index, @bitCast(load_flags), &a));
|
|
return @intCast(a);
|
|
}
|
|
|
|
pub fn getAdvances(self: Face, start: u32, advances_out: []c_long, load_flags: LoadFlags) Error!void {
|
|
try intToError(c.FT_Get_Advances(self.handle, start, @intCast(advances_out.len), @bitCast(load_flags), advances_out.ptr));
|
|
}
|
|
|
|
pub fn numCharmaps(self: Face) u32 {
|
|
return @intCast(self.handle.*.num_charmaps);
|
|
}
|
|
|
|
pub fn charmaps(self: Face) []const CharMap {
|
|
return @as([*]const CharMap, @ptrCast(self.handle.*.charmaps))[0..self.numCharmaps()];
|
|
}
|
|
|
|
pub fn bbox(self: Face) BBox {
|
|
return self.handle.*.bbox;
|
|
}
|
|
|
|
pub fn unitsPerEM(self: Face) u16 {
|
|
return self.handle.*.units_per_EM;
|
|
}
|
|
|
|
pub fn ascender(self: Face) i16 {
|
|
return self.handle.*.ascender;
|
|
}
|
|
|
|
pub fn descender(self: Face) i16 {
|
|
return self.handle.*.descender;
|
|
}
|
|
|
|
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 glyph(self: Face) GlyphSlot {
|
|
return .{ .handle = self.handle.*.glyph };
|
|
}
|
|
|
|
pub fn size(self: Face) Size {
|
|
return Size{ .handle = self.handle.*.size };
|
|
}
|
|
|
|
pub fn charmap(self: Face) CharMap {
|
|
return self.handle.*.charmap.*;
|
|
}
|
|
|
|
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 const Glyph = struct {
|
|
handle: c.FT_Glyph,
|
|
|
|
pub fn deinit(self: Glyph) void {
|
|
c.FT_Done_Glyph(self.handle);
|
|
}
|
|
|
|
pub fn newGlyph(library: Library, glyph_format: GlyphFormat) Glyph {
|
|
var g: c.FT_Glyph = undefined;
|
|
return .{
|
|
.handle = c.FT_New_Glyph(library.handle, @intFromEnum(glyph_format), &g),
|
|
};
|
|
}
|
|
|
|
pub fn copy(self: Glyph) Error!Glyph {
|
|
var g: c.FT_Glyph = undefined;
|
|
try intToError(c.FT_Glyph_Copy(self.handle, &g));
|
|
return Glyph{ .handle = g };
|
|
}
|
|
|
|
pub fn transform(self: Glyph, matrix: ?Matrix, delta: ?Vector) Error!void {
|
|
try intToError(c.FT_Glyph_Transform(self.handle, if (matrix) |m| &m else null, if (delta) |d| &d else null));
|
|
}
|
|
|
|
pub fn getCBox(self: Glyph, bbox_mode: BBoxMode) BBox {
|
|
var b: BBox = undefined;
|
|
c.FT_Glyph_Get_CBox(self.handle, @intFromEnum(bbox_mode), &b);
|
|
return b;
|
|
}
|
|
|
|
pub fn toBitmapGlyph(self: *Glyph, render_mode: RenderMode, origin: ?Vector) Error!BitmapGlyph {
|
|
try intToError(c.FT_Glyph_To_Bitmap(&self.handle, @intFromEnum(render_mode), if (origin) |o| &o else null, 1));
|
|
return BitmapGlyph{ .handle = @ptrCast(self.handle) };
|
|
}
|
|
|
|
pub fn copyBitmapGlyph(self: *Glyph, render_mode: RenderMode, origin: ?Vector) Error!BitmapGlyph {
|
|
try intToError(c.FT_Glyph_To_Bitmap(&self.handle, @intFromEnum(render_mode), if (origin) |o| &o else null, 0));
|
|
return BitmapGlyph{ .handle = @ptrCast(self.handle) };
|
|
}
|
|
|
|
pub fn castBitmapGlyph(self: Glyph) Error!BitmapGlyph {
|
|
return BitmapGlyph{ .handle = @ptrCast(self.handle) };
|
|
}
|
|
|
|
pub fn castOutlineGlyph(self: Glyph) Error!OutlineGlyph {
|
|
return OutlineGlyph{ .handle = @ptrCast(self.handle) };
|
|
}
|
|
|
|
pub fn castSvgGlyph(self: Glyph) Error!SvgGlyph {
|
|
return SvgGlyph{ .handle = @ptrCast(self.handle) };
|
|
}
|
|
|
|
pub fn stroke(self: *Glyph, stroker: Stroker) Error!void {
|
|
try intToError(c.FT_Glyph_Stroke(&self.handle, stroker.handle, 0));
|
|
}
|
|
|
|
pub fn strokeBorder(self: *Glyph, stroker: Stroker, inside: bool) Error!void {
|
|
try intToError(c.FT_Glyph_StrokeBorder(&self.handle, stroker.handle, if (inside) 1 else 0, 0));
|
|
}
|
|
|
|
pub fn format(self: Glyph) GlyphFormat {
|
|
return @enumFromInt(self.handle.*.format);
|
|
}
|
|
|
|
pub fn advanceX(self: Glyph) isize {
|
|
return self.handle.*.advance.x;
|
|
}
|
|
|
|
pub fn advanceY(self: Glyph) isize {
|
|
return self.handle.*.advance.y;
|
|
}
|
|
};
|
|
|
|
pub const GlyphLayersIterator = struct {
|
|
face: Face,
|
|
glyph_index: u32,
|
|
layer_glyph_index: u32,
|
|
layer_color_index: u32,
|
|
iterator: LayerIterator,
|
|
|
|
pub fn init(face: Face, glyph_index: u32) GlyphLayersIterator {
|
|
var iterator: LayerIterator = undefined;
|
|
iterator.p = null;
|
|
return .{
|
|
.face = face,
|
|
.glyph_index = glyph_index,
|
|
.layer_glyph_index = 0,
|
|
.layer_color_index = 0,
|
|
.iterator = iterator,
|
|
};
|
|
}
|
|
|
|
pub fn next(self: *GlyphLayersIterator) bool {
|
|
return if (c.FT_Get_Color_Glyph_Layer(
|
|
self.face.handle,
|
|
self.glyph_index,
|
|
&self.layer_glyph_index,
|
|
&self.layer_color_index,
|
|
&self.iterator,
|
|
) == 0) false else true;
|
|
}
|
|
};
|
|
|
|
pub const GlyphSlot = struct {
|
|
pub const SubGlyphInfo = struct {
|
|
index: i32,
|
|
flags: c_uint,
|
|
arg1: i32,
|
|
arg2: i32,
|
|
transform: Matrix,
|
|
};
|
|
|
|
handle: c.FT_GlyphSlot,
|
|
|
|
pub fn library(self: GlyphSlot) Library {
|
|
return .{ .handle = self.handle.*.library };
|
|
}
|
|
|
|
pub fn face(self: GlyphSlot) Face {
|
|
return .{ .handle = self.handle.*.face };
|
|
}
|
|
|
|
pub fn next(self: GlyphSlot) GlyphSlot {
|
|
return .{ .handle = self.handle.*.next };
|
|
}
|
|
|
|
pub fn glyphIndex(self: GlyphSlot) u32 {
|
|
return self.handle.*.glyph_index;
|
|
}
|
|
|
|
pub fn metrics(self: GlyphSlot) GlyphMetrics {
|
|
return self.handle.*.metrics;
|
|
}
|
|
|
|
pub fn linearHoriAdvance(self: GlyphSlot) i32 {
|
|
return @intCast(self.handle.*.linearHoriAdvance);
|
|
}
|
|
|
|
pub fn linearVertAdvance(self: GlyphSlot) i32 {
|
|
return @intCast(self.handle.*.linearVertAdvance);
|
|
}
|
|
|
|
pub fn advance(self: GlyphSlot) Vector {
|
|
return self.handle.*.advance;
|
|
}
|
|
|
|
pub fn format(self: GlyphSlot) GlyphFormat {
|
|
return @enumFromInt(self.handle.*.format);
|
|
}
|
|
|
|
pub fn ownBitmap(self: GlyphSlot) Error!void {
|
|
try intToError(c.FT_GlyphSlot_Own_Bitmap(self.handle));
|
|
}
|
|
|
|
pub fn bitmap(self: GlyphSlot) Bitmap {
|
|
return .{ .handle = 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 outline(self: GlyphSlot) ?Outline {
|
|
return if (self.format() == .outline) .{ .handle = &self.handle.*.outline } else null;
|
|
}
|
|
|
|
pub fn lsbDelta(self: GlyphSlot) i32 {
|
|
return @intCast(self.handle.*.lsb_delta);
|
|
}
|
|
|
|
pub fn rsbDelta(self: GlyphSlot) i32 {
|
|
return @intCast(self.handle.*.rsb_delta);
|
|
}
|
|
|
|
pub fn render(self: GlyphSlot, render_mode: RenderMode) Error!void {
|
|
return intToError(c.FT_Render_Glyph(self.handle, @intFromEnum(render_mode)));
|
|
}
|
|
|
|
pub fn adjustWeight(self: GlyphSlot, x_delta: i32, y_delta: i32) void {
|
|
return c.FT_GlyphSlot_AdjustWeight(self.handle, x_delta, y_delta);
|
|
}
|
|
|
|
pub fn slant(self: GlyphSlot, x_slant: i32, y_slant: i32) void {
|
|
return c.FT_GlyphSlot_Slant(self.handle, x_slant, y_slant);
|
|
}
|
|
|
|
pub fn getSubGlyphInfo(self: GlyphSlot, sub_index: u32) Error!SubGlyphInfo {
|
|
var info: SubGlyphInfo = undefined;
|
|
try intToError(c.FT_Get_SubGlyph_Info(self.handle, sub_index, &info.index, &info.flags, &info.arg1, &info.arg2, &info.transform));
|
|
return info;
|
|
}
|
|
|
|
pub fn getGlyph(self: GlyphSlot) Error!Glyph {
|
|
var res: c.FT_Glyph = undefined;
|
|
try intToError(c.FT_Get_Glyph(self.handle, &res));
|
|
return Glyph{ .handle = res };
|
|
}
|
|
};
|
|
|
|
pub const Library = struct {
|
|
pub const Version = struct {
|
|
major: i32,
|
|
minor: i32,
|
|
patch: i32,
|
|
};
|
|
|
|
handle: c.FT_Library,
|
|
|
|
pub fn init() Error!Library {
|
|
var lib = Library{ .handle = undefined };
|
|
try intToError(c.FT_Init_FreeType(&lib.handle));
|
|
return lib;
|
|
}
|
|
|
|
pub fn deinit(self: Library) void {
|
|
_ = c.FT_Done_FreeType(self.handle);
|
|
}
|
|
|
|
pub fn createFace(self: Library, path: [*:0]const u8, face_index: i32) Error!Face {
|
|
return self.openFace(.{
|
|
.flags = .{ .path = true },
|
|
.data = .{ .path = path },
|
|
}, face_index);
|
|
}
|
|
|
|
pub fn createFaceMemory(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: OpenArgs, face_index: i32) Error!Face {
|
|
var f: c.FT_Face = undefined;
|
|
try intToError(c.FT_Open_Face(self.handle, &args.cast(), face_index, &f));
|
|
return Face{ .handle = f };
|
|
}
|
|
|
|
pub fn version(self: Library) Version {
|
|
var v: Version = undefined;
|
|
c.FT_Library_Version(
|
|
self.handle,
|
|
&v.major,
|
|
&v.minor,
|
|
&v.patch,
|
|
);
|
|
return v;
|
|
}
|
|
|
|
pub fn createStroker(self: Library) Error!Stroker {
|
|
var s: c.FT_Stroker = undefined;
|
|
try intToError(c.FT_Stroker_New(self.handle, &s));
|
|
return Stroker{ .handle = s };
|
|
}
|
|
|
|
pub fn createOutlineFromBitmap(self: Library, bitmap: Bitmap) Error!Outline {
|
|
const o: Outline = undefined;
|
|
try intToError(c.FT_Outline_Get_Bitmap(self.handle, o.handle, &bitmap.handle));
|
|
return o;
|
|
}
|
|
|
|
pub fn renderOutline(self: Library, outline: Outline, params: *Raster.Params) Error!void {
|
|
try intToError(c.FT_Outline_Render(self.handle, outline.handle, @ptrCast(params)));
|
|
}
|
|
|
|
pub fn setLcdFilter(self: Library, lcd_filter: LcdFilter) Error!void {
|
|
return intToError(c.FT_Library_SetLcdFilter(self.handle, @intFromEnum(lcd_filter)));
|
|
}
|
|
};
|
|
|
|
pub const OpenArgs = struct {
|
|
flags: OpenFlags,
|
|
data: union(enum) {
|
|
memory: []const u8,
|
|
path: [*:0]const u8,
|
|
stream: c.FT_Stream,
|
|
driver: c.FT_Module,
|
|
params: []const c.FT_Parameter,
|
|
},
|
|
|
|
pub fn cast(self: OpenArgs) c.FT_Open_Args {
|
|
var oa: c.FT_Open_Args = undefined;
|
|
oa.flags = @bitCast(self.flags);
|
|
switch (self.data) {
|
|
.memory => |d| {
|
|
oa.memory_base = d.ptr;
|
|
oa.memory_size = @intCast(d.len);
|
|
},
|
|
// The Freetype API requires a mutable string.
|
|
// This is an oversight, Freetype actually never writes to this string.
|
|
.path => |d| oa.pathname = @constCast(d),
|
|
.stream => |d| oa.stream = d,
|
|
.driver => |d| oa.driver = d,
|
|
.params => |*d| {
|
|
oa.params = @constCast(d.ptr);
|
|
oa.num_params = @intCast(d.len);
|
|
},
|
|
}
|
|
return oa;
|
|
}
|
|
};
|
|
|
|
pub const Outline = struct {
|
|
pub const Orientation = enum(u2) {
|
|
truetype = c.FT_ORIENTATION_TRUETYPE,
|
|
postscript = c.FT_ORIENTATION_POSTSCRIPT,
|
|
none = c.FT_ORIENTATION_NONE,
|
|
};
|
|
|
|
pub const Flags = packed struct(c_int) {
|
|
owner: bool = false,
|
|
even_odd_fill: bool = false,
|
|
reverse_fill: bool = false,
|
|
ignore_dropouts: bool = false,
|
|
smart_dropouts: bool = false,
|
|
include_stubs: bool = false,
|
|
overlap: bool = false,
|
|
_padding: u1 = 0,
|
|
high_precision: bool = false,
|
|
single_pass: bool = false,
|
|
_padding0: u22 = 0,
|
|
};
|
|
|
|
handle: *c.FT_Outline,
|
|
|
|
pub fn numPoints(self: Outline) u15 {
|
|
return @intCast(self.handle.*.n_points);
|
|
}
|
|
|
|
pub fn numContours(self: Outline) u15 {
|
|
return @intCast(self.handle.*.n_contours);
|
|
}
|
|
|
|
pub fn points(self: Outline) []const Vector {
|
|
return self.handle.*.points[0..self.numPoints()];
|
|
}
|
|
|
|
pub fn tags(self: Outline) []const u8 {
|
|
return self.handle.tags[0..@intCast(self.handle.n_points)];
|
|
}
|
|
|
|
pub fn contours(self: Outline) []const i16 {
|
|
return self.handle.*.contours[0..self.numContours()];
|
|
}
|
|
|
|
pub fn flags(self: Outline) Flags {
|
|
return @bitCast(self.handle.*.flags);
|
|
}
|
|
|
|
pub fn copy(self: Outline) Error!Outline {
|
|
var o: c.FT_Outline = undefined;
|
|
try intToError(c.FT_Outline_Copy(self.handle, &o));
|
|
return Outline{ .handle = &o };
|
|
}
|
|
|
|
pub fn translate(self: Outline, x_offset: i32, y_offset: i32) void {
|
|
c.FT_Outline_Translate(self.handle, x_offset, y_offset);
|
|
}
|
|
|
|
pub fn transform(self: Outline, matrix: ?Matrix) void {
|
|
c.FT_Outline_Transform(self.handle, if (matrix) |m| &m else null);
|
|
}
|
|
|
|
pub fn embolden(self: Outline, strength: i32) Error!void {
|
|
try intToError(c.FT_Outline_Embolden(self.handle, strength));
|
|
}
|
|
|
|
pub fn emboldenXY(self: Outline, x_strength: i32, y_strength: i32) Error!void {
|
|
try intToError(c.FT_Outline_EmboldenXY(self.handle, x_strength, y_strength));
|
|
}
|
|
|
|
pub fn reverse(self: Outline) void {
|
|
c.FT_Outline_Reverse(self.handle);
|
|
}
|
|
|
|
pub fn check(self: Outline) Error!void {
|
|
try intToError(c.FT_Outline_Check(self.handle));
|
|
}
|
|
|
|
pub fn cbox(self: Outline) BBox {
|
|
var b: BBox = undefined;
|
|
c.FT_Outline_Get_CBox(self.handle, &b);
|
|
return b;
|
|
}
|
|
|
|
pub fn bbox(self: Outline) Error!BBox {
|
|
var b: BBox = undefined;
|
|
try intToError(c.FT_Outline_Get_BBox(self.handle, &b));
|
|
return b;
|
|
}
|
|
|
|
pub fn orientation(self: Outline) Orientation {
|
|
return @enumFromInt(c.FT_Outline_Get_Orientation(self.handle));
|
|
}
|
|
|
|
pub fn getInsideBorder(self: Outline) Border {
|
|
return @enumFromInt(c.FT_Outline_GetInsideBorder(self.handle));
|
|
}
|
|
|
|
pub fn getOutsideBorder(self: Outline) Border {
|
|
return @enumFromInt(c.FT_Outline_GetOutsideBorder(self.handle));
|
|
}
|
|
|
|
pub fn Funcs(comptime Context: type) type {
|
|
return struct {
|
|
move_to: *const fn (ctx: Context, to: Vector) Error!void,
|
|
line_to: *const fn (ctx: Context, to: Vector) Error!void,
|
|
conic_to: *const fn (ctx: Context, control: Vector, to: Vector) Error!void,
|
|
cubic_to: *const fn (ctx: Context, control_0: Vector, control_1: Vector, to: Vector) Error!void,
|
|
shift: i32,
|
|
delta: i32,
|
|
};
|
|
}
|
|
|
|
fn FuncsWrapper(comptime Context: type) type {
|
|
return struct {
|
|
const Self = @This();
|
|
ctx: Context,
|
|
callbacks: Funcs(Context),
|
|
|
|
fn getSelf(ptr: ?*anyopaque) *Self {
|
|
return @ptrCast(@alignCast(ptr));
|
|
}
|
|
|
|
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, 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, 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,
|
|
control.*,
|
|
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,
|
|
control_0.*,
|
|
control_1.*,
|
|
to.*,
|
|
)) |_|
|
|
0
|
|
else |err|
|
|
errorToInt(err);
|
|
}
|
|
};
|
|
}
|
|
|
|
pub fn decompose(self: Outline, ctx: anytype, callbacks: Funcs(@TypeOf(ctx))) Error!void {
|
|
var wrapper = FuncsWrapper(@TypeOf(ctx)){ .ctx = ctx, .callbacks = callbacks };
|
|
try intToError(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,
|
|
));
|
|
}
|
|
};
|
|
|
|
pub const OutlineGlyph = struct {
|
|
handle: c.FT_OutlineGlyph,
|
|
|
|
pub fn deinit(self: OutlineGlyph) void {
|
|
c.FT_Done_Glyph(@ptrCast(self.handle));
|
|
}
|
|
|
|
pub fn outline(self: OutlineGlyph) Outline {
|
|
return .{ .handle = &self.handle.*.outline };
|
|
}
|
|
};
|
|
|
|
pub const PaletteData = struct {
|
|
handle: c.FT_Palette_Data,
|
|
|
|
pub fn numPalettes(self: PaletteData) u16 {
|
|
return self.handle.num_palettes;
|
|
}
|
|
|
|
pub fn paletteNameIDs(self: PaletteData) ?[]const u16 {
|
|
return self.handle.palette_name_ids[0..self.numPalettes()];
|
|
}
|
|
|
|
pub fn paletteFlags(self: PaletteData) ?[]const u16 {
|
|
return self.handle.palette_flags[0..self.numPalettes()];
|
|
}
|
|
|
|
pub fn paletteFlag(self: PaletteData, index: u32) PaletteFlags {
|
|
return @bitCast(self.handle.palette_flags[index]);
|
|
}
|
|
|
|
pub fn numPaletteEntries(self: PaletteData) u16 {
|
|
return self.handle.num_palette_entries;
|
|
}
|
|
|
|
pub fn paletteEntryNameIDs(self: PaletteData) ?[]const u16 {
|
|
return self.handle.palette_entry_name_ids[0..self.numPaletteEntries()];
|
|
}
|
|
};
|
|
|
|
pub const Raster = struct {
|
|
handle: c.FT_Raster,
|
|
|
|
pub const NewFunc = *const fn (memory: ?*anyopaque, raster: [*c]c.FT_Raster) callconv(.C) c_int;
|
|
pub const DoneFunc = *const fn (raster: [*c]c.FT_Raster) callconv(.C) void;
|
|
pub const ResetFunc = *const fn (raster: c.FT_Raster, pool_base: [*c]u8, pool_size: c_ulong) callconv(.C) void;
|
|
pub const SetModeFunc = *const fn (raster: c.FT_Raster, mode: c_ulong, args: ?*anyopaque) callconv(.C) c_int;
|
|
pub const RenderFunc = *const fn (raster: c.FT_Raster, params: Params) callconv(.C) c_int;
|
|
pub const BitTestFunc = *const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) c_int;
|
|
pub const BitSetFunc = *const fn (y: c_int, x: c_int, user: ?*anyopaque) callconv(.C) void;
|
|
pub const SpanFunc = *const fn (y: c_int, count: c_int, spans: [*]const Span, user: *anyopaque) callconv(.C) void;
|
|
|
|
pub const Params = extern struct {
|
|
target: [*c]const c.FT_Bitmap,
|
|
source: [*]const u8,
|
|
flags: Flags,
|
|
gray_spans: SpanFunc,
|
|
black_spans: ?SpanFunc = null, // unused
|
|
bit_test: ?BitTestFunc = null, // unused
|
|
bit_set: ?BitSetFunc = null, // unused
|
|
user: ?*anyopaque = null,
|
|
clip_box: BBox,
|
|
};
|
|
|
|
pub const Flags = packed struct(c_int) {
|
|
aa: bool = false,
|
|
direct: bool = false,
|
|
clip: bool = false,
|
|
sdf: bool = false,
|
|
_padding: u28 = 0,
|
|
};
|
|
};
|
|
|
|
pub const Size = struct {
|
|
handle: c.FT_Size,
|
|
|
|
pub fn face(self: Size) Face {
|
|
return Face{ .handle = self.handle.*.face };
|
|
}
|
|
|
|
pub fn generic(self: Size) Generic {
|
|
return self.handle.*.generic;
|
|
}
|
|
|
|
pub fn metrics(self: Size) SizeMetrics {
|
|
return self.handle.*.metrics;
|
|
}
|
|
|
|
pub fn activate(self: Size) Error!void {
|
|
try intToError(c.FT_Activate_Size(self.handle));
|
|
}
|
|
|
|
pub fn deinit(self: Size) void {
|
|
intToError(c.FT_Done_Size(self.handle)) catch |err| {
|
|
std.log.err("mach/freetype: Failed to destroy Size: {}", .{err});
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const Stroker = struct {
|
|
pub const BorderCounts = struct {
|
|
points: u32,
|
|
contours: u32,
|
|
};
|
|
|
|
handle: c.FT_Stroker,
|
|
|
|
pub fn set(self: Stroker, radius: i32, line_cap: LineCap, line_join: LineJoin, miter_limit: i32) void {
|
|
c.FT_Stroker_Set(self.handle, radius, @intFromEnum(line_cap), @intFromEnum(line_join), miter_limit);
|
|
}
|
|
|
|
pub fn rewind(self: Stroker) void {
|
|
c.FT_Stroker_Rewind(self.handle);
|
|
}
|
|
|
|
pub fn parseOutline(self: Stroker, outline: Outline, opened: bool) Error!void {
|
|
try intToError(c.FT_Stroker_ParseOutline(self.handle, outline.handle, if (opened) 1 else 0));
|
|
}
|
|
|
|
pub fn beginSubPath(self: Stroker, to: *Vector, open: bool) Error!void {
|
|
try intToError(c.FT_Stroker_BeginSubPath(self.handle, to, if (open) 1 else 0));
|
|
}
|
|
|
|
pub fn endSubPath(self: Stroker) Error!void {
|
|
try intToError(c.FT_Stroker_EndSubPath(self.handle));
|
|
}
|
|
|
|
pub fn lineTo(self: Stroker, to: *Vector) Error!void {
|
|
try intToError(c.FT_Stroker_LineTo(self.handle, to));
|
|
}
|
|
|
|
pub fn conicTo(self: Stroker, control: *Vector, to: *Vector) Error!void {
|
|
try intToError(c.FT_Stroker_ConicTo(self.handle, control, to));
|
|
}
|
|
|
|
pub fn cubicTo(self: Stroker, control_0: *Vector, control_1: *Vector, to: *Vector) Error!void {
|
|
try intToError(c.FT_Stroker_CubicTo(self.handle, control_0, control_1, to));
|
|
}
|
|
|
|
pub fn getBorderCounts(self: Stroker, border: Border) Error!BorderCounts {
|
|
var counts: BorderCounts = undefined;
|
|
try intToError(c.FT_Stroker_GetBorderCounts(self.handle, @intFromEnum(border), &counts.points, &counts.contours));
|
|
return counts;
|
|
}
|
|
|
|
pub fn exportBorder(self: Stroker, border: Border, outline: *Outline) void {
|
|
c.FT_Stroker_ExportBorder(self.handle, @intFromEnum(border), outline.handle);
|
|
}
|
|
|
|
pub fn getCounts(self: Stroker) Error!BorderCounts {
|
|
var counts: BorderCounts = undefined;
|
|
try intToError(c.FT_Stroker_GetCounts(self.handle, &counts.points, &counts.contours));
|
|
return counts;
|
|
}
|
|
|
|
pub fn exportAll(self: Stroker, outline: *Outline) void {
|
|
c.FT_Stroker_Export(self.handle, outline.handle);
|
|
}
|
|
|
|
pub fn deinit(self: Stroker) void {
|
|
c.FT_Stroker_Done(self.handle);
|
|
}
|
|
};
|
|
|
|
pub const SvgGlyph = struct {
|
|
handle: c.FT_SvgGlyph,
|
|
|
|
pub fn deinit(self: SvgGlyph) void {
|
|
c.FT_Done_Glyph(@ptrCast(self.handle));
|
|
}
|
|
|
|
pub fn svgBuffer(self: SvgGlyph) []const u8 {
|
|
return self.handle.*.svg_document[0..self.svgBufferLen()];
|
|
}
|
|
|
|
pub fn svgBufferLen(self: SvgGlyph) u32 {
|
|
return @intCast(self.handle.*.svg_document_length);
|
|
}
|
|
|
|
pub fn glyphIndex(self: SvgGlyph) u32 {
|
|
return @intCast(self.handle.*.glyph_index);
|
|
}
|
|
|
|
pub fn metrics(self: SvgGlyph) SizeMetrics {
|
|
return self.handle.*.metrics;
|
|
}
|
|
|
|
pub fn unitsPerEM(self: SvgGlyph) u16 {
|
|
return self.handle.*.units_per_EM;
|
|
}
|
|
|
|
pub fn startGlyphID(self: SvgGlyph) u16 {
|
|
return self.handle.*.start_glyph_id;
|
|
}
|
|
|
|
pub fn endGlyphID(self: SvgGlyph) u16 {
|
|
return self.handle.*.end_glyph_id;
|
|
}
|
|
|
|
pub fn transform(self: SvgGlyph) Matrix {
|
|
return self.handle.*.transform;
|
|
}
|
|
|
|
pub fn delta(self: SvgGlyph) Vector {
|
|
return self.handle.*.delta;
|
|
}
|
|
};
|
|
|
|
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 intToError(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,
|
|
};
|
|
}
|
|
|
|
pub fn errorToInt(err: Error) c_int {
|
|
return switch (err) {
|
|
Error.CannotOpenResource => c.FT_Err_Cannot_Open_Resource,
|
|
Error.UnknownFileFormat => c.FT_Err_Unknown_File_Format,
|
|
Error.InvalidFileFormat => c.FT_Err_Invalid_File_Format,
|
|
Error.InvalidVersion => c.FT_Err_Invalid_Version,
|
|
Error.LowerModuleVersion => c.FT_Err_Lower_Module_Version,
|
|
Error.InvalidArgument => c.FT_Err_Invalid_Argument,
|
|
Error.UnimplementedFeature => c.FT_Err_Unimplemented_Feature,
|
|
Error.InvalidTable => c.FT_Err_Invalid_Table,
|
|
Error.InvalidOffset => c.FT_Err_Invalid_Offset,
|
|
Error.ArrayTooLarge => c.FT_Err_Array_Too_Large,
|
|
Error.MissingModule => c.FT_Err_Missing_Module,
|
|
Error.MissingProperty => c.FT_Err_Missing_Property,
|
|
Error.InvalidGlyphIndex => c.FT_Err_Invalid_Glyph_Index,
|
|
Error.InvalidCharacterCode => c.FT_Err_Invalid_Character_Code,
|
|
Error.InvalidGlyphFormat => c.FT_Err_Invalid_Glyph_Format,
|
|
Error.CannotRenderGlyph => c.FT_Err_Cannot_Render_Glyph,
|
|
Error.InvalidOutline => c.FT_Err_Invalid_Outline,
|
|
Error.InvalidComposite => c.FT_Err_Invalid_Composite,
|
|
Error.TooManyHints => c.FT_Err_Too_Many_Hints,
|
|
Error.InvalidPixelSize => c.FT_Err_Invalid_Pixel_Size,
|
|
Error.InvalidHandle => c.FT_Err_Invalid_Handle,
|
|
Error.InvalidLibraryHandle => c.FT_Err_Invalid_Library_Handle,
|
|
Error.InvalidDriverHandle => c.FT_Err_Invalid_Driver_Handle,
|
|
Error.InvalidFaceHandle => c.FT_Err_Invalid_Face_Handle,
|
|
Error.InvalidSizeHandle => c.FT_Err_Invalid_Size_Handle,
|
|
Error.InvalidSlotHandle => c.FT_Err_Invalid_Slot_Handle,
|
|
Error.InvalidCharMapHandle => c.FT_Err_Invalid_CharMap_Handle,
|
|
Error.InvalidCacheHandle => c.FT_Err_Invalid_Cache_Handle,
|
|
Error.InvalidStreamHandle => c.FT_Err_Invalid_Stream_Handle,
|
|
Error.TooManyDrivers => c.FT_Err_Too_Many_Drivers,
|
|
Error.TooManyExtensions => c.FT_Err_Too_Many_Extensions,
|
|
Error.OutOfMemory => c.FT_Err_Out_Of_Memory,
|
|
Error.UnlistedObject => c.FT_Err_Unlisted_Object,
|
|
Error.CannotOpenStream => c.FT_Err_Cannot_Open_Stream,
|
|
Error.InvalidStreamSeek => c.FT_Err_Invalid_Stream_Seek,
|
|
Error.InvalidStreamSkip => c.FT_Err_Invalid_Stream_Skip,
|
|
Error.InvalidStreamRead => c.FT_Err_Invalid_Stream_Read,
|
|
Error.InvalidStreamOperation => c.FT_Err_Invalid_Stream_Operation,
|
|
Error.InvalidFrameOperation => c.FT_Err_Invalid_Frame_Operation,
|
|
Error.NestedFrameAccess => c.FT_Err_Nested_Frame_Access,
|
|
Error.InvalidFrameRead => c.FT_Err_Invalid_Frame_Read,
|
|
Error.RasterUninitialized => c.FT_Err_Raster_Uninitialized,
|
|
Error.RasterCorrupted => c.FT_Err_Raster_Corrupted,
|
|
Error.RasterOverflow => c.FT_Err_Raster_Overflow,
|
|
Error.RasterNegativeHeight => c.FT_Err_Raster_Negative_Height,
|
|
Error.TooManyCaches => c.FT_Err_Too_Many_Caches,
|
|
Error.InvalidOpcode => c.FT_Err_Invalid_Opcode,
|
|
Error.TooFewArguments => c.FT_Err_Too_Few_Arguments,
|
|
Error.StackOverflow => c.FT_Err_Stack_Overflow,
|
|
Error.CodeOverflow => c.FT_Err_Code_Overflow,
|
|
Error.BadArgument => c.FT_Err_Bad_Argument,
|
|
Error.DivideByZero => c.FT_Err_Divide_By_Zero,
|
|
Error.InvalidReference => c.FT_Err_Invalid_Reference,
|
|
Error.DebugOpCode => c.FT_Err_Debug_OpCode,
|
|
Error.ENDFInExecStream => c.FT_Err_ENDF_In_Exec_Stream,
|
|
Error.NestedDEFS => c.FT_Err_Nested_DEFS,
|
|
Error.InvalidCodeRange => c.FT_Err_Invalid_CodeRange,
|
|
Error.ExecutionTooLong => c.FT_Err_Execution_Too_Long,
|
|
Error.TooManyFunctionDefs => c.FT_Err_Too_Many_Function_Defs,
|
|
Error.TooManyInstructionDefs => c.FT_Err_Too_Many_Instruction_Defs,
|
|
Error.TableMissing => c.FT_Err_Table_Missing,
|
|
Error.HorizHeaderMissing => c.FT_Err_Horiz_Header_Missing,
|
|
Error.LocationsMissing => c.FT_Err_Locations_Missing,
|
|
Error.NameTableMissing => c.FT_Err_Name_Table_Missing,
|
|
Error.CMapTableMissing => c.FT_Err_CMap_Table_Missing,
|
|
Error.HmtxTableMissing => c.FT_Err_Hmtx_Table_Missing,
|
|
Error.PostTableMissing => c.FT_Err_Post_Table_Missing,
|
|
Error.InvalidHorizMetrics => c.FT_Err_Invalid_Horiz_Metrics,
|
|
Error.InvalidCharMapFormat => c.FT_Err_Invalid_CharMap_Format,
|
|
Error.InvalidPPem => c.FT_Err_Invalid_PPem,
|
|
Error.InvalidVertMetrics => c.FT_Err_Invalid_Vert_Metrics,
|
|
Error.CouldNotFindContext => c.FT_Err_Could_Not_Find_Context,
|
|
Error.InvalidPostTableFormat => c.FT_Err_Invalid_Post_Table_Format,
|
|
Error.InvalidPostTable => c.FT_Err_Invalid_Post_Table,
|
|
Error.Syntax => c.FT_Err_Syntax_Error,
|
|
Error.StackUnderflow => c.FT_Err_Stack_Underflow,
|
|
Error.Ignore => c.FT_Err_Ignore,
|
|
Error.NoUnicodeGlyphName => c.FT_Err_No_Unicode_Glyph_Name,
|
|
Error.MissingStartfontField => c.FT_Err_Missing_Startfont_Field,
|
|
Error.MissingFontField => c.FT_Err_Missing_Font_Field,
|
|
Error.MissingSizeField => c.FT_Err_Missing_Size_Field,
|
|
Error.MissingFontboundingboxField => c.FT_Err_Missing_Fontboundingbox_Field,
|
|
Error.MissingCharsField => c.FT_Err_Missing_Chars_Field,
|
|
Error.MissingStartcharField => c.FT_Err_Missing_Startchar_Field,
|
|
Error.MissingEncodingField => c.FT_Err_Missing_Encoding_Field,
|
|
Error.MissingBbxField => c.FT_Err_Missing_Bbx_Field,
|
|
Error.BbxTooBig => c.FT_Err_Bbx_Too_Big,
|
|
Error.CorruptedFontHeader => c.FT_Err_Corrupted_Font_Header,
|
|
Error.CorruptedFontGlyphs => c.FT_Err_Corrupted_Font_Glyphs,
|
|
};
|
|
}
|
|
|
|
pub fn mulDiv(a: i32, b: i32, _c: i32) i32 {
|
|
return @intCast(c.FT_MulDiv(a, b, _c));
|
|
}
|
|
|
|
pub fn mulFix(a: i32, b: i32) i32 {
|
|
return @intCast(c.FT_MulFix(a, b));
|
|
}
|
|
|
|
pub fn divFix(a: i32, b: i32) i32 {
|
|
return @intCast(c.FT_DivFix(a, b));
|
|
}
|
|
|
|
pub fn roundFix(a: i32) i32 {
|
|
return @intCast(c.FT_RoundFix(a));
|
|
}
|
|
|
|
pub fn ceilFix(a: i32) i32 {
|
|
return @intCast(c.FT_CeilFix(a));
|
|
}
|
|
|
|
pub fn floorFix(a: i32) i32 {
|
|
return @intCast(c.FT_FloorFix(a));
|
|
}
|
|
|
|
pub fn vectorTransform(vec: *Vector, matrix: Matrix) void {
|
|
c.FT_Vector_Transform(vec, &matrix);
|
|
}
|
|
|
|
pub fn matrixMul(a: Matrix, b: *Matrix) void {
|
|
c.FT_Matrix_Multiply(&a, b);
|
|
}
|
|
|
|
pub fn matrixInvert(m: *Matrix) Error!void {
|
|
try intToError(c.FT_Matrix_Invert(m));
|
|
}
|
|
|
|
pub fn angleDiff(a: i32, b: i32) i32 {
|
|
return @intCast(c.FT_Angle_Diff(a, b));
|
|
}
|
|
|
|
pub fn vectorUnit(vec: *Vector, angle: i32) void {
|
|
c.FT_Vector_Unit(vec, angle);
|
|
}
|
|
|
|
pub fn vectorRotate(vec: *Vector, angle: i32) void {
|
|
c.FT_Vector_Rotate(vec, angle);
|
|
}
|
|
|
|
pub fn vectorLength(vec: *Vector) i32 {
|
|
return @intCast(c.FT_Vector_Length(vec));
|
|
}
|
|
|
|
pub fn vectorPolarize(vec: *Vector, length: *c_long, angle: *c_long) void {
|
|
c.FT_Vector_Polarize(vec, length, angle);
|
|
}
|
|
|
|
pub fn vectorFromPolar(vec: *Vector, length: i32, angle: i32) void {
|
|
c.FT_Vector_From_Polar(vec, length, angle);
|
|
}
|
|
|
|
pub fn getCharmapIndex(self: [*c]CharMap) ?u32 {
|
|
const i = c.FT_Get_Charmap_Index(self);
|
|
return if (i == -1) null else @intCast(i);
|
|
}
|
|
|
|
const std = @import("std");
|
|
const font_assets = struct {
|
|
pub const fira_sans_regular_ttf = @embedFile("assets/FiraSans-Regular.ttf");
|
|
};
|
|
|
|
test "reference declarations" {
|
|
// TODO: we cannot refAllDeclsRecursive(@This()) because of some errors in the
|
|
// translate-c output
|
|
std.testing.refAllDecls(@This());
|
|
|
|
std.testing.refAllDeclsRecursive(Bitmap);
|
|
std.testing.refAllDeclsRecursive(BitmapGlyph);
|
|
std.testing.refAllDeclsRecursive(Affine23);
|
|
std.testing.refAllDeclsRecursive(Face);
|
|
std.testing.refAllDeclsRecursive(Glyph);
|
|
std.testing.refAllDeclsRecursive(GlyphLayersIterator);
|
|
std.testing.refAllDeclsRecursive(GlyphSlot);
|
|
std.testing.refAllDeclsRecursive(Library);
|
|
std.testing.refAllDeclsRecursive(OpenArgs);
|
|
std.testing.refAllDeclsRecursive(Outline);
|
|
std.testing.refAllDeclsRecursive(OutlineGlyph);
|
|
std.testing.refAllDeclsRecursive(PaletteData);
|
|
std.testing.refAllDeclsRecursive(Raster);
|
|
std.testing.refAllDeclsRecursive(Size);
|
|
std.testing.refAllDeclsRecursive(Stroker);
|
|
std.testing.refAllDeclsRecursive(SvgGlyph);
|
|
}
|
|
|
|
test "create face from memory" {
|
|
const lib = try Library.init();
|
|
_ = try lib.createFaceMemory(font_assets.fira_sans_regular_ttf, 0);
|
|
}
|
|
|
|
test "create stroker" {
|
|
const lib = try Library.init();
|
|
_ = try lib.createStroker();
|
|
}
|
|
|
|
test "load glyph" {
|
|
const lib = try Library.init();
|
|
const face = try lib.createFaceMemory(font_assets.fira_sans_regular_ttf, 0);
|
|
|
|
try face.setPixelSizes(100, 100);
|
|
try face.setCharSize(10 * 10, 0, 72, 0);
|
|
|
|
try face.loadGlyph(205, .{});
|
|
try face.loadChar('A', .{});
|
|
|
|
face.deinit();
|
|
}
|
|
|
|
test "charmap iterator" {
|
|
const lib = try Library.init();
|
|
const face = try lib.createFaceMemory(font_assets.fira_sans_regular_ttf, 0);
|
|
var iterator = face.iterateCharmap();
|
|
var old_char: u32 = 0;
|
|
while (iterator.next()) |char| {
|
|
try std.testing.expect(old_char != char);
|
|
old_char = char;
|
|
}
|
|
}
|
|
|
|
test "get name index" {
|
|
const lib = try Library.init();
|
|
const face = try lib.createFaceMemory(font_assets.fira_sans_regular_ttf, 0);
|
|
try std.testing.expectEqual(@as(u32, 1120), face.getNameIndex("summation").?);
|
|
}
|
|
|
|
test "get index name" {
|
|
const lib = try Library.init();
|
|
const face = try lib.createFaceMemory(font_assets.fira_sans_regular_ttf, 0);
|
|
var buf: [32]u8 = undefined;
|
|
try face.getGlyphName(1120, &buf);
|
|
try std.testing.expectEqualStrings(std.mem.sliceTo(&buf, 0), "summation");
|
|
}
|
|
|
|
test "error convertion" {
|
|
const expectError = @import("std").testing.expectError;
|
|
|
|
try intToError(c.FT_Err_Ok);
|
|
try expectError(Error.OutOfMemory, intToError(c.FT_Err_Out_Of_Memory));
|
|
}
|