underline is derived from the primary font

This commit is contained in:
Mitchell Hashimoto
2022-10-04 11:08:07 -07:00
parent c149696f61
commit 3d4aacd51d
4 changed files with 41 additions and 14 deletions

View File

@ -1,6 +1,5 @@
Bugs: Bugs:
* Underline should use freetype underline thickness hint
* Glyph baseline is using the main font, but it can vary font to font * Glyph baseline is using the main font, but it can vary font to font
Performance: Performance:

View File

@ -57,7 +57,8 @@ uniform sampler2D text;
uniform sampler2D text_color; uniform sampler2D text_color;
uniform vec2 cell_size; uniform vec2 cell_size;
uniform mat4 projection; uniform mat4 projection;
uniform float glyph_baseline; uniform float underline_position;
uniform float underline_thickness;
/******************************************************************** /********************************************************************
* Modes * Modes
@ -196,18 +197,16 @@ void main() {
break; break;
case MODE_UNDERLINE: case MODE_UNDERLINE:
// Make the underline a smaller version of our cell // Underline Y value is just our thickness
// TODO: use real font underline thickness vec2 underline_size = vec2(cell_size_scaled.x, underline_thickness);
vec2 underline_size = vec2(cell_size_scaled.x, cell_size_scaled.y*0.05);
// Position our underline so that it is midway between the glyph // Position the underline where we are told to
// baseline and the bottom of the cell. vec2 underline_offset = vec2(cell_size_scaled.x, underline_position) ;
vec2 underline_offset = vec2(cell_size_scaled.x, cell_size_scaled.y - (glyph_baseline / 2));
// Go to the bottom of the cell, take away the size of the // Go to the bottom of the cell, take away the size of the
// underline, and that is our position. We also float it slightly // underline, and that is our position. We also float it slightly
// above the bottom. // above the bottom.
cell_pos = cell_pos + underline_offset - underline_size * position; cell_pos = cell_pos + underline_offset - (underline_size * position);
gl_Position = projection * vec4(cell_pos, cell_z, 1.0); gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
color = fg_color_in / 255.0; color = fg_color_in / 255.0;

View File

@ -178,7 +178,8 @@ pub fn init(alloc: Allocator, font_group: *font.GroupCache) !Grid {
const pbind = try program.use(); const pbind = try program.use();
defer pbind.unbind(); defer pbind.unbind();
try program.setUniform("cell_size", @Vector(2, f32){ metrics.cell_width, metrics.cell_height }); try program.setUniform("cell_size", @Vector(2, f32){ metrics.cell_width, metrics.cell_height });
try program.setUniform("glyph_baseline", metrics.cell_baseline); try program.setUniform("underline_position", metrics.underline_position);
try program.setUniform("underline_thickness", metrics.underline_thickness);
// Set all of our texture indexes // Set all of our texture indexes
try program.setUniform("text", 0); try program.setUniform("text", 0);

View File

@ -229,7 +229,7 @@ pub fn renderGlyph(self: Face, alloc: Allocator, atlas: *Atlas, glyph_index: u32
/// Convert 16.6 pixel format to pixels based on the scale factor of the /// Convert 16.6 pixel format to pixels based on the scale factor of the
/// current font size. /// current font size.
pub fn unitsToPxY(self: Face, units: i32) i32 { fn unitsToPxY(self: Face, units: i32) i32 {
return @intCast(i32, freetype.mulFix( return @intCast(i32, freetype.mulFix(
units, units,
@intCast(i32, self.face.handle.*.size.*.metrics.y_scale), @intCast(i32, self.face.handle.*.size.*.metrics.y_scale),
@ -251,6 +251,11 @@ pub const Metrics = struct {
/// the baseline for font rendering. This is chosen so that things such /// the baseline for font rendering. This is chosen so that things such
/// as the bottom of a "g" or "y" do not drop below the cell. /// as the bottom of a "g" or "y" do not drop below the cell.
cell_baseline: f32, cell_baseline: f32,
/// The position of the underline from the top of the cell and the
/// thickness in pixels.
underline_position: f32,
underline_thickness: f32,
}; };
/// Calculate the metrics associated with a face. This is not public because /// Calculate the metrics associated with a face. This is not public because
@ -319,18 +324,41 @@ fn calcMetrics(face: freetype.Face) Metrics {
// is reversed. // is reversed.
const cell_baseline = -1 * f26dot6ToFloat(size_metrics.descender); const cell_baseline = -1 * f26dot6ToFloat(size_metrics.descender);
// log.warn("METRICS={} width={} height={} baseline={} baseline_desc={}", .{ // The underline position. This is a value from the top where the
// underline should go.
const underline_position = underline_pos: {
// We use the declared underline position if its available
const declared = freetype.mulFix(
@intCast(i32, size_metrics.descender) + face.handle.*.underline_position,
@intCast(i32, size_metrics.x_scale),
) >> 6;
if (declared > 0)
break :underline_pos @intToFloat(f32, declared);
// If we have no declared underline position, we go slightly under the
// cell height (mainly: non-scalable fonts, i.e. emoji)
break :underline_pos cell_height - 1;
};
const underline_thickness = @intToFloat(f32, @maximum(1, freetype.mulFix(
face.handle.*.underline_thickness,
@intCast(i32, size_metrics.x_scale),
) >> 6));
// log.warn("METRICS={} width={} height={} baseline={} underline_pos={} underline_thickness={}", .{
// size_metrics, // size_metrics,
// cell_width, // cell_width,
// cell_height, // cell_height,
// f26dot6ToFloat(size_metrics.ascender), // cell_baseline,
// -1 * f26dot6ToFloat(size_metrics.descender), // cell_height - underline_position,
// underline_thickness,
// }); // });
return .{ return .{
.cell_width = cell_width, .cell_width = cell_width,
.cell_height = cell_height, .cell_height = cell_height,
.cell_baseline = cell_baseline, .cell_baseline = cell_baseline,
.underline_position = underline_position,
.underline_thickness = underline_thickness,
}; };
} }