mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
renderer: draw underlines below text to improve legibility
This commit is contained in:
@ -2523,6 +2523,45 @@ fn updateCell(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the cell has an underline, draw it before the character glyph,
|
||||||
|
// so that it layers underneath instead of overtop, since that can
|
||||||
|
// make text difficult to read.
|
||||||
|
if (underline != .none) {
|
||||||
|
const sprite: font.Sprite = switch (underline) {
|
||||||
|
.none => unreachable,
|
||||||
|
.single => .underline,
|
||||||
|
.double => .underline_double,
|
||||||
|
.dotted => .underline_dotted,
|
||||||
|
.dashed => .underline_dashed,
|
||||||
|
.curly => .underline_curly,
|
||||||
|
};
|
||||||
|
|
||||||
|
const render = try self.font_grid.renderGlyph(
|
||||||
|
self.alloc,
|
||||||
|
font.sprite_index,
|
||||||
|
@intFromEnum(sprite),
|
||||||
|
.{
|
||||||
|
.cell_width = if (cell.wide == .wide) 2 else 1,
|
||||||
|
.grid_metrics = self.grid_metrics,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const color = style.underlineColor(palette) orelse colors.fg;
|
||||||
|
|
||||||
|
try self.cells.add(self.alloc, .underline, .{
|
||||||
|
.mode = .fg,
|
||||||
|
.grid_pos = .{ @intCast(coord.x), @intCast(coord.y) },
|
||||||
|
.constraint_width = cell.gridWidth(),
|
||||||
|
.color = .{ color.r, color.g, color.b, alpha },
|
||||||
|
.glyph_pos = .{ render.glyph.atlas_x, render.glyph.atlas_y },
|
||||||
|
.glyph_size = .{ render.glyph.width, render.glyph.height },
|
||||||
|
.bearings = .{
|
||||||
|
@intCast(render.glyph.offset_x),
|
||||||
|
@intCast(render.glyph.offset_y),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// If the shaper cell has a glyph, draw it.
|
// If the shaper cell has a glyph, draw it.
|
||||||
if (shaper_cell.glyph_index) |glyph_index| glyph: {
|
if (shaper_cell.glyph_index) |glyph_index| glyph: {
|
||||||
// Render
|
// Render
|
||||||
@ -2566,42 +2605,6 @@ fn updateCell(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (underline != .none) {
|
|
||||||
const sprite: font.Sprite = switch (underline) {
|
|
||||||
.none => unreachable,
|
|
||||||
.single => .underline,
|
|
||||||
.double => .underline_double,
|
|
||||||
.dotted => .underline_dotted,
|
|
||||||
.dashed => .underline_dashed,
|
|
||||||
.curly => .underline_curly,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = try self.font_grid.renderGlyph(
|
|
||||||
self.alloc,
|
|
||||||
font.sprite_index,
|
|
||||||
@intFromEnum(sprite),
|
|
||||||
.{
|
|
||||||
.cell_width = if (cell.wide == .wide) 2 else 1,
|
|
||||||
.grid_metrics = self.grid_metrics,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const color = style.underlineColor(palette) orelse colors.fg;
|
|
||||||
|
|
||||||
try self.cells.add(self.alloc, .underline, .{
|
|
||||||
.mode = .fg,
|
|
||||||
.grid_pos = .{ @intCast(coord.x), @intCast(coord.y) },
|
|
||||||
.constraint_width = cell.gridWidth(),
|
|
||||||
.color = .{ color.r, color.g, color.b, alpha },
|
|
||||||
.glyph_pos = .{ render.glyph.atlas_x, render.glyph.atlas_y },
|
|
||||||
.glyph_size = .{ render.glyph.width, render.glyph.height },
|
|
||||||
.bearings = .{
|
|
||||||
@intCast(render.glyph.offset_x),
|
|
||||||
@intCast(render.glyph.offset_y),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style.flags.strikethrough) {
|
if (style.flags.strikethrough) {
|
||||||
const render = try self.font_grid.renderGlyph(
|
const render = try self.font_grid.renderGlyph(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
|
@ -1761,6 +1761,53 @@ fn updateCell(
|
|||||||
@intFromFloat(@max(0, @min(255, @round(self.config.background_opacity * 255)))),
|
@intFromFloat(@max(0, @min(255, @round(self.config.background_opacity * 255)))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If the cell has an underline, draw it before the character glyph,
|
||||||
|
// so that it layers underneath instead of overtop, since that can
|
||||||
|
// make text difficult to read.
|
||||||
|
if (underline != .none) {
|
||||||
|
const sprite: font.Sprite = switch (underline) {
|
||||||
|
.none => unreachable,
|
||||||
|
.single => .underline,
|
||||||
|
.double => .underline_double,
|
||||||
|
.dotted => .underline_dotted,
|
||||||
|
.dashed => .underline_dashed,
|
||||||
|
.curly => .underline_curly,
|
||||||
|
};
|
||||||
|
|
||||||
|
const render = try self.font_grid.renderGlyph(
|
||||||
|
self.alloc,
|
||||||
|
font.sprite_index,
|
||||||
|
@intFromEnum(sprite),
|
||||||
|
.{
|
||||||
|
.cell_width = if (cell.wide == .wide) 2 else 1,
|
||||||
|
.grid_metrics = self.grid_metrics,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const color = style.underlineColor(palette) orelse colors.fg;
|
||||||
|
|
||||||
|
try self.cells.append(self.alloc, .{
|
||||||
|
.mode = .fg,
|
||||||
|
.grid_col = @intCast(x),
|
||||||
|
.grid_row = @intCast(y),
|
||||||
|
.grid_width = cell.gridWidth(),
|
||||||
|
.glyph_x = render.glyph.atlas_x,
|
||||||
|
.glyph_y = render.glyph.atlas_y,
|
||||||
|
.glyph_width = render.glyph.width,
|
||||||
|
.glyph_height = render.glyph.height,
|
||||||
|
.glyph_offset_x = render.glyph.offset_x,
|
||||||
|
.glyph_offset_y = render.glyph.offset_y,
|
||||||
|
.r = color.r,
|
||||||
|
.g = color.g,
|
||||||
|
.b = color.b,
|
||||||
|
.a = alpha,
|
||||||
|
.bg_r = bg[0],
|
||||||
|
.bg_g = bg[1],
|
||||||
|
.bg_b = bg[2],
|
||||||
|
.bg_a = bg[3],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// If the cell has a character, draw it
|
// If the cell has a character, draw it
|
||||||
if (cell.hasText()) fg: {
|
if (cell.hasText()) fg: {
|
||||||
// Render
|
// Render
|
||||||
@ -1807,50 +1854,6 @@ fn updateCell(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (underline != .none) {
|
|
||||||
const sprite: font.Sprite = switch (underline) {
|
|
||||||
.none => unreachable,
|
|
||||||
.single => .underline,
|
|
||||||
.double => .underline_double,
|
|
||||||
.dotted => .underline_dotted,
|
|
||||||
.dashed => .underline_dashed,
|
|
||||||
.curly => .underline_curly,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = try self.font_grid.renderGlyph(
|
|
||||||
self.alloc,
|
|
||||||
font.sprite_index,
|
|
||||||
@intFromEnum(sprite),
|
|
||||||
.{
|
|
||||||
.cell_width = if (cell.wide == .wide) 2 else 1,
|
|
||||||
.grid_metrics = self.grid_metrics,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const color = style.underlineColor(palette) orelse colors.fg;
|
|
||||||
|
|
||||||
try self.cells.append(self.alloc, .{
|
|
||||||
.mode = .fg,
|
|
||||||
.grid_col = @intCast(x),
|
|
||||||
.grid_row = @intCast(y),
|
|
||||||
.grid_width = cell.gridWidth(),
|
|
||||||
.glyph_x = render.glyph.atlas_x,
|
|
||||||
.glyph_y = render.glyph.atlas_y,
|
|
||||||
.glyph_width = render.glyph.width,
|
|
||||||
.glyph_height = render.glyph.height,
|
|
||||||
.glyph_offset_x = render.glyph.offset_x,
|
|
||||||
.glyph_offset_y = render.glyph.offset_y,
|
|
||||||
.r = color.r,
|
|
||||||
.g = color.g,
|
|
||||||
.b = color.b,
|
|
||||||
.a = alpha,
|
|
||||||
.bg_r = bg[0],
|
|
||||||
.bg_g = bg[1],
|
|
||||||
.bg_b = bg[2],
|
|
||||||
.bg_a = bg[3],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style.flags.strikethrough) {
|
if (style.flags.strikethrough) {
|
||||||
const render = try self.font_grid.renderGlyph(
|
const render = try self.font_grid.renderGlyph(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
|
Reference in New Issue
Block a user