freetype: ~99% Core-API Coverage
- breaking structure changes - optimazed examples - more tests
This commit is contained in:
parent
db377459c4
commit
04a0a79ef6
21 changed files with 1176 additions and 549 deletions
|
|
@ -15,7 +15,7 @@ const Vec4 = @Vector(4, f32);
|
||||||
|
|
||||||
const GlyphInfo = struct {
|
const GlyphInfo = struct {
|
||||||
uv_data: UVData,
|
uv_data: UVData,
|
||||||
metrics: ft.Glyph.GlyphMetrics,
|
metrics: ft.GlyphMetrics,
|
||||||
};
|
};
|
||||||
|
|
||||||
face: ft.Face,
|
face: ft.Face,
|
||||||
|
|
@ -63,7 +63,7 @@ fn write(ctx: WriterContext, bytes: []const u8) ft.Error!usize {
|
||||||
switch (char) {
|
switch (char) {
|
||||||
'\n' => {
|
'\n' => {
|
||||||
offset[0] = 0;
|
offset[0] = 0;
|
||||||
offset[1] -= @intToFloat(f32, ctx.label.face.sizeMetrics().?.height >> 6);
|
offset[1] -= @intToFloat(f32, ctx.label.face.size().metrics().height >> 6);
|
||||||
},
|
},
|
||||||
' ' => {
|
' ' => {
|
||||||
const v = ctx.label.char_map.getOrPut(char) catch unreachable;
|
const v = ctx.label.char_map.getOrPut(char) catch unreachable;
|
||||||
|
|
@ -73,7 +73,7 @@ fn write(ctx: WriterContext, bytes: []const u8) ft.Error!usize {
|
||||||
const glyph = ctx.label.face.glyph;
|
const glyph = ctx.label.face.glyph;
|
||||||
v.value_ptr.* = GlyphInfo{
|
v.value_ptr.* = GlyphInfo{
|
||||||
.uv_data = undefined,
|
.uv_data = undefined,
|
||||||
.metrics = glyph.metrics(),
|
.metrics = glyph().metrics(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
offset[0] += @intToFloat(f32, v.value_ptr.metrics.horiAdvance >> 6);
|
offset[0] += @intToFloat(f32, v.value_ptr.metrics.horiAdvance >> 6);
|
||||||
|
|
@ -83,7 +83,7 @@ fn write(ctx: WriterContext, bytes: []const u8) ft.Error!usize {
|
||||||
if (!v.found_existing) {
|
if (!v.found_existing) {
|
||||||
try ctx.label.face.setCharSize(ctx.label.size * 64, 0, 50, 0);
|
try ctx.label.face.setCharSize(ctx.label.size * 64, 0, 50, 0);
|
||||||
try ctx.label.face.loadChar(char, .{ .render = true });
|
try ctx.label.face.loadChar(char, .{ .render = true });
|
||||||
const glyph = ctx.label.face.glyph;
|
const glyph = ctx.label.face.glyph();
|
||||||
const glyph_bitmap = glyph.bitmap();
|
const glyph_bitmap = glyph.bitmap();
|
||||||
const glyph_width = glyph_bitmap.width();
|
const glyph_width = glyph_bitmap.width();
|
||||||
const glyph_height = glyph_bitmap.rows();
|
const glyph_height = glyph_bitmap.rows();
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,10 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
|
|
||||||
const example_run_cmd = example_exe.run();
|
const example_run_cmd = example_exe.run();
|
||||||
example_run_cmd.step.dependOn(b.getInstallStep());
|
example_run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
if (b.args) |args| {
|
||||||
|
example_run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
const example_run_step = b.step("run-example-" ++ example, "Run '" ++ example ++ "' example");
|
const example_run_step = b.step("run-example-" ++ example, "Run '" ++ example ++ "' example");
|
||||||
example_run_step.dependOn(&example_run_cmd.step);
|
example_run_step.dependOn(&example_run_cmd.step);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const OutlinePrinter = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outlineExists(self: Self) bool {
|
pub fn outlineExists(self: Self) bool {
|
||||||
const outline = self.face.glyph.outline() orelse return false;
|
const outline = self.face.glyph().outline() orelse return false;
|
||||||
if (outline.numContours() <= 0 or outline.numPoints() <= 0)
|
if (outline.numContours() <= 0 or outline.numPoints() <= 0)
|
||||||
return false;
|
return false;
|
||||||
outline.check() catch return false;
|
outline.check() catch return false;
|
||||||
|
|
@ -48,7 +48,7 @@ const OutlinePrinter = struct {
|
||||||
.yx = 0 * multiplier,
|
.yx = 0 * multiplier,
|
||||||
.yy = -1 * multiplier,
|
.yy = -1 * multiplier,
|
||||||
};
|
};
|
||||||
self.face.glyph.outline().?.transform(matrix);
|
self.face.glyph().outline().?.transform(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extractOutline(self: *Self) !void {
|
pub fn extractOutline(self: *Self) !void {
|
||||||
|
|
@ -61,12 +61,12 @@ const OutlinePrinter = struct {
|
||||||
.shift = 0,
|
.shift = 0,
|
||||||
.delta = 0,
|
.delta = 0,
|
||||||
};
|
};
|
||||||
try self.face.glyph.outline().?.decompose(self, callbacks);
|
try self.face.glyph().outline().?.decompose(self, callbacks);
|
||||||
try self.path_stream.writer().writeAll("' fill='#000'/>");
|
try self.path_stream.writer().writeAll("' fill='#000'/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn computeViewBox(self: *Self) !void {
|
pub fn computeViewBox(self: *Self) !void {
|
||||||
const boundingBox = try self.face.glyph.outline().?.bbox();
|
const boundingBox = try self.face.glyph().outline().?.bbox();
|
||||||
self.xMin = boundingBox.xMin;
|
self.xMin = boundingBox.xMin;
|
||||||
self.yMin = boundingBox.yMin;
|
self.yMin = boundingBox.yMin;
|
||||||
self.width = boundingBox.xMax - boundingBox.xMin;
|
self.width = boundingBox.xMax - boundingBox.xMin;
|
||||||
|
|
@ -99,7 +99,7 @@ const OutlinePrinter = struct {
|
||||||
self.path_stream.writer().print("C {d} {d}, {d} {d}, {d} {d}\t", .{ control_0.x, control_0.y, control_1.x, control_1.y, to.x, to.y }) catch unreachable;
|
self.path_stream.writer().print("C {d} {d}, {d} {d}, {d} {d}\t", .{ control_0.x, control_0.y, control_1.x, control_1.y, to.x, to.y }) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self: *Self, symbol: u8) !void {
|
pub fn run(self: *Self, symbol: u32) !void {
|
||||||
try self.face.loadChar(symbol, .{ .no_scale = true, .no_bitmap = true });
|
try self.face.loadChar(symbol, .{ .no_scale = true, .no_bitmap = true });
|
||||||
|
|
||||||
if (!self.outlineExists())
|
if (!self.outlineExists())
|
||||||
|
|
@ -118,5 +118,5 @@ pub fn main() !void {
|
||||||
|
|
||||||
var outline_printer = try OutlinePrinter.init(file);
|
var outline_printer = try OutlinePrinter.init(file);
|
||||||
defer outline_printer.deinit();
|
defer outline_printer.deinit();
|
||||||
try outline_printer.run('a');
|
try outline_printer.run(@as(u32, 'ë'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,27 @@
|
||||||
|
// zig build run-example-single-glyph -- B
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const freetype = @import("freetype");
|
const freetype = @import("freetype");
|
||||||
|
|
||||||
const WIDTH = 32;
|
|
||||||
const HEIGHT = 24;
|
|
||||||
|
|
||||||
fn drawBitmap(bitmap: freetype.Bitmap, x: usize, y: usize) [HEIGHT][WIDTH]u8 {
|
|
||||||
var figure = std.mem.zeroes([HEIGHT][WIDTH]u8);
|
|
||||||
var p: usize = 0;
|
|
||||||
var q: usize = 0;
|
|
||||||
const w = bitmap.width();
|
|
||||||
const x_max = x + w;
|
|
||||||
const y_max = y + bitmap.rows();
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < x_max - x) : (i += 1) {
|
|
||||||
var j: usize = 0;
|
|
||||||
while (j < y_max - y) : (j += 1) {
|
|
||||||
if (i < WIDTH and j < HEIGHT) {
|
|
||||||
figure[j][i] |= bitmap.buffer()[q * w + p];
|
|
||||||
q += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q = 0;
|
|
||||||
p += 1;
|
|
||||||
}
|
|
||||||
return figure;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
defer _ = gpa.deinit();
|
||||||
|
const allocator = gpa.allocator();
|
||||||
|
var args = try std.process.argsAlloc(allocator);
|
||||||
|
defer std.process.argsFree(allocator, args);
|
||||||
|
|
||||||
const lib = try freetype.Library.init();
|
const lib = try freetype.Library.init();
|
||||||
defer lib.deinit();
|
defer lib.deinit();
|
||||||
|
|
||||||
const face = try lib.newFace("upstream/assets/FiraSans-Regular.ttf", 0);
|
const face = try lib.newFace("upstream/assets/FiraSans-Regular.ttf", 0);
|
||||||
defer face.deinit();
|
try face.setCharSize(60 * 48, 0, 50, 0);
|
||||||
|
try face.loadChar(args[1][0], .{ .render = true });
|
||||||
try face.setCharSize(40 * 64, 0, 50, 0);
|
const bitmap = face.glyph().bitmap();
|
||||||
try face.loadChar('@', .{ .render = true });
|
|
||||||
|
|
||||||
const glyph = face.glyph;
|
|
||||||
const x = @intCast(usize, glyph.bitmapLeft());
|
|
||||||
const y = HEIGHT - @intCast(usize, glyph.bitmapTop());
|
|
||||||
|
|
||||||
var figure = drawBitmap(glyph.bitmap(), x, y);
|
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < HEIGHT) : (i += 1) {
|
while (i < bitmap.rows()) : (i += 1) {
|
||||||
var j: usize = 0;
|
var j: usize = 0;
|
||||||
while (j < WIDTH) : (j += 1) {
|
while (j < bitmap.width()) : (j += 1) {
|
||||||
const char: u8 = switch (figure[i][j]) {
|
const char: u8 = switch (bitmap.buffer()[i * bitmap.width() + j]) {
|
||||||
0 => ' ',
|
0 => ' ',
|
||||||
1...128 => ';',
|
1...128 => ';',
|
||||||
else => '#',
|
else => '#',
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
|
||||||
const Error = @import("error.zig").Error;
|
|
||||||
const intToError = @import("error.zig").intToError;
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
|
||||||
const Bitmap = @import("Bitmap.zig");
|
|
||||||
const Error = @import("error.zig").Error;
|
|
||||||
const intToError = @import("error.zig").intToError;
|
|
||||||
|
|
||||||
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 intToError(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);
|
|
||||||
}
|
|
||||||
|
|
@ -1,101 +1,59 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig");
|
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 utils = @import("utils.zig");
|
||||||
|
const intToError = @import("error.zig").intToError;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const GlyphSlot = @import("freetype.zig").GlyphSlot;
|
||||||
|
const LoadFlags = @import("freetype.zig").LoadFlags;
|
||||||
|
const FaceFlags = @import("freetype.zig").FaceFlags;
|
||||||
|
const StyleFlags = @import("freetype.zig").StyleFlags;
|
||||||
|
const FSType = @import("freetype.zig").FSType;
|
||||||
|
const OpenArgs = @import("freetype.zig").OpenArgs;
|
||||||
|
const KerningMode = @import("freetype.zig").KerningMode;
|
||||||
|
const Encoding = @import("freetype.zig").Encoding;
|
||||||
|
const CharMap = @import("freetype.zig").CharMap;
|
||||||
|
const Size = @import("freetype.zig").Size;
|
||||||
|
const SizeRequest = @import("freetype.zig").SizeRequest;
|
||||||
|
const BitmapSize = @import("freetype.zig").BitmapSize;
|
||||||
|
const Matrix = @import("types.zig").Matrix;
|
||||||
|
const BBox = @import("types.zig").BBox;
|
||||||
|
const Vector = @import("image.zig").Vector;
|
||||||
|
const RootTransform = @import("color.zig").RootTransform;
|
||||||
|
const PaintFormat = @import("color.zig").PaintFormat;
|
||||||
|
const Color = @import("color.zig").Color;
|
||||||
|
const ClipBox = @import("color.zig").ClipBox;
|
||||||
|
const OpaquePaint = @import("color.zig").OpaquePaint;
|
||||||
|
const Paint = @import("color.zig").Paint;
|
||||||
|
const PaletteData = @import("color.zig").PaletteData;
|
||||||
|
const GlyphLayersIterator = @import("color.zig").GlyphLayersIterator;
|
||||||
|
|
||||||
const Face = @This();
|
const Face = @This();
|
||||||
|
|
||||||
pub const SizeMetrics = extern struct {
|
pub const CharmapIterator = struct {
|
||||||
x_ppem: u16,
|
face: Face,
|
||||||
y_ppem: u16,
|
index: u32,
|
||||||
x_scale: c_long,
|
charcode: u32,
|
||||||
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) {
|
pub fn init(face: Face) CharmapIterator {
|
||||||
no_scale = c.FT_LOAD_NO_SCALE,
|
var i: u32 = 0;
|
||||||
no_hinting = c.FT_LOAD_NO_HINTING,
|
const cc = c.FT_Get_First_Char(face.handle, &i);
|
||||||
render = c.FT_LOAD_RENDER,
|
return .{
|
||||||
no_bitmap = c.FT_LOAD_NO_BITMAP,
|
.face = face,
|
||||||
vertical_layout = c.FT_LOAD_VERTICAL_LAYOUT,
|
.index = i,
|
||||||
force_autohint = c.FT_LOAD_FORCE_AUTOHINT,
|
.charcode = @intCast(u32, cc),
|
||||||
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) {
|
pub fn next(self: *CharmapIterator) ?u32 {
|
||||||
bold = c.FT_STYLE_FLAG_BOLD,
|
self.charcode = @intCast(u32, c.FT_Get_Next_Char(self.face.handle, self.charcode, &self.index));
|
||||||
italic = c.FT_STYLE_FLAG_ITALIC,
|
return if (self.index != 0)
|
||||||
};
|
self.charcode
|
||||||
|
else
|
||||||
pub fn toBitFields(flags: StyleFlags) u2 {
|
null;
|
||||||
return utils.structToBitFields(u2, StyleFlags, Flag, flags);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handle: c.FT_Face,
|
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 {
|
pub fn deinit(self: Face) void {
|
||||||
intToError(c.FT_Done_Face(self.handle)) catch |err| {
|
intToError(c.FT_Done_Face(self.handle)) catch |err| {
|
||||||
|
|
@ -117,8 +75,16 @@ pub fn attachMemory(self: Face, bytes: []const u8) Error!void {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attachStream(self: Face, args: types.OpenArgs) Error!void {
|
pub fn attachStream(self: Face, args: OpenArgs) Error!void {
|
||||||
return intToError(c.FT_Attach_Stream(self.handle, &args.toCInterface()));
|
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, flags.cast()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loadChar(self: Face, char: u32, flags: LoadFlags) Error!void {
|
||||||
|
return intToError(c.FT_Load_Char(self.handle, char, flags.cast()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setCharSize(self: Face, pt_width: i32, pt_height: i32, horz_resolution: u16, vert_resolution: u16) Error!void {
|
pub fn setCharSize(self: Face, pt_width: i32, pt_height: i32, horz_resolution: u16, vert_resolution: u16) Error!void {
|
||||||
|
|
@ -129,29 +95,277 @@ 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));
|
return intToError(c.FT_Set_Pixel_Sizes(self.handle, pixel_width, pixel_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadGlyph(self: Face, index: u32, flags: LoadFlags) Error!void {
|
pub fn requestSize(self: Face, req: SizeRequest) Error!void {
|
||||||
return intToError(c.FT_Load_Glyph(self.handle, index, flags.toBitFields()));
|
var req_mut = req;
|
||||||
|
return intToError(c.FT_Request_Size(self.handle, &req_mut));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadChar(self: Face, char: u32, flags: LoadFlags) Error!void {
|
pub fn selectSize(self: Face, strike_index: i32) Error!void {
|
||||||
return intToError(c.FT_Load_Char(self.handle, char, flags.toBitFields()));
|
return intToError(c.FT_Select_Size(self.handle, strike_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTransform(self: Face, matrix: ?types.Matrix, delta: ?types.Vector) Error!void {
|
pub fn setTransform(self: Face, matrix: ?Matrix, delta: ?Vector) Error!void {
|
||||||
var m = matrix orelse std.mem.zeroes(types.Matrix);
|
var matrix_mut = matrix;
|
||||||
var d = delta orelse std.mem.zeroes(types.Vector);
|
var delta_mut = delta;
|
||||||
return c.FT_Set_Transform(self.handle, @ptrCast(*c.FT_Matrix, &m), @ptrCast(*c.FT_Vector, &d));
|
return c.FT_Set_Transform(self.handle, if (matrix_mut) |*m| m else null, if (delta_mut) |*d| d else null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getCharIndex(self: Face, index: u32) ?u32 {
|
pub fn getTransform(self: Face) std.meta.Tuple(&.{ Matrix, Vector }) {
|
||||||
const i = c.FT_Get_Char_Index(self.handle, index);
|
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;
|
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 {
|
pub fn getNameIndex(self: Face, name: [:0]const u8) ?u32 {
|
||||||
var vec = std.mem.zeroes(types.Vector);
|
const i = c.FT_Get_Name_Index(self.handle, name);
|
||||||
try intToError(c.FT_Get_Kerning(self.handle, left_char_index, right_char_index, @enumToInt(mode), @ptrCast(*c.FT_Vector, &vec)));
|
return if (i == 0) null else i;
|
||||||
return vec;
|
}
|
||||||
|
|
||||||
|
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, @enumToInt(mode), &kerning));
|
||||||
|
return kerning;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getTrackKerning(self: Face, point_size: i32, degree: i32) Error!i32 {
|
||||||
|
var kerning: i32 = 0;
|
||||||
|
try intToError(c.FT_Get_Track_Kerning(self.handle, point_size, degree, &@intCast(c_long, kerning)));
|
||||||
|
return kerning;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getGlyphName(self: Face, index: u32) Error![]const u8 {
|
||||||
|
var name_buf: [30]u8 = undefined;
|
||||||
|
try intToError(c.FT_Get_Glyph_Name(self.handle, index, &name_buf, 30));
|
||||||
|
return std.mem.sliceTo(&name_buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPostscriptName(self: Face) ?[:0]const u8 {
|
||||||
|
return if (c.FT_Get_Postscript_Name(self.handle)) |face_name|
|
||||||
|
std.mem.span(face_name)
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getCharmapIterator(self: Face) CharmapIterator {
|
||||||
|
return CharmapIterator.init(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selectCharmap(self: Face, encoding: Encoding) Error!void {
|
||||||
|
return intToError(c.FT_Select_Charmap(self.handle, @enumToInt(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 FSType.from(@intCast(u10, 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([]u32, std.mem.sliceTo(chars, 0))
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getVariantsOfChar(self: Face, char: u32) ?[]u32 {
|
||||||
|
return if (c.FT_Face_GetVariantsOfChar(self.handle, char)) |variants|
|
||||||
|
@ptrCast([]u32, std.mem.sliceTo(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([]u32, std.mem.sliceTo(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, @enumToInt(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 (@intToEnum(PaintFormat, 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(u32, self.handle.*.num_faces);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn faceIndex(self: Face) u32 {
|
||||||
|
return @intCast(u32, self.handle.*.face_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn faceFlags(self: Face) FaceFlags {
|
||||||
|
return FaceFlags.from(@intCast(u19, self.handle.*.face_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn styleFlags(self: Face) StyleFlags {
|
||||||
|
return StyleFlags.from(@intCast(u2, self.handle.*.style_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn numGlyphs(self: Face) u32 {
|
||||||
|
return @intCast(u32, 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 numFixedSizes(self: Face) u32 {
|
||||||
|
return @intCast(u32, self.handle.*.num_fixed_sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn availableSizes(self: Face) ?BitmapSize {
|
||||||
|
return if (self.handle.*.available_sizes != null)
|
||||||
|
self.handle.*.available_sizes.*
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn numCharmaps(self: Face) u32 {
|
||||||
|
return @intCast(u32, self.handle.*.num_charmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn charmaps(self: Face) []const CharMap {
|
||||||
|
return @ptrCast([]const CharMap, 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 {
|
pub fn hasHorizontal(self: Face) bool {
|
||||||
|
|
@ -197,76 +411,3 @@ pub fn isCidKeyed(self: Face) bool {
|
||||||
pub fn isTricky(self: Face) bool {
|
pub fn isTricky(self: Face) bool {
|
||||||
return c.FT_IS_TRICKY(self.handle);
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,86 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig");
|
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 intToError = @import("error.zig").intToError;
|
const intToError = @import("error.zig").intToError;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const Stroker = @import("Stroker.zig");
|
||||||
|
const Library = @import("freetype.zig").Library;
|
||||||
|
const RenderMode = @import("freetype.zig").RenderMode;
|
||||||
|
const SizeMetrics = @import("freetype.zig").SizeMetrics;
|
||||||
|
const Matrix = @import("types.zig").Matrix;
|
||||||
|
const BBox = @import("types.zig").BBox;
|
||||||
|
const Outline = @import("image.zig").Outline;
|
||||||
|
const GlyphFormat = @import("image.zig").GlyphFormat;
|
||||||
|
const Vector = @import("image.zig").Vector;
|
||||||
|
const Bitmap = @import("image.zig").Bitmap;
|
||||||
|
|
||||||
const Glyph = @This();
|
const Glyph = @This();
|
||||||
|
|
||||||
pub const BBoxMode = enum(u2) {
|
pub const BBoxMode = enum(u2) {
|
||||||
// https://freetype.org/freetype2/docs/reference/ft2-glyph_management.html#ft_glyph_bbox_mode
|
// https://freetype.org/freetype2/docs/reference/ft2-glyph_management.html#ft_glyph_bbox_mode
|
||||||
// both `unscaled` and `subpixel` constants are set to 0
|
// both `unscaled` and `subpixel` are set to 0
|
||||||
unscaled_or_subpixels = c.FT_GLYPH_BBOX_UNSCALED,
|
unscaled_or_subpixels = c.FT_GLYPH_BBOX_UNSCALED,
|
||||||
gridfit = c.FT_GLYPH_BBOX_GRIDFIT,
|
gridfit = c.FT_GLYPH_BBOX_GRIDFIT,
|
||||||
truncate = c.FT_GLYPH_BBOX_TRUNCATE,
|
truncate = c.FT_GLYPH_BBOX_TRUNCATE,
|
||||||
pixels = c.FT_GLYPH_BBOX_PIXELS,
|
pixels = c.FT_GLYPH_BBOX_PIXELS,
|
||||||
};
|
};
|
||||||
pub const GlyphMetrics = c.FT_Glyph_Metrics;
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
handle: c.FT_Glyph,
|
handle: c.FT_Glyph,
|
||||||
|
|
||||||
pub fn init(handle: c.FT_Glyph) Glyph {
|
|
||||||
return Glyph{ .handle = handle };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: Glyph) void {
|
pub fn deinit(self: Glyph) void {
|
||||||
c.FT_Done_Glyph(self.handle);
|
c.FT_Done_Glyph(self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone(self: Glyph) Error!Glyph {
|
pub fn newGlyph(library: Library, glyph_format: GlyphFormat) Glyph {
|
||||||
var res = std.mem.zeroes(c.FT_Glyph);
|
var g: c.FT_Glyph = undefined;
|
||||||
try intToError(c.FT_Glyph_Copy(self.handle, &res));
|
return .{
|
||||||
return Glyph.init(res);
|
.handle = c.FT_New_Glyph(library.handle, @enumToInt(glyph_format), &g),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform(self: Glyph, matrix: ?types.Matrix, delta: ?types.Vector) Error!void {
|
pub fn copy(self: Glyph) Error!Glyph {
|
||||||
var m = matrix orelse std.mem.zeroes(types.Matrix);
|
var g: c.FT_Glyph = undefined;
|
||||||
var d = delta orelse std.mem.zeroes(types.Vector);
|
try intToError(c.FT_Glyph_Copy(self.handle, &g));
|
||||||
try intToError(c.FT_Glyph_Transform(self.handle, @ptrCast(*c.FT_Matrix, &m), @ptrCast(*c.FT_Vector, &d)));
|
return Glyph{ .handle = g };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getCBox(self: Glyph, bbox_mode: BBoxMode) types.BBox {
|
pub fn transform(self: Glyph, matrix: ?Matrix, delta: ?Vector) Error!void {
|
||||||
var res = std.mem.zeroes(types.BBox);
|
try intToError(c.FT_Glyph_Transform(self.handle, if (matrix) |m| &m else null, if (delta) |d| &d else null));
|
||||||
c.FT_Glyph_Get_CBox(self.handle, @enumToInt(bbox_mode), @ptrCast(*c.FT_BBox, &res));
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toBitmap(self: Glyph, render_mode: types.RenderMode, origin: ?types.Vector) Error!BitmapGlyph {
|
pub fn getCBox(self: Glyph, bbox_mode: BBoxMode) BBox {
|
||||||
var res = self.handle;
|
var b: BBox = undefined;
|
||||||
var o = origin orelse std.mem.zeroes(types.Vector);
|
c.FT_Glyph_Get_CBox(self.handle, @enumToInt(bbox_mode), &b);
|
||||||
try intToError(c.FT_Glyph_To_Bitmap(&res, @enumToInt(render_mode), @ptrCast(*c.FT_Vector, &o), 0));
|
return b;
|
||||||
return BitmapGlyph.init(@ptrCast(c.FT_BitmapGlyph, self.handle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stroke(self: Glyph, stroker: Stroker) Error!Glyph {
|
pub fn toBitmapGlyph(self: *Glyph, render_mode: RenderMode, origin: ?Vector) Error!BitmapGlyph {
|
||||||
var res = self.handle;
|
try intToError(c.FT_Glyph_To_Bitmap(&self.handle, @enumToInt(render_mode), if (origin) |o| &o else null, 1));
|
||||||
try intToError(c.FT_Glyph_Stroke(&res, stroker.handle, 0));
|
return BitmapGlyph{ .handle = @ptrCast(c.FT_BitmapGlyph, self.handle) };
|
||||||
return Glyph.init(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strokeBorder(self: Glyph, stroker: Stroker, inside: bool) Error!Glyph {
|
pub fn copyBitmapGlyph(self: *Glyph, render_mode: RenderMode, origin: ?Vector) Error!BitmapGlyph {
|
||||||
var res = self.handle;
|
try intToError(c.FT_Glyph_To_Bitmap(&self.handle, @enumToInt(render_mode), if (origin) |o| &o else null, 0));
|
||||||
try intToError(c.FT_Glyph_StrokeBorder(&res, stroker.handle, if (inside) 1 else 0, 0));
|
return BitmapGlyph{ .handle = @ptrCast(c.FT_BitmapGlyph, self.handle) };
|
||||||
return Glyph.init(res);
|
}
|
||||||
|
|
||||||
|
pub fn castBitmapGlyph(self: Glyph) Error!BitmapGlyph {
|
||||||
|
return BitmapGlyph{ .handle = @ptrCast(c.FT_BitmapGlyph, self.handle) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn castOutlineGlyph(self: Glyph) Error!OutlineGlyph {
|
||||||
|
return OutlineGlyph{ .handle = @ptrCast(c.FT_OutlineGlyph, self.handle) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn castSvgGlyph(self: Glyph) Error!SvgGlyph {
|
||||||
|
return SvgGlyph{ .handle = @ptrCast(c.FT_SvgGlyph, 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 {
|
pub fn format(self: Glyph) GlyphFormat {
|
||||||
|
|
@ -84,3 +94,79 @@ pub fn advanceX(self: Glyph) isize {
|
||||||
pub fn advanceY(self: Glyph) isize {
|
pub fn advanceY(self: Glyph) isize {
|
||||||
return self.handle.*.advance.y;
|
return self.handle.*.advance.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SvgGlyph = struct {
|
||||||
|
handle: c.FT_SvgGlyph,
|
||||||
|
|
||||||
|
pub fn deinit(self: SvgGlyph) void {
|
||||||
|
c.FT_Done_Glyph(@ptrCast(c.FT_Glyph, self.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn svgBuffer(self: SvgGlyph) []const u8 {
|
||||||
|
return self.handle.*.svg_document[0..self.svgBufferLen()];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn svgBufferLen(self: SvgGlyph) usize {
|
||||||
|
return self.handle.*.svg_document_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glyphIndex(self: SvgGlyph) usize {
|
||||||
|
return 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 BitmapGlyph = struct {
|
||||||
|
handle: c.FT_BitmapGlyph,
|
||||||
|
|
||||||
|
pub fn deinit(self: BitmapGlyph) void {
|
||||||
|
c.FT_Done_Glyph(@ptrCast(c.FT_Glyph, 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 OutlineGlyph = struct {
|
||||||
|
handle: c.FT_OutlineGlyph,
|
||||||
|
|
||||||
|
pub fn deinit(self: OutlineGlyph) void {
|
||||||
|
c.FT_Done_Glyph(@ptrCast(c.FT_Glyph, self.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outline(self: OutlineGlyph) Outline {
|
||||||
|
return .{ .handle = &self.handle.*.outline };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
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 intToError = @import("error.zig").intToError;
|
const intToError = @import("error.zig").intToError;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const Glyph = @import("Glyph.zig");
|
||||||
|
const Library = @import("freetype.zig").Library;
|
||||||
|
const Face = @import("freetype.zig").Face;
|
||||||
|
const RenderMode = @import("freetype.zig").RenderMode;
|
||||||
|
const Matrix = @import("types.zig").Matrix;
|
||||||
|
const Outline = @import("image.zig").Outline;
|
||||||
|
const GlyphFormat = @import("image.zig").GlyphFormat;
|
||||||
|
const Vector = @import("image.zig").Vector;
|
||||||
|
const GlyphMetrics = @import("image.zig").GlyphMetrics;
|
||||||
|
const Bitmap = @import("image.zig").Bitmap;
|
||||||
|
|
||||||
const GlyphSlot = @This();
|
const GlyphSlot = @This();
|
||||||
|
|
||||||
|
|
@ -14,40 +19,49 @@ pub const SubGlyphInfo = struct {
|
||||||
flags: u32,
|
flags: u32,
|
||||||
arg1: i32,
|
arg1: i32,
|
||||||
arg2: i32,
|
arg2: i32,
|
||||||
transform: types.Matrix,
|
transform: Matrix,
|
||||||
};
|
};
|
||||||
|
|
||||||
handle: c.FT_GlyphSlot,
|
handle: c.FT_GlyphSlot,
|
||||||
|
|
||||||
pub fn init(handle: c.FT_GlyphSlot) GlyphSlot {
|
pub fn library(self: GlyphSlot) Library {
|
||||||
return GlyphSlot{ .handle = handle };
|
return .{ .handle = self.handle.*.library };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: GlyphSlot, render_mode: types.RenderMode) Error!void {
|
pub fn face(self: GlyphSlot) Face {
|
||||||
return intToError(c.FT_Render_Glyph(self.handle, @enumToInt(render_mode)));
|
return .{ .handle = self.handle.*.face };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subGlyphInfo(self: GlyphSlot, sub_index: u32) Error!SubGlyphInfo {
|
pub fn next(self: GlyphSlot) GlyphSlot {
|
||||||
var info = std.mem.zeroes(SubGlyphInfo);
|
return .{ .handle = self.handle.*.next };
|
||||||
try intToError(c.FT_Get_SubGlyph_Info(self.handle, sub_index, &info.index, &info.flags, &info.arg1, &info.arg2, @ptrCast(*c.FT_Matrix, &info.transform)));
|
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph(self: GlyphSlot) Error!Glyph {
|
pub fn glyphIndex(self: GlyphSlot) u32 {
|
||||||
var out = std.mem.zeroes(c.FT_Glyph);
|
return self.handle.*.glyph_index;
|
||||||
try intToError(c.FT_Get_Glyph(self.handle, &out));
|
|
||||||
return Glyph.init(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outline(self: GlyphSlot) ?Outline {
|
pub fn metrics(self: GlyphSlot) GlyphMetrics {
|
||||||
return if (self.format() == .outline)
|
return self.handle.*.metrics;
|
||||||
Outline.init(&self.handle.*.outline)
|
}
|
||||||
else
|
|
||||||
null;
|
pub fn linearHoriAdvance(self: GlyphSlot) i32 {
|
||||||
|
return @intCast(i32, self.handle.*.linearHoriAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linearVertAdvance(self: GlyphSlot) i32 {
|
||||||
|
return @intCast(i32, self.handle.*.linearVertAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn advance(self: GlyphSlot) Vector {
|
||||||
|
return self.handle.*.advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(self: GlyphSlot) GlyphFormat {
|
||||||
|
return @intToEnum(GlyphFormat, self.handle.*.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bitmap(self: GlyphSlot) Bitmap {
|
pub fn bitmap(self: GlyphSlot) Bitmap {
|
||||||
return Bitmap.init(self.handle.*.bitmap);
|
return .{ .handle = self.handle.*.bitmap };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bitmapLeft(self: GlyphSlot) i32 {
|
pub fn bitmapLeft(self: GlyphSlot) i32 {
|
||||||
|
|
@ -58,22 +72,30 @@ pub fn bitmapTop(self: GlyphSlot) i32 {
|
||||||
return self.handle.*.bitmap_top;
|
return self.handle.*.bitmap_top;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linearHoriAdvance(self: GlyphSlot) i64 {
|
pub fn outline(self: GlyphSlot) ?Outline {
|
||||||
return self.handle.*.linearHoriAdvance;
|
return if (self.format() == .outline) .{ .handle = &self.handle.*.outline } else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linearVertAdvance(self: GlyphSlot) i64 {
|
pub fn lsbDelta(self: GlyphSlot) i32 {
|
||||||
return self.handle.*.linearVertAdvance;
|
return @intCast(i32, self.handle.*.lsb_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance(self: GlyphSlot) types.Vector {
|
pub fn rsbDelta(self: GlyphSlot) i32 {
|
||||||
return @ptrCast(*types.Vector, &self.handle.*.advance).*;
|
return @intCast(i32, self.handle.*.rsb_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(self: GlyphSlot) Glyph.GlyphFormat {
|
pub fn render(self: GlyphSlot, render_mode: RenderMode) Error!void {
|
||||||
return @intToEnum(Glyph.GlyphFormat, self.handle.*.format);
|
return intToError(c.FT_Render_Glyph(self.handle, @enumToInt(render_mode)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metrics(self: GlyphSlot) Glyph.GlyphMetrics {
|
pub fn subGlyphInfo(self: GlyphSlot, sub_index: u32) Error!SubGlyphInfo {
|
||||||
return self.handle.*.metrics;
|
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 };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig");
|
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 intToError = @import("error.zig").intToError;
|
const intToError = @import("error.zig").intToError;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const Stroker = @import("Stroker.zig");
|
||||||
|
const Face = @import("freetype.zig").Face;
|
||||||
|
const OpenArgs = @import("freetype.zig").OpenArgs;
|
||||||
|
const LcdFilter = @import("lcdfilter.zig").LcdFilter;
|
||||||
|
|
||||||
const Library = @This();
|
const Library = @This();
|
||||||
|
|
||||||
pub const LcdFilter = enum(u5) {
|
pub const Version = struct {
|
||||||
none = c.FT_LCD_FILTER_NONE,
|
major: i32,
|
||||||
default = c.FT_LCD_FILTER_DEFAULT,
|
minor: i32,
|
||||||
light = c.FT_LCD_FILTER_LIGHT,
|
patch: i32,
|
||||||
legacy = c.FT_LCD_FILTER_LEGACY,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handle: c.FT_Library,
|
handle: c.FT_Library,
|
||||||
|
|
||||||
pub fn init() Error!Library {
|
pub fn init() Error!Library {
|
||||||
var ft = std.mem.zeroes(Library);
|
var lib = Library{ .handle = undefined };
|
||||||
try intToError(c.FT_Init_FreeType(&ft.handle));
|
try intToError(c.FT_Init_FreeType(&lib.handle));
|
||||||
return ft;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Library) void {
|
pub fn deinit(self: Library) void {
|
||||||
|
|
@ -43,16 +43,27 @@ pub fn newFaceMemory(self: Library, bytes: []const u8, face_index: i32) Error!Fa
|
||||||
}, face_index);
|
}, face_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn openFace(self: Library, args: types.OpenArgs, face_index: i32) Error!Face {
|
pub fn openFace(self: Library, args: OpenArgs, face_index: i32) Error!Face {
|
||||||
var face = std.mem.zeroes(c.FT_Face);
|
var f: c.FT_Face = undefined;
|
||||||
try intToError(c.FT_Open_Face(self.handle, &args.toCInterface(), face_index, &face));
|
try intToError(c.FT_Open_Face(self.handle, &args.cast(), face_index, &f));
|
||||||
return Face.init(face);
|
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 newStroker(self: Library) Error!Stroker {
|
pub fn newStroker(self: Library) Error!Stroker {
|
||||||
var stroker = std.mem.zeroes(c.FT_Stroker);
|
var s: c.FT_Stroker = undefined;
|
||||||
try intToError(c.FT_Stroker_New(self.handle, &stroker));
|
try intToError(c.FT_Stroker_New(self.handle, &s));
|
||||||
return Stroker.init(stroker);
|
return Stroker{ .handle = s };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setLcdFilter(self: Library, lcd_filter: LcdFilter) Error!void {
|
pub fn setLcdFilter(self: Library, lcd_filter: LcdFilter) Error!void {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const types = @import("types.zig");
|
|
||||||
const Glyph = @import("Glyph.zig");
|
|
||||||
const Error = @import("error.zig").Error;
|
|
||||||
const intToError = @import("error.zig").intToError;
|
const intToError = @import("error.zig").intToError;
|
||||||
const errorToInt = @import("error.zig").errorToInt;
|
const errorToInt = @import("error.zig").errorToInt;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const Matrix = @import("types.zig").Matrix;
|
||||||
|
const BBox = @import("types.zig").BBox;
|
||||||
|
const Vector = @import("image.zig").Vector;
|
||||||
|
|
||||||
const Outline = @This();
|
const Outline = @This();
|
||||||
|
|
||||||
handle: *c.FT_Outline,
|
handle: *c.FT_Outline,
|
||||||
|
|
||||||
pub fn init(handle: *c.FT_Outline) Outline {
|
|
||||||
return Outline{ .handle = handle };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn numPoints(self: Outline) u15 {
|
pub fn numPoints(self: Outline) u15 {
|
||||||
return @intCast(u15, self.handle.*.n_points);
|
return @intCast(u15, self.handle.*.n_points);
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +18,8 @@ pub fn numContours(self: Outline) u15 {
|
||||||
return @intCast(u15, self.handle.*.n_contours);
|
return @intCast(u15, self.handle.*.n_contours);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn points(self: Outline) []const types.Vector {
|
pub fn points(self: Outline) []const Vector {
|
||||||
return @ptrCast([]types.Vector, self.handle.*.points[0..self.numPoints()]);
|
return self.handle.*.points[0..self.numPoints()];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tags(self: Outline) []const u8 {
|
pub fn tags(self: Outline) []const u8 {
|
||||||
|
|
@ -38,25 +34,24 @@ pub fn check(self: Outline) Error!void {
|
||||||
try intToError(c.FT_Outline_Check(self.handle));
|
try intToError(c.FT_Outline_Check(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform(self: Outline, matrix: ?types.Matrix) void {
|
pub fn transform(self: Outline, matrix: ?Matrix) void {
|
||||||
var m = matrix orelse std.mem.zeroes(types.Matrix);
|
c.FT_Outline_Transform(self.handle, if (matrix) |m| &m else null);
|
||||||
c.FT_Outline_Transform(self.handle, @ptrCast(*c.FT_Matrix, &m));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bbox(self: Outline) Error!types.BBox {
|
pub fn bbox(self: Outline) Error!BBox {
|
||||||
var res = std.mem.zeroes(types.BBox);
|
var b: BBox = undefined;
|
||||||
try intToError(c.FT_Outline_Get_BBox(self.handle, @ptrCast(*c.FT_BBox, &res)));
|
try intToError(c.FT_Outline_Get_BBox(self.handle, &b));
|
||||||
return res;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn OutlineFuncs(comptime Context: type) type {
|
pub fn OutlineFuncs(comptime Context: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
move_to: fn (ctx: Context, to: types.Vector) Error!void,
|
move_to: fn (ctx: Context, to: Vector) Error!void,
|
||||||
line_to: fn (ctx: Context, to: types.Vector) Error!void,
|
line_to: fn (ctx: Context, to: Vector) Error!void,
|
||||||
conic_to: fn (ctx: Context, control: types.Vector, to: types.Vector) Error!void,
|
conic_to: fn (ctx: Context, control: Vector, to: Vector) Error!void,
|
||||||
cubic_to: fn (ctx: Context, control_0: types.Vector, control_1: types.Vector, to: types.Vector) Error!void,
|
cubic_to: fn (ctx: Context, control_0: Vector, control_1: Vector, to: Vector) Error!void,
|
||||||
shift: c_int,
|
shift: i32,
|
||||||
delta: isize,
|
delta: i32,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,8 +65,8 @@ pub fn OutlineFuncsWrapper(comptime Context: type) type {
|
||||||
return @ptrCast(*Self, @alignCast(@alignOf(Self), ptr));
|
return @ptrCast(*Self, @alignCast(@alignOf(Self), ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn castVec(vec: [*c]const c.FT_Vector) types.Vector {
|
fn castVec(vec: [*c]const c.FT_Vector) Vector {
|
||||||
return @intToPtr(*types.Vector, @ptrToInt(vec)).*;
|
return @intToPtr(*Vector, @ptrToInt(vec)).*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_to(to: [*c]const c.FT_Vector, ctx: ?*anyopaque) callconv(.C) c_int {
|
pub fn move_to(to: [*c]const c.FT_Vector, ctx: ?*anyopaque) callconv(.C) c_int {
|
||||||
|
|
@ -130,7 +125,7 @@ pub fn decompose(self: Outline, ctx: anytype, callbacks: OutlineFuncs(@TypeOf(ct
|
||||||
var wrapper = OutlineFuncsWrapper(@TypeOf(ctx)){ .ctx = ctx, .callbacks = callbacks };
|
var wrapper = OutlineFuncsWrapper(@TypeOf(ctx)){ .ctx = ctx, .callbacks = callbacks };
|
||||||
try intToError(c.FT_Outline_Decompose(
|
try intToError(c.FT_Outline_Decompose(
|
||||||
self.handle,
|
self.handle,
|
||||||
&c.FT_Outline_Funcs{
|
&.{
|
||||||
.move_to = @TypeOf(wrapper).move_to,
|
.move_to = @TypeOf(wrapper).move_to,
|
||||||
.line_to = @TypeOf(wrapper).line_to,
|
.line_to = @TypeOf(wrapper).line_to,
|
||||||
.conic_to = @TypeOf(wrapper).conic_to,
|
.conic_to = @TypeOf(wrapper).conic_to,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const Error = @import("error.zig").Error;
|
|
||||||
const intToError = @import("error.zig").intToError;
|
|
||||||
|
|
||||||
const Stroker = @This();
|
pub const Stroker = @This();
|
||||||
|
|
||||||
pub const StrokerLineCap = enum(u2) {
|
pub const LineCap = enum(u2) {
|
||||||
butt = c.FT_STROKER_LINECAP_BUTT,
|
butt = c.FT_STROKER_LINECAP_BUTT,
|
||||||
round = c.FT_STROKER_LINECAP_ROUND,
|
round = c.FT_STROKER_LINECAP_ROUND,
|
||||||
square = c.FT_STROKER_LINECAP_SQUARE,
|
square = c.FT_STROKER_LINECAP_SQUARE,
|
||||||
};
|
};
|
||||||
pub const StrokerLineJoin = enum(u2) {
|
|
||||||
|
pub const LineJoin = enum(u2) {
|
||||||
round = c.FT_STROKER_LINEJOIN_ROUND,
|
round = c.FT_STROKER_LINEJOIN_ROUND,
|
||||||
bevel = c.FT_STROKER_LINEJOIN_BEVEL,
|
bevel = c.FT_STROKER_LINEJOIN_BEVEL,
|
||||||
miterVariable = c.FT_STROKER_LINEJOIN_MITER_VARIABLE,
|
miterVariable = c.FT_STROKER_LINEJOIN_MITER_VARIABLE,
|
||||||
|
|
@ -18,11 +17,7 @@ pub const StrokerLineJoin = enum(u2) {
|
||||||
|
|
||||||
handle: c.FT_Stroker,
|
handle: c.FT_Stroker,
|
||||||
|
|
||||||
pub fn init(handle: c.FT_Stroker) Stroker {
|
pub fn set(self: Stroker, radius: i32, line_cap: LineCap, line_join: LineJoin, miter_limit: i32) void {
|
||||||
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);
|
c.FT_Stroker_Set(self.handle, radius, @enumToInt(line_cap), @enumToInt(line_join), miter_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
pub usingnamespace @cImport({
|
pub usingnamespace @cImport({
|
||||||
@cInclude("freetype/freetype.h");
|
@cInclude("freetype/freetype.h");
|
||||||
@cInclude("freetype/ftbbox.h");
|
@cInclude("freetype/ftbbox.h");
|
||||||
|
@cInclude("freetype/ftcolor.h");
|
||||||
@cInclude("freetype/ftlcdfil.h");
|
@cInclude("freetype/ftlcdfil.h");
|
||||||
@cInclude("freetype/ftmodapi.h");
|
@cInclude("freetype/ftmodapi.h");
|
||||||
|
@cInclude("freetype/ftsizes.h");
|
||||||
@cInclude("freetype/ftstroke.h");
|
@cInclude("freetype/ftstroke.h");
|
||||||
@cInclude("freetype/ftsystem.h");
|
@cInclude("freetype/ftsystem.h");
|
||||||
@cInclude("ft2build.h");
|
@cInclude("ft2build.h");
|
||||||
|
|
|
||||||
176
freetype/src/color.zig
Normal file
176
freetype/src/color.zig
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
const Face = @import("freetype.zig").Face;
|
||||||
|
|
||||||
|
pub const Color = c.FT_Color;
|
||||||
|
pub const LayerIterator = c.FT_LayerIterator;
|
||||||
|
pub const ColorStopIterator = c.FT_ColorStopIterator;
|
||||||
|
pub const ColorIndex = c.FT_ColorIndex;
|
||||||
|
pub const ColorStop = c.FT_ColorStop;
|
||||||
|
pub const ColorLine = c.FT_ColorLine;
|
||||||
|
pub const Affine23 = c.FT_Affine23;
|
||||||
|
pub const OpaquePaint = c.FT_OpaquePaint;
|
||||||
|
pub const PaintColrLayers = c.FT_PaintColrLayers;
|
||||||
|
pub const PaintSolid = c.FT_PaintSolid;
|
||||||
|
pub const PaintLinearGradient = c.FT_PaintLinearGradient;
|
||||||
|
pub const PaintRadialGradient = c.FT_PaintRadialGradient;
|
||||||
|
pub const PaintSweepGradient = c.FT_PaintSweepGradient;
|
||||||
|
pub const PaintGlyph = c.FT_PaintGlyph;
|
||||||
|
pub const PaintColrGlyph = c.FT_PaintColrGlyph;
|
||||||
|
pub const PaintTransform = c.FT_PaintTransform;
|
||||||
|
pub const PaintTranslate = c.FT_PaintTranslate;
|
||||||
|
pub const PaintScale = c.FT_PaintScale;
|
||||||
|
pub const PaintRotate = c.FT_PaintRotate;
|
||||||
|
pub const PaintSkew = c.FT_PaintSkew;
|
||||||
|
pub const PaintComposite = c.FT_PaintComposite;
|
||||||
|
pub const ClipBox = c.FT_ClipBox;
|
||||||
|
|
||||||
|
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 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 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 Paint = union(PaintFormat) {
|
||||||
|
color_layers: PaintColrLayers,
|
||||||
|
glyph: PaintGlyph,
|
||||||
|
solid: PaintSolid,
|
||||||
|
linear_gradient: PaintLinearGradient,
|
||||||
|
radial_gradient: PaintRadialGradient,
|
||||||
|
sweep_gradient: PaintSweepGradient,
|
||||||
|
transform: PaintTransform,
|
||||||
|
translate: PaintTranslate,
|
||||||
|
scale: PaintScale,
|
||||||
|
rotate: PaintRotate,
|
||||||
|
skew: PaintSkew,
|
||||||
|
composite: PaintComposite,
|
||||||
|
color_glyph: PaintColrGlyph,
|
||||||
|
};
|
||||||
|
|
||||||
|
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 @ptrCast(?[]const u16, self.handle.palette_name_ids[0..self.numPalettes()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paletteFlags(self: PaletteData) ?[]const u16 {
|
||||||
|
return @ptrCast(?[]const u16, self.handle.palette_flags[0..self.numPalettes()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paletteFlag(self: PaletteData, index: usize) PaletteFlags {
|
||||||
|
return PaletteFlags.from(@intCast(u2, 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 @ptrCast(?[]const u16, self.handle.palette_entry_name_ids[0..self.numPaletteEntries()]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PaletteFlags = packed struct {
|
||||||
|
for_light_background: bool = false,
|
||||||
|
for_dark_background: bool = false,
|
||||||
|
|
||||||
|
pub const Flag = enum(u2) {
|
||||||
|
for_light_background = c.FT_PALETTE_FOR_LIGHT_BACKGROUND,
|
||||||
|
for_dark_background = c.FT_PALETTE_FOR_DARK_BACKGROUND,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn from(bits: u2) PaletteFlags {
|
||||||
|
return utils.bitFieldsToStruct(PaletteFlags, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to(flags: PaletteFlags) u2 {
|
||||||
|
return utils.structToBitFields(u2, PaletteFlags, Flag, flags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
288
freetype/src/freetype.zig
Normal file
288
freetype/src/freetype.zig
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
const intToError = @import("error.zig").intToError;
|
||||||
|
const Error = @import("error.zig").Error;
|
||||||
|
const Generic = @import("types.zig").Generic;
|
||||||
|
|
||||||
|
pub const Library = @import("Library.zig");
|
||||||
|
pub const Face = @import("Face.zig");
|
||||||
|
pub const GlyphSlot = @import("GlyphSlot.zig");
|
||||||
|
|
||||||
|
pub const SizeRequest = c.FT_Size_RequestRec;
|
||||||
|
pub const BitmapSize = c.FT_Bitmap_Size;
|
||||||
|
pub const CharMap = c.FT_CharMapRec;
|
||||||
|
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 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 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 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 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 {
|
||||||
|
c.FT_Done_Size(self.handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 from(bits: u21) LoadFlags {
|
||||||
|
return utils.bitFieldsToStruct(LoadFlags, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast(flags: LoadFlags) u21 {
|
||||||
|
return utils.structToBitFields(u21, Flag, flags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const FaceFlags = packed struct {
|
||||||
|
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,
|
||||||
|
|
||||||
|
pub const Flag = enum(u19) {
|
||||||
|
scalable = c.FT_FACE_FLAG_SCALABLE,
|
||||||
|
fixed_sizes = c.FT_FACE_FLAG_FIXED_SIZES,
|
||||||
|
fixed_width = c.FT_FACE_FLAG_FIXED_WIDTH,
|
||||||
|
sfnt = c.FT_FACE_FLAG_SFNT,
|
||||||
|
horizontal = c.FT_FACE_FLAG_HORIZONTAL,
|
||||||
|
vertical = c.FT_FACE_FLAG_VERTICAL,
|
||||||
|
kerning = c.FT_FACE_FLAG_KERNING,
|
||||||
|
fast_glyphs = c.FT_FACE_FLAG_FAST_GLYPHS,
|
||||||
|
multiple_masters = c.FT_FACE_FLAG_MULTIPLE_MASTERS,
|
||||||
|
glyph_names = c.FT_FACE_FLAG_GLYPH_NAMES,
|
||||||
|
external_stream = c.FT_FACE_FLAG_EXTERNAL_STREAM,
|
||||||
|
hinter = c.FT_FACE_FLAG_HINTER,
|
||||||
|
cid_keyed = c.FT_FACE_FLAG_CID_KEYED,
|
||||||
|
tricky = c.FT_FACE_FLAG_TRICKY,
|
||||||
|
color = c.FT_FACE_FLAG_COLOR,
|
||||||
|
variation = c.FT_FACE_FLAG_VARIATION,
|
||||||
|
svg = c.FT_FACE_FLAG_SVG,
|
||||||
|
sbix = c.FT_FACE_FLAG_SBIX,
|
||||||
|
sbix_overlay = c.FT_FACE_FLAG_SBIX_OVERLAY,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn from(bits: u19) FaceFlags {
|
||||||
|
return utils.bitFieldsToStruct(FaceFlags, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast(self: FaceFlags) u19 {
|
||||||
|
return utils.structToBitFields(u19, Flag, self);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const FSType = packed struct {
|
||||||
|
installable_embedding: bool = false,
|
||||||
|
restriced_license_embedding: bool = false,
|
||||||
|
preview_and_print_embedding: bool = false,
|
||||||
|
editable_embedding: bool = false,
|
||||||
|
no_subsetting: bool = false,
|
||||||
|
bitmap_embedding_only: bool = false,
|
||||||
|
|
||||||
|
pub const Flag = enum(u10) {
|
||||||
|
installable_embedding = c.FT_FSTYPE_INSTALLABLE_EMBEDDING,
|
||||||
|
restriced_license_embedding = c.FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING,
|
||||||
|
preview_and_print_embedding = c.FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING,
|
||||||
|
editable_embedding = c.FT_FSTYPE_EDITABLE_EMBEDDING,
|
||||||
|
no_subsetting = c.FT_FSTYPE_NO_SUBSETTING,
|
||||||
|
bitmap_embedding_only = c.FT_FSTYPE_BITMAP_EMBEDDING_ONLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn from(bits: u10) FSType {
|
||||||
|
return utils.bitFieldsToStruct(FSType, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast(flags: FSType) u10 {
|
||||||
|
return utils.structToBitFields(u10, FSType, Flag, flags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const StyleFlags = packed struct {
|
||||||
|
italic: bool = false,
|
||||||
|
bold: bool = false,
|
||||||
|
|
||||||
|
pub const Flag = enum(u2) {
|
||||||
|
italic = c.FT_STYLE_FLAG_ITALIC,
|
||||||
|
bold = c.FT_STYLE_FLAG_BOLD,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn from(bits: u2) StyleFlags {
|
||||||
|
return utils.bitFieldsToStruct(StyleFlags, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast(flags: StyleFlags) u2 {
|
||||||
|
return utils.structToBitFields(u2, StyleFlags, Flag, flags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 from(bits: u5) OpenFlags {
|
||||||
|
return utils.bitFieldsToStruct(OpenFlags, Flag, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast(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 cast(self: OpenArgs) c.FT_Open_Args {
|
||||||
|
var oa: c.FT_Open_Args = undefined;
|
||||||
|
oa.flags = self.flags.cast();
|
||||||
|
switch (self.data) {
|
||||||
|
.memory => |d| {
|
||||||
|
oa.memory_base = d.ptr;
|
||||||
|
oa.memory_size = @intCast(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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn getCharmapIndex(self: [*c]CharMap) ?u32 {
|
||||||
|
const i = c.FT_Get_Charmap_Index(self);
|
||||||
|
return if (i == -1) null else @intCast(u32, i);
|
||||||
|
}
|
||||||
52
freetype/src/image.zig
Normal file
52
freetype/src/image.zig
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
|
||||||
|
pub const Outline = @import("Outline.zig");
|
||||||
|
|
||||||
|
pub const Vector = c.FT_Vector;
|
||||||
|
pub const GlyphMetrics = c.FT_Glyph_Metrics;
|
||||||
|
|
||||||
|
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 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 Bitmap = struct {
|
||||||
|
handle: c.FT_Bitmap,
|
||||||
|
|
||||||
|
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 @intToEnum(PixelMode, self.handle.pixel_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buffer(self: Bitmap) []const u8 {
|
||||||
|
const buffer_size = std.math.absCast(self.pitch()) * self.rows();
|
||||||
|
return self.handle.buffer[0..buffer_size];
|
||||||
|
}
|
||||||
|
};
|
||||||
8
freetype/src/lcdfilter.zig
Normal file
8
freetype/src/lcdfilter.zig
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const c = @import("c.zig");
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
@ -1,26 +1,38 @@
|
||||||
pub const Library = @import("Library.zig");
|
pub usingnamespace @import("freetype.zig");
|
||||||
pub const Face = @import("Face.zig");
|
pub usingnamespace @import("types.zig");
|
||||||
pub const GlyphSlot = @import("GlyphSlot.zig");
|
pub usingnamespace @import("image.zig");
|
||||||
|
pub usingnamespace @import("color.zig");
|
||||||
|
pub usingnamespace @import("lcdfilter.zig");
|
||||||
|
pub const c = @import("c.zig");
|
||||||
pub const Glyph = @import("Glyph.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 Stroker = @import("Stroker.zig");
|
||||||
pub const Error = @import("error.zig").Error;
|
pub const Error = @import("error.zig").Error;
|
||||||
pub const C = @import("c.zig");
|
|
||||||
pub usingnamespace @import("types.zig");
|
const std = @import("std");
|
||||||
|
|
||||||
|
fn refLiterallyAllDecls(comptime T: type) void {
|
||||||
|
switch (@typeInfo(T)) {
|
||||||
|
.Struct, .Union, .Opaque, .Enum => {
|
||||||
|
inline for (comptime std.meta.declarations(T)) |decl| {
|
||||||
|
if (decl.is_pub) {
|
||||||
|
refLiterallyAllDecls(@TypeOf(@field(T, decl.name)));
|
||||||
|
std.testing.refAllDecls(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
const refAllDecls = @import("std").testing.refAllDecls;
|
refLiterallyAllDecls(@This());
|
||||||
refAllDecls(@import("Library.zig"));
|
refLiterallyAllDecls(@import("color.zig"));
|
||||||
refAllDecls(@import("Face.zig"));
|
refLiterallyAllDecls(@import("error.zig"));
|
||||||
refAllDecls(@import("GlyphSlot.zig"));
|
refLiterallyAllDecls(@import("utils.zig"));
|
||||||
refAllDecls(@import("Glyph.zig"));
|
refLiterallyAllDecls(@import("Face.zig"));
|
||||||
refAllDecls(@import("BitmapGlyph.zig"));
|
refLiterallyAllDecls(@import("GlyphSlot.zig"));
|
||||||
refAllDecls(@import("Bitmap.zig"));
|
refLiterallyAllDecls(@import("Library.zig"));
|
||||||
refAllDecls(@import("Outline.zig"));
|
refLiterallyAllDecls(@import("Outline.zig"));
|
||||||
refAllDecls(@import("Stroker.zig"));
|
refLiterallyAllDecls(Glyph);
|
||||||
refAllDecls(@import("types.zig"));
|
refLiterallyAllDecls(Stroker);
|
||||||
refAllDecls(@import("error.zig"));
|
|
||||||
refAllDecls(@import("utils.zig"));
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,5 @@
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const utils = @import("utils.zig");
|
|
||||||
|
|
||||||
pub const Vector = extern struct {
|
pub const Matrix = c.FT_Matrix;
|
||||||
x: c_long,
|
pub const Generic = c.FT_Generic;
|
||||||
y: c_long,
|
pub const BBox = c.FT_BBox;
|
||||||
};
|
|
||||||
pub const Matrix = extern struct {
|
|
||||||
xx: c_long,
|
|
||||||
xy: c_long,
|
|
||||||
yx: c_long,
|
|
||||||
yy: c_long,
|
|
||||||
};
|
|
||||||
pub const BBox = extern struct {
|
|
||||||
xMin: c_long,
|
|
||||||
yMin: c_long,
|
|
||||||
xMax: c_long,
|
|
||||||
yMax: c_long,
|
|
||||||
};
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
const std = @import("std");
|
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 {
|
pub fn structToBitFields(comptime IntType: type, comptime EnumDataType: type, flags: anytype) IntType {
|
||||||
var value: IntType = 0;
|
var value: IntType = 0;
|
||||||
inline for (comptime meta.fieldNames(EnumDataType)) |field_name| {
|
inline for (comptime std.meta.fieldNames(EnumDataType)) |field_name| {
|
||||||
if (@field(flags, field_name)) {
|
if (@field(flags, field_name)) {
|
||||||
value |= @enumToInt(@field(EnumDataType, field_name));
|
value |= @enumToInt(@field(EnumDataType, field_name));
|
||||||
}
|
}
|
||||||
|
|
@ -14,8 +11,8 @@ pub fn structToBitFields(comptime IntType: type, comptime EnumDataType: type, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bitFieldsToStruct(comptime StructType: type, comptime EnumDataType: type, flags: anytype) StructType {
|
pub fn bitFieldsToStruct(comptime StructType: type, comptime EnumDataType: type, flags: anytype) StructType {
|
||||||
var value = mem.zeroes(StructType);
|
var value = std.mem.zeroes(StructType);
|
||||||
inline for (comptime meta.fieldNames(EnumDataType)) |field_name| {
|
inline for (comptime std.meta.fieldNames(EnumDataType)) |field_name| {
|
||||||
if (flags & (@enumToInt(@field(EnumDataType, field_name))) != 0) {
|
if (flags & (@enumToInt(@field(EnumDataType, field_name))) != 0) {
|
||||||
@field(value, field_name) = true;
|
@field(value, field_name) = true;
|
||||||
}
|
}
|
||||||
|
|
@ -36,13 +33,13 @@ const TestStruct = packed struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
test "struct fields to bit fields" {
|
test "struct fields to bit fields" {
|
||||||
try testing.expectEqual(@as(u16, (1 << 1) | (1 << 3)), structToBitFields(u16, TestEnum, TestStruct{
|
try std.testing.expectEqual(@as(u16, (1 << 1) | (1 << 3)), structToBitFields(u16, TestEnum, TestStruct{
|
||||||
.filed_1 = true,
|
.filed_1 = true,
|
||||||
.filed_3 = true,
|
.filed_3 = true,
|
||||||
}));
|
}));
|
||||||
try testing.expectEqual(@as(u16, 0), structToBitFields(u16, TestEnum, TestStruct{}));
|
try std.testing.expectEqual(@as(u16, 0), structToBitFields(u16, TestEnum, TestStruct{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "bit fields to struct" {
|
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)));
|
try std.testing.expectEqual(TestStruct{ .filed_1 = true, .filed_2 = true, .filed_3 = false }, bitFieldsToStruct(TestStruct, TestEnum, (1 << 1) | (1 << 2)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
const testing = @import("std").testing;
|
||||||
const freetype = @import("freetype");
|
const freetype = @import("freetype");
|
||||||
|
|
||||||
const firasnas_font_path = "upstream/assets/FiraSans-Regular.ttf";
|
const firasnas_font_path = "upstream/assets/FiraSans-Regular.ttf";
|
||||||
|
|
@ -19,7 +20,7 @@ test "new stroker" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "set lcd filter" {
|
test "set lcd filter" {
|
||||||
if (@hasDecl(freetype.C, "FT_CONFIG_OPTION_SUBPIXEL_RENDERING")) {
|
if (@hasDecl(freetype.c, "FT_CONFIG_OPTION_SUBPIXEL_RENDERING")) {
|
||||||
const lib = try freetype.Library.init();
|
const lib = try freetype.Library.init();
|
||||||
try lib.setLcdFilter(.default);
|
try lib.setLcdFilter(.default);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -52,3 +53,26 @@ test "attach from memory" {
|
||||||
const file = @embedFile("../upstream/assets/DejaVuSans.pfm");
|
const file = @embedFile("../upstream/assets/DejaVuSans.pfm");
|
||||||
try face.attachMemory(file);
|
try face.attachMemory(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "charmap iterator" {
|
||||||
|
const lib = try freetype.Library.init();
|
||||||
|
const face = try lib.newFace(firasnas_font_path, 0);
|
||||||
|
var iterator = face.getCharmapIterator();
|
||||||
|
var old_char: usize = 0;
|
||||||
|
while (iterator.next()) |c| {
|
||||||
|
try testing.expect(old_char != c);
|
||||||
|
old_char = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "get name index" {
|
||||||
|
const lib = try freetype.Library.init();
|
||||||
|
const face = try lib.newFace(firasnas_font_path, 0);
|
||||||
|
try testing.expectEqual(@as(u32, 1120), face.getNameIndex("summation").?);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "get index name" {
|
||||||
|
const lib = try freetype.Library.init();
|
||||||
|
const face = try lib.newFace(firasnas_font_path, 0);
|
||||||
|
try testing.expectEqualStrings("summation", try face.getGlyphName(1120));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue