renderer: exempt Powerline cells from minimum contrast requirements

With a minimum contrast set, the colored glyphs that Powerline uses
would sometimes be set to white or black while the surrounding background
colors remain unchanged, breaking up contiguous colors on segments of
the Powerline.

This no longer happens with this patch as Powerline glyphs are now
special-cased and exempt from the minimum contrast adjustment.
This commit is contained in:
Leah Amelia Chen
2024-08-06 15:20:14 +08:00
parent 5f0371c189
commit 503dfae6ff
8 changed files with 31 additions and 9 deletions

View File

@ -2481,6 +2481,7 @@ fn updateCell(
.normal => .fg, .normal => .fg,
.color => .fg_color, .color => .fg_color,
.constrained => .fg_constrained, .constrained => .fg_constrained,
.powerline => .fg_powerline,
}; };
try self.cells.add(self.alloc, .text, .{ try self.cells.add(self.alloc, .text, .{

View File

@ -1253,11 +1253,7 @@ pub fn rebuildCells(
const screen_cell = row.cells(.all)[screen.cursor.x]; const screen_cell = row.cells(.all)[screen.cursor.x];
const x = screen.cursor.x - @intFromBool(screen_cell.wide == .spacer_tail); const x = screen.cursor.x - @intFromBool(screen_cell.wide == .spacer_tail);
for (self.cells.items[start_i..]) |cell| { for (self.cells.items[start_i..]) |cell| {
if (cell.grid_col == x and if (cell.grid_col == x and cell.mode.isFg()) {
(cell.mode == .fg or
cell.mode == .fg_color or
cell.mode == .fg_constrained))
{
cursor_cell = cell; cursor_cell = cell;
break; break;
} }
@ -1382,7 +1378,7 @@ pub fn rebuildCells(
_ = try self.addCursor(screen, cursor_style, cursor_color); _ = try self.addCursor(screen, cursor_style, cursor_color);
if (cursor_cell) |*cell| { if (cursor_cell) |*cell| {
if (cell.mode == .fg or cell.mode == .fg_constrained) { if (cell.mode.isFg() and cell.mode != .fg_color) {
const cell_color = if (self.cursor_invert) blk: { const cell_color = if (self.cursor_invert) blk: {
const sty = screen.cursor.page_pin.style(screen.cursor.page_cell); const sty = screen.cursor.page_pin.style(screen.cursor.page_cell);
break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color; break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color;
@ -1708,6 +1704,7 @@ fn updateCell(
.normal => .fg, .normal => .fg,
.color => .fg_color, .color => .fg_color,
.constrained => .fg_constrained, .constrained => .fg_constrained,
.powerline => .fg_powerline,
}; };
try self.cells.append(self.alloc, .{ try self.cells.append(self.alloc, .{

View File

@ -14,6 +14,10 @@ pub const FgMode = enum {
/// size. If a glyph is larger than the cell then it must be resized /// size. If a glyph is larger than the cell then it must be resized
/// to fit. /// to fit.
constrained, constrained,
/// Similar to normal, but the text consists of Powerline glyphs and is
/// optionally exempt from padding color extension and minimum contrast requirements.
powerline,
}; };
/// Returns the appropriate foreground mode for the given cell. This is /// Returns the appropriate foreground mode for the given cell. This is
@ -45,10 +49,9 @@ pub fn fgMode(
break :text .normal; break :text .normal;
} }
// We exempt the Powerline range from this since they exhibit // Special-case Powerline glyphs
// box-drawing behavior and should not be constrained.
if (isPowerline(cp)) { if (isPowerline(cp)) {
break :text .normal; break :text .powerline;
} }
// If we are at the end of the screen its definitely constrained // If we are at the end of the screen its definitely constrained

View File

@ -319,6 +319,7 @@ pub const CellText = extern struct {
fg_constrained = 2, fg_constrained = 2,
fg_color = 3, fg_color = 3,
cursor = 4, cursor = 4,
fg_powerline = 5,
}; };
}; };

View File

@ -53,6 +53,7 @@ pub const CellMode = enum(u8) {
fg = 2, fg = 2,
fg_constrained = 3, fg_constrained = 3,
fg_color = 7, fg_color = 7,
fg_powerline = 15,
// Non-exhaustive because masks change it // Non-exhaustive because masks change it
_, _,
@ -61,6 +62,10 @@ pub const CellMode = enum(u8) {
pub fn mask(self: CellMode, m: CellMode) CellMode { pub fn mask(self: CellMode, m: CellMode) CellMode {
return @enumFromInt(@intFromEnum(self) | @intFromEnum(m)); return @enumFromInt(@intFromEnum(self) | @intFromEnum(m));
} }
pub fn isFg(self: CellMode) bool {
return @intFromEnum(self) & @intFromEnum(@as(CellMode, .fg)) != 0;
}
}; };
pub fn init() !CellProgram { pub fn init() !CellProgram {

View File

@ -28,6 +28,7 @@ const uint MODE_BG = 1u;
const uint MODE_FG = 2u; const uint MODE_FG = 2u;
const uint MODE_FG_CONSTRAINED = 3u; const uint MODE_FG_CONSTRAINED = 3u;
const uint MODE_FG_COLOR = 7u; const uint MODE_FG_COLOR = 7u;
const uint MODE_FG_POWERLINE = 15u;
void main() { void main() {
float a; float a;
@ -39,6 +40,7 @@ void main() {
case MODE_FG: case MODE_FG:
case MODE_FG_CONSTRAINED: case MODE_FG_CONSTRAINED:
case MODE_FG_POWERLINE:
a = texture(text, glyph_tex_coords).r; a = texture(text, glyph_tex_coords).r;
vec3 premult = color.rgb * color.a; vec3 premult = color.rgb * color.a;
out_FragColor = vec4(premult.rgb*a, a); out_FragColor = vec4(premult.rgb*a, a);

View File

@ -162,6 +162,7 @@ enum CellTextMode : uint8_t {
MODE_TEXT_CONSTRAINED = 2u, MODE_TEXT_CONSTRAINED = 2u,
MODE_TEXT_COLOR = 3u, MODE_TEXT_COLOR = 3u,
MODE_TEXT_CURSOR = 4u, MODE_TEXT_CURSOR = 4u,
MODE_TEXT_POWERLINE = 4u,
}; };
struct CellTextVertexIn { struct CellTextVertexIn {
@ -263,6 +264,10 @@ vertex CellTextVertexOut cell_text_vertex(unsigned int vid [[vertex_id]],
// If we have a minimum contrast, we need to check if we need to // If we have a minimum contrast, we need to check if we need to
// change the color of the text to ensure it has enough contrast // change the color of the text to ensure it has enough contrast
// with the background. // with the background.
// We only apply this adjustment to "normal" text with MODE_TEXT,
// since we want color glyphs to appear in their original color
// and Powerline glyphs to be unaffected (else parts of the line would
// have different colors as some parts are displayed via background colors).
if (uniforms.min_contrast > 1.0f && input.mode == MODE_TEXT) { if (uniforms.min_contrast > 1.0f && input.mode == MODE_TEXT) {
float4 bg_color = float4(input.bg_color) / 255.0f; float4 bg_color = float4(input.bg_color) / 255.0f;
out.color = contrasted_color(uniforms.min_contrast, out.color, bg_color); out.color = contrasted_color(uniforms.min_contrast, out.color, bg_color);
@ -288,6 +293,7 @@ fragment float4 cell_text_fragment(CellTextVertexOut in [[stage_in]],
switch (in.mode) { switch (in.mode) {
case MODE_TEXT_CURSOR: case MODE_TEXT_CURSOR:
case MODE_TEXT_CONSTRAINED: case MODE_TEXT_CONSTRAINED:
case MODE_TEXT_POWERLINE:
case MODE_TEXT: { case MODE_TEXT: {
// Normalize the texture coordinates to [0,1] // Normalize the texture coordinates to [0,1]
float2 size = float2 size =

View File

@ -8,6 +8,7 @@ const uint MODE_BG = 1u;
const uint MODE_FG = 2u; const uint MODE_FG = 2u;
const uint MODE_FG_CONSTRAINED = 3u; const uint MODE_FG_CONSTRAINED = 3u;
const uint MODE_FG_COLOR = 7u; const uint MODE_FG_COLOR = 7u;
const uint MODE_FG_POWERLINE = 15u;
// The grid coordinates (x, y) where x < columns and y < rows // The grid coordinates (x, y) where x < columns and y < rows
layout (location = 0) in vec2 grid_coord; layout (location = 0) in vec2 grid_coord;
@ -198,6 +199,7 @@ void main() {
case MODE_FG: case MODE_FG:
case MODE_FG_CONSTRAINED: case MODE_FG_CONSTRAINED:
case MODE_FG_COLOR: case MODE_FG_COLOR:
case MODE_FG_POWERLINE:
vec2 glyph_offset_calc = glyph_offset; vec2 glyph_offset_calc = glyph_offset;
// The glyph_offset.y is the y bearing, a y value that when added // The glyph_offset.y is the y bearing, a y value that when added
@ -227,6 +229,7 @@ void main() {
ivec2 text_size; ivec2 text_size;
switch(mode) { switch(mode) {
case MODE_FG_CONSTRAINED: case MODE_FG_CONSTRAINED:
case MODE_FG_POWERLINE:
case MODE_FG: case MODE_FG:
text_size = textureSize(text, 0); text_size = textureSize(text, 0);
break; break;
@ -242,6 +245,10 @@ void main() {
// If we have a minimum contrast, we need to check if we need to // If we have a minimum contrast, we need to check if we need to
// change the color of the text to ensure it has enough contrast // change the color of the text to ensure it has enough contrast
// with the background. // with the background.
// We only apply this adjustment to "normal" text with MODE_FG,
// since we want color glyphs to appear in their original color
// and Powerline glyphs to be unaffected (else parts of the line would
// have different colors as some parts are displayed via background colors).
vec4 color_final = color_in / 255.0; vec4 color_final = color_in / 255.0;
if (min_contrast > 1.0 && mode == MODE_FG) { if (min_contrast > 1.0 && mode == MODE_FG) {
vec4 bg_color = bg_color_in / 255.0; vec4 bg_color = bg_color_in / 255.0;