mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
underline is derived from the primary font
This commit is contained in:
1
TODO.md
1
TODO.md
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user