terminal: track palette color in cell state

Rather than immediately converting a color palette index into an RGB
value for a cell color, when a palette color is used track the palette
color directly in the cell state and convert to an RGB value in the
renderer.

This causes palette color changes to take effect immediately instead of
only for newly drawn cells.
This commit is contained in:
Gregory Anders
2024-01-02 17:01:00 -06:00
parent 46ccf6b02e
commit 060bdff117
8 changed files with 320 additions and 241 deletions

View File

@@ -649,6 +649,7 @@ pub fn updateFrame(
mouse: renderer.State.Mouse,
preedit: ?renderer.State.Preedit,
cursor_style: ?renderer.CursorStyle,
color_palette: terminal.color.Palette,
};
// Update all our data as tightly as possible within the mutex.
@@ -730,6 +731,7 @@ pub fn updateFrame(
.mouse = state.mouse,
.preedit = preedit,
.cursor_style = cursor_style,
.color_palette = state.terminal.color_palette.colors,
};
};
defer {
@@ -752,6 +754,7 @@ pub fn updateFrame(
critical.mouse,
critical.preedit,
critical.cursor_style,
&critical.color_palette,
);
}
}
@@ -943,6 +946,7 @@ pub fn rebuildCells(
mouse: renderer.State.Mouse,
preedit: ?renderer.State.Preedit,
cursor_style_: ?renderer.CursorStyle,
color_palette: *const terminal.color.Palette,
) !void {
const t = trace(@src());
defer t.end();
@@ -1097,6 +1101,7 @@ pub fn rebuildCells(
term_selection,
screen,
cell,
color_palette,
shaper_cell,
run,
shaper_cell.x,
@@ -1330,11 +1335,12 @@ fn addCursor(
/// Update a single cell. The bool returns whether the cell was updated
/// or not. If the cell wasn't updated, a full refreshCells call is
/// needed.
pub fn updateCell(
fn updateCell(
self: *OpenGL,
selection: ?terminal.Selection,
screen: *terminal.Screen,
cell: terminal.Screen.Cell,
palette: *const terminal.color.Palette,
shaper_cell: font.shape.Cell,
shaper_run: font.shape.TextRun,
x: usize,
@@ -1373,14 +1379,30 @@ pub fn updateCell(
const cell_res: BgFg = if (!cell.attrs.inverse) .{
// In normal mode, background and fg match the cell. We
// un-optionalize the fg by defaulting to our fg color.
.bg = if (cell.attrs.has_bg) cell.bg else null,
.fg = if (cell.attrs.has_fg) cell.fg else self.foreground_color,
.bg = switch (cell.bg) {
.none => null,
.indexed => |i| palette[i],
.rgb => |rgb| rgb,
},
.fg = switch (cell.fg) {
.none => self.foreground_color,
.indexed => |i| palette[i],
.rgb => |rgb| rgb,
},
} else .{
// In inverted mode, the background MUST be set to something
// (is never null) so it is either the fg or default fg. The
// fg is either the bg or default background.
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground_color,
.fg = if (cell.attrs.has_bg) cell.bg else self.background_color,
.bg = switch (cell.fg) {
.none => self.foreground_color,
.indexed => |i| palette[i],
.rgb => |rgb| rgb,
},
.fg = switch (cell.bg) {
.none => self.background_color,
.indexed => |i| palette[i],
.rgb => |rgb| rgb,
},
};
// If we are selected, we our colors are just inverted fg/bg
@@ -1441,7 +1463,7 @@ pub fn updateCell(
// If we have a background and its not the default background
// then we apply background opacity
if (cell.attrs.has_bg and !std.meta.eql(rgb, self.background_color)) {
if (cell.bg != .none and !rgb.eql(self.background_color)) {
break :bg_alpha default;
}