gfx: font: account for glyph bearings
Helps hexops/mach#877 Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
dfbf3e3603
commit
34259ed1b8
2 changed files with 21 additions and 13 deletions
|
|
@ -36,16 +36,18 @@ pub fn shape(f: *const Font, r: *TextRun) anyerror!void {
|
||||||
// Guess text segment properties.
|
// Guess text segment properties.
|
||||||
r.buffer.guessSegmentProps();
|
r.buffer.guessSegmentProps();
|
||||||
// TODO: Optionally override specific text segment properties?
|
// TODO: Optionally override specific text segment properties?
|
||||||
// buffer.setDirection(.ltr);
|
// r.buffer.setDirection(.ltr);
|
||||||
// buffer.setScript(.latin);
|
// r.buffer.setScript(.latin);
|
||||||
// buffer.setLanguage(harfbuzz.Language.fromString("en"));
|
// r.buffer.setLanguage(harfbuzz.Language.fromString("en"));
|
||||||
|
|
||||||
|
const font_size_pt = r.font_size_px / px_per_pt;
|
||||||
|
const font_size_pt_frac: i32 = @intFromFloat(font_size_pt * 64.0);
|
||||||
|
f.face.setCharSize(font_size_pt_frac, font_size_pt_frac, 0, 0) catch return error.RenderError;
|
||||||
|
|
||||||
const hb_face = harfbuzz.Face.fromFreetypeFace(f.face);
|
const hb_face = harfbuzz.Face.fromFreetypeFace(f.face);
|
||||||
const hb_font = harfbuzz.Font.init(hb_face);
|
const hb_font = harfbuzz.Font.init(hb_face);
|
||||||
defer hb_font.deinit();
|
defer hb_font.deinit();
|
||||||
|
|
||||||
const font_size_pt = r.font_size_px / px_per_pt;
|
|
||||||
const font_size_pt_frac: i32 = @intFromFloat(font_size_pt * 256.0);
|
|
||||||
hb_font.setScale(font_size_pt_frac, font_size_pt_frac);
|
hb_font.setScale(font_size_pt_frac, font_size_pt_frac);
|
||||||
hb_font.setPTEM(font_size_pt);
|
hb_font.setPTEM(font_size_pt);
|
||||||
|
|
||||||
|
|
@ -55,14 +57,20 @@ pub fn shape(f: *const Font, r: *TextRun) anyerror!void {
|
||||||
r.index = 0;
|
r.index = 0;
|
||||||
r.infos = r.buffer.getGlyphInfos();
|
r.infos = r.buffer.getGlyphInfos();
|
||||||
r.positions = r.buffer.getGlyphPositions() orelse return error.OutOfMemory;
|
r.positions = r.buffer.getGlyphPositions() orelse return error.OutOfMemory;
|
||||||
|
|
||||||
|
for (r.positions, r.infos) |*pos, info| {
|
||||||
|
const glyph_index = info.codepoint;
|
||||||
|
f.face.loadGlyph(glyph_index, .{ .render = false }) catch return error.RenderError;
|
||||||
|
const glyph = f.face.glyph();
|
||||||
|
const metrics = glyph.metrics();
|
||||||
|
pos.*.x_offset += @intCast(metrics.horiBearingX);
|
||||||
|
pos.*.y_offset += @intCast(metrics.horiBearingY);
|
||||||
|
// TODO: use vertBearingX / vertBearingY for vertical layouts
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(f: *Font, allocator: std.mem.Allocator, glyph_index: u32, opt: RenderOptions) anyerror!RenderedGlyph {
|
pub fn render(f: *Font, allocator: std.mem.Allocator, glyph_index: u32, opt: RenderOptions) anyerror!RenderedGlyph {
|
||||||
// TODO: DPI configuration
|
_ = opt;
|
||||||
const dpi = 72;
|
|
||||||
const font_size_pt = opt.font_size_px / px_per_pt;
|
|
||||||
const font_size_pt_frac: i32 = @intFromFloat(font_size_pt * 64.0);
|
|
||||||
f.face.setCharSize(font_size_pt_frac, font_size_pt_frac, dpi, dpi) catch return error.RenderError;
|
|
||||||
f.face.loadGlyph(glyph_index, .{ .render = true }) catch return error.RenderError;
|
f.face.loadGlyph(glyph_index, .{ .render = true }) catch return error.RenderError;
|
||||||
|
|
||||||
const glyph = f.face.glyph();
|
const glyph = f.face.glyph();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ px_density: u8 = 1,
|
||||||
buffer: harfbuzz.Buffer,
|
buffer: harfbuzz.Buffer,
|
||||||
index: usize = 0,
|
index: usize = 0,
|
||||||
infos: []harfbuzz.GlyphInfo = undefined,
|
infos: []harfbuzz.GlyphInfo = undefined,
|
||||||
positions: []harfbuzz.Position = undefined,
|
positions: []harfbuzz.GlyphPosition = undefined,
|
||||||
|
|
||||||
pub fn init() anyerror!TextRun {
|
pub fn init() anyerror!TextRun {
|
||||||
return TextRun{
|
return TextRun{
|
||||||
|
|
@ -37,8 +37,8 @@ pub fn next(s: *TextRun) ?Glyph {
|
||||||
// .var1 = @intCast(info.var1),
|
// .var1 = @intCast(info.var1),
|
||||||
// .var2 = @intCast(info.var2),
|
// .var2 = @intCast(info.var2),
|
||||||
.cluster = info.cluster,
|
.cluster = info.cluster,
|
||||||
.advance = vec2(@floatFromInt(pos.x_advance), @floatFromInt(pos.y_advance)).div(&Vec2.splat(256.0)),
|
.advance = vec2(@floatFromInt(pos.x_advance), @floatFromInt(pos.y_advance)).div(&Vec2.splat(64.0)),
|
||||||
.offset = vec2(@floatFromInt(pos.x_offset), @floatFromInt(pos.y_offset)).div(&Vec2.splat(256.0)),
|
.offset = vec2(@floatFromInt(pos.x_offset), @floatFromInt(pos.y_offset)).div(&Vec2.splat(64.0)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue