fix the baseline for font rendering

This commit is contained in:
Mitchell Hashimoto
2022-04-19 19:30:30 -07:00
parent e2ed1ed745
commit d250bcda65
4 changed files with 23 additions and 11 deletions

View File

@ -44,6 +44,7 @@ flat out uint mode;
uniform sampler2D text;
uniform vec2 cell_size;
uniform mat4 projection;
uniform float glyph_baseline;
/********************************************************************
* Modes
@ -99,11 +100,12 @@ void main() {
break;
case MODE_FG:
// The glyph offset is upside down so we need to reverse it to
// be based on the offset of our cell. This is equivalent to
// "1 - value" to flip the value.
// The glyph_offset.y is the y bearing, a y value that when added
// to the baseline is the offset (+y is up). Our grid goes down.
// So we flip it with `cell_size.y - glyph_offset.y`. The glyph_baseline
// uniform sets our line baseline where characters "sit".
vec2 glyph_offset_calc = glyph_offset;
glyph_offset_calc.y = cell_size.y - glyph_offset.y;
glyph_offset_calc.y = cell_size.y - glyph_offset.y - glyph_baseline;
// Calculate the final position of the cell.
cell_pos = cell_pos + glyph_size * position + glyph_offset_calc;

View File

@ -42,7 +42,7 @@ pub const Glyph = struct {
offset_y: i32,
/// coordinates in the atlas of the top-left corner. These have to
/// be normalized to be between 0 and 1 prior to use.
/// be normalized to be between 0 and 1 prior to use in shaders.
atlas_x: u32,
atlas_y: u32,

View File

@ -95,14 +95,19 @@ pub fn init(alloc: Allocator) !Grid {
// The cell height is the vertical height required to render underscore
// '_' which should live at the bottom of a cell.
const cell_height: f32 = cell_height: {
// TODO(render): kitty does a calculation based on other font
// metrics that we probably want to research more. For now, this is
// fine.
// This is the height reported by the font face
const face_height: i32 = font.ft_face.*.height >> 6;
// Determine the height of the underscore char
assert(font.ft_face != null);
const glyph = font.getGlyph('_').?;
var res: i32 = font.ft_face.*.ascender >> 6;
res -= glyph.offset_y;
res += @intCast(i32, glyph.height);
// We take whatever is larger to account for some fonts that
// put the underscore outside f the rectangle.
if (res < face_height) res = face_height;
break :cell_height @intToFloat(f32, res);
};
log.debug("cell dimensions w={d} h={d}", .{ cell_width, cell_height });
@ -117,6 +122,10 @@ pub fn init(alloc: Allocator) !Grid {
const pbind = try program.use();
defer pbind.unbind();
try program.setUniform("cell_size", @Vector(2, f32){ cell_width, cell_height });
try program.setUniform(
"glyph_baseline",
cell_height - @intToFloat(f32, font.ft_face.*.ascender >> 6),
);
// Setup our VAO
const vao = try gl.VertexArray.create();
@ -258,6 +267,7 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
// TODO: for background colors, add another cell with mode = 1
self.cells.appendAssumeCapacity(.{
.mode = 2,
.grid_col = @intCast(u16, x),
.grid_row = @intCast(u16, y),
.glyph_x = glyph.atlas_x,
@ -274,13 +284,13 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.bg_g = 0xA5,
.bg_b = 0,
.bg_a = 0,
.mode = 2,
});
}
}
// Draw the cursor
self.cells.appendAssumeCapacity(.{
.mode = 1,
.grid_col = @intCast(u16, term.cursor.x),
.grid_row = @intCast(u16, term.cursor.y),
.fg_r = 0,
@ -291,7 +301,6 @@ pub fn updateCells(self: *Grid, term: Terminal) !void {
.bg_g = 0xFF,
.bg_b = 0xFF,
.bg_a = 255,
.mode = 1,
});
}
@ -316,7 +325,7 @@ pub fn setScreenSize(self: *Grid, dim: ScreenSize) !void {
// Recalculate the rows/columns.
self.size.update(dim, self.cell_size);
log.debug("screen size screen={} grid={}", .{ dim, self.size });
log.debug("screen size screen={} grid={}, cell={}", .{ dim, self.size, self.cell_size });
}
pub fn render(self: Grid) !void {

View File

@ -83,6 +83,7 @@ pub inline fn setUniform(p: Program, n: [:0]const u8, value: anytype) !void {
// Perform the correct call depending on the type of the value.
switch (@TypeOf(value)) {
comptime_int => c.glUniform1i(loc, value),
f32 => c.glUniform1f(loc, value),
@Vector(2, f32) => c.glUniform2f(loc, value[0], value[1]),
@Vector(3, f32) => c.glUniform3f(loc, value[0], value[1], value[2]),
@Vector(4, f32) => c.glUniform4f(loc, value[0], value[1], value[2], value[3]),