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:
* Underline should use freetype underline thickness hint
* Glyph baseline is using the main font, but it can vary font to font
Performance:

View File

@ -57,7 +57,8 @@ uniform sampler2D text;
uniform sampler2D text_color;
uniform vec2 cell_size;
uniform mat4 projection;
uniform float glyph_baseline;
uniform float underline_position;
uniform float underline_thickness;
/********************************************************************
* Modes
@ -196,18 +197,16 @@ void main() {
break;
case MODE_UNDERLINE:
// Make the underline a smaller version of our cell
// TODO: use real font underline thickness
vec2 underline_size = vec2(cell_size_scaled.x, cell_size_scaled.y*0.05);
// Underline Y value is just our thickness
vec2 underline_size = vec2(cell_size_scaled.x, underline_thickness);
// Position our underline so that it is midway between the glyph
// baseline and the bottom of the cell.
vec2 underline_offset = vec2(cell_size_scaled.x, cell_size_scaled.y - (glyph_baseline / 2));
// Position the underline where we are told to
vec2 underline_offset = vec2(cell_size_scaled.x, underline_position) ;
// Go to the bottom of the cell, take away the size of the
// underline, and that is our position. We also float it slightly
// 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);
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();
defer pbind.unbind();
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
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
/// current font size.
pub fn unitsToPxY(self: Face, units: i32) i32 {
fn unitsToPxY(self: Face, units: i32) i32 {
return @intCast(i32, freetype.mulFix(
units,
@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
/// as the bottom of a "g" or "y" do not drop below the cell.
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
@ -319,18 +324,41 @@ fn calcMetrics(face: freetype.Face) Metrics {
// is reversed.
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,
// cell_width,
// cell_height,
// f26dot6ToFloat(size_metrics.ascender),
// -1 * f26dot6ToFloat(size_metrics.descender),
// cell_baseline,
// cell_height - underline_position,
// underline_thickness,
// });
return .{
.cell_width = cell_width,
.cell_height = cell_height,
.cell_baseline = cell_baseline,
.underline_position = underline_position,
.underline_thickness = underline_thickness,
};
}