From 2ee54879a4b7d806c173a90273fb18c8c78f8fff Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 18 Aug 2024 11:28:51 -0700 Subject: [PATCH] renderer: use fg as extension color for covering glyphs (U+2588) Fixes #2099 This is another heuristic of sorts to make `window-padding-color=extend` look better by default. If a fully covering glyph is used then we use the fg color to extend rather than the background. This doesn't account for fonts that may do this for whatever codepoints, but I think that's a special scenario that we should just recommend disabling this feature. --- src/renderer/Metal.zig | 15 ++++++++++++--- src/renderer/OpenGL.zig | 10 ++++++++++ src/renderer/cell.zig | 12 ++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 116b3b659..6a17ee094 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -22,6 +22,7 @@ const math = @import("../math.zig"); const Surface = @import("../Surface.zig"); const link = @import("link.zig"); const fgMode = @import("cell.zig").fgMode; +const isCovering = @import("cell.zig").isCovering; const shadertoy = @import("shadertoy.zig"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; @@ -2444,12 +2445,21 @@ fn updateCell( // the cell is transparent but still copy-able. const res: BgFg = selection_res orelse cell_res; if (style.flags.invisible) { - break :colors BgFg{ + break :colors .{ .bg = res.bg, .fg = res.bg orelse self.background_color, }; } + // If our cell has a covering glyph, then our bg is set to our fg + // so that padding extension works correctly. + if (!selected and isCovering(cell.codepoint())) { + break :colors .{ + .bg = res.fg, + .fg = res.fg, + }; + } + break :colors res; }; @@ -2489,9 +2499,8 @@ fn updateCell( self.cells.bgCell(coord.y, coord.x).* = .{ rgb.r, rgb.g, rgb.b, bg_alpha, }; - if (cell.gridWidth() > 1 and coord.x < self.cells.size.columns - 1) { - self.cells.bgCell(coord.y, coord.x).* = .{ + self.cells.bgCell(coord.y, coord.x + 1).* = .{ rgb.r, rgb.g, rgb.b, bg_alpha, }; } diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 1a426975d..7e5e140a1 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -9,6 +9,7 @@ const testing = std.testing; const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; const link = @import("link.zig"); +const isCovering = @import("cell.zig").isCovering; const fgMode = @import("cell.zig").fgMode; const shadertoy = @import("shadertoy.zig"); const apprt = @import("../apprt.zig"); @@ -1649,6 +1650,15 @@ fn updateCell( }; } + // If our cell has a covering glyph, then our bg is set to our fg + // so that padding extension works correctly. + if (!selected and isCovering(cell.codepoint())) { + break :colors .{ + .bg = res.fg, + .fg = res.fg, + }; + } + break :colors res; }; diff --git a/src/renderer/cell.zig b/src/renderer/cell.zig index 064aabc87..4fd93db02 100644 --- a/src/renderer/cell.zig +++ b/src/renderer/cell.zig @@ -2,6 +2,18 @@ const ziglyph = @import("ziglyph"); const font = @import("../font/main.zig"); const terminal = @import("../terminal/main.zig"); +/// Returns true if a codepoint for a cell is a covering character. A covering +/// character is a character that covers the entire cell. This is used to +/// make window-padding-color=extend work better. See #2099. +pub fn isCovering(cp: u21) bool { + return switch (cp) { + // U+2588 FULL BLOCK + 0x2588 => true, + + else => false, + }; +} + pub const FgMode = enum { /// Normal non-colored text rendering. The text can leave the cell /// size if it is larger than the cell to allow for ligatures.