diff --git a/src/renderer/generic.zig b/src/renderer/generic.zig index 8c914e476..48be0d95e 100644 --- a/src/renderer/generic.zig +++ b/src/renderer/generic.zig @@ -15,6 +15,7 @@ const cellpkg = @import("cell.zig"); const noMinContrast = cellpkg.noMinContrast; const constraintWidth = cellpkg.constraintWidth; const isCovering = cellpkg.isCovering; +const rowNeverExtendBg = @import("row.zig").neverExtendBg; const imagepkg = @import("image.zig"); const Image = imagepkg.Image; const ImageMap = imagepkg.ImageMap; @@ -2312,6 +2313,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type { // Get our row data from our state const row_data = state.row_data.slice(); + const row_raws = row_data.items(.raw); const row_cells = row_data.items(.cells); const row_dirty = row_data.items(.dirty); const row_selection = row_data.items(.selection); @@ -2326,10 +2328,11 @@ pub fn Renderer(comptime GraphicsAPI: type) type { ); for ( 0.., + row_raws[0..row_len], row_cells[0..row_len], row_dirty[0..row_len], row_selection[0..row_len], - ) |y_usize, *cells, *dirty, selection| { + ) |y_usize, row, *cells, *dirty, selection| { const y: terminal.size.CellCountInt = @intCast(y_usize); if (!rebuild) { @@ -2343,32 +2346,43 @@ pub fn Renderer(comptime GraphicsAPI: type) type { // Unmark the dirty state in our render state. dirty.* = false; - // TODO: renderstate + // If our viewport is wider than our cell contents buffer, + // we still only process cells up to the width of the buffer. + const cells_slice = cells.slice(); + const cells_len = @min(cells_slice.len, self.cells.size.columns); + const cells_raw = cells_slice.items(.raw); + const cells_style = cells_slice.items(.style); + // On primary screen, we still apply vertical padding // extension under certain conditions we feel are safe. // // This helps make some scenarios look better while // avoiding scenarios we know do NOT look good. - // switch (self.config.padding_color) { - // // These already have the correct values set above. - // .background, .@"extend-always" => {}, - // - // // Apply heuristics for padding extension. - // .extend => if (y == 0) { - // self.uniforms.padding_extend.up = !row.neverExtendBg( - // color_palette, - // background, - // ); - // } else if (y == self.cells.size.rows - 1) { - // self.uniforms.padding_extend.down = !row.neverExtendBg( - // color_palette, - // background, - // ); - // }, - // } + switch (self.config.padding_color) { + // These already have the correct values set above. + .background, .@"extend-always" => {}, + + // Apply heuristics for padding extension. + .extend => if (y == 0) { + self.uniforms.padding_extend.up = !rowNeverExtendBg( + row, + cells_raw, + cells_style, + &state.colors.palette, + state.colors.background, + ); + } else if (y == self.cells.size.rows - 1) { + self.uniforms.padding_extend.down = !rowNeverExtendBg( + row, + cells_raw, + cells_style, + &state.colors.palette, + state.colors.background, + ); + }, + } // Iterator of runs for shaping. - const cells_slice = cells.slice(); var run_iter_opts: font.shape.RunOptions = .{ .grid = self.font_grid, .cells = cells_slice, @@ -2393,11 +2407,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type { var shaper_cells: ?[]const font.shape.Cell = null; var shaper_cells_i: usize = 0; - // If our viewport is wider than our cell contents buffer, - // we still only process cells up to the width of the buffer. - const cells_len = @min(cells_slice.len, self.cells.size.columns); - const cells_raw = cells_slice.items(.raw); - const cells_style = cells_slice.items(.style); for ( 0.., cells_raw[0..cells_len], diff --git a/src/renderer/row.zig b/src/renderer/row.zig new file mode 100644 index 000000000..157d22b54 --- /dev/null +++ b/src/renderer/row.zig @@ -0,0 +1,64 @@ +const std = @import("std"); +const terminal = @import("../terminal/main.zig"); + +// TODO: Test neverExtendBg function + +/// Returns true if the row of this pin should never have its background +/// color extended for filling padding space in the renderer. This is +/// a set of heuristics that help making our padding look better. +pub fn neverExtendBg( + row: terminal.page.Row, + cells: []const terminal.page.Cell, + styles: []const terminal.Style, + palette: *const terminal.color.Palette, + default_background: terminal.color.RGB, +) bool { + // Any semantic prompts should not have their background extended + // because prompts often contain special formatting (such as + // powerline) that looks bad when extended. + switch (row.semantic_prompt) { + .prompt, .prompt_continuation, .input => return true, + .unknown, .command => {}, + } + + for (0.., cells) |x, *cell| { + // If any cell has a default background color then we don't + // extend because the default background color probably looks + // good enough as an extension. + switch (cell.content_tag) { + // If it is a background color cell, we check the color. + .bg_color_palette, .bg_color_rgb => { + const s: terminal.Style = if (cell.hasStyling()) styles[x] else .{}; + const bg = s.bg(cell, palette) orelse return true; + if (bg.eql(default_background)) return true; + }, + + // If its a codepoint cell we can check the style. + .codepoint, .codepoint_grapheme => { + // For codepoint containing, we also never extend bg + // if any cell has a powerline glyph because these are + // perfect-fit. + switch (cell.codepoint()) { + // Powerline + 0xE0B0...0xE0C8, + 0xE0CA, + 0xE0CC...0xE0D2, + 0xE0D4, + => return true, + + else => {}, + } + + // Never extend a cell that has a default background. + // A default background is applied if there is no background + // on the style or the explicitly set background + // matches our default background. + const s: terminal.Style = if (cell.hasStyling()) styles[x] else .{}; + const bg = s.bg(cell, palette) orelse return true; + if (bg.eql(default_background)) return true; + }, + } + } + + return false; +} diff --git a/src/terminal/PageList.zig b/src/terminal/PageList.zig index aab01fa7c..0e793a254 100644 --- a/src/terminal/PageList.zig +++ b/src/terminal/PageList.zig @@ -3977,65 +3977,6 @@ pub const Pin = struct { self.rowAndCell().row.dirty = true; } - /// Returns true if the row of this pin should never have its background - /// color extended for filling padding space in the renderer. This is - /// a set of heuristics that help making our padding look better. - pub fn neverExtendBg( - self: Pin, - palette: *const color.Palette, - default_background: color.RGB, - ) bool { - // Any semantic prompts should not have their background extended - // because prompts often contain special formatting (such as - // powerline) that looks bad when extended. - const rac = self.rowAndCell(); - switch (rac.row.semantic_prompt) { - .prompt, .prompt_continuation, .input => return true, - .unknown, .command => {}, - } - - for (self.cells(.all)) |*cell| { - // If any cell has a default background color then we don't - // extend because the default background color probably looks - // good enough as an extension. - switch (cell.content_tag) { - // If it is a background color cell, we check the color. - .bg_color_palette, .bg_color_rgb => { - const s = self.style(cell); - const bg = s.bg(cell, palette) orelse return true; - if (bg.eql(default_background)) return true; - }, - - // If its a codepoint cell we can check the style. - .codepoint, .codepoint_grapheme => { - // For codepoint containing, we also never extend bg - // if any cell has a powerline glyph because these are - // perfect-fit. - switch (cell.codepoint()) { - // Powerline - 0xE0B0...0xE0C8, - 0xE0CA, - 0xE0CC...0xE0D2, - 0xE0D4, - => return true, - - else => {}, - } - - // Never extend a cell that has a default background. - // A default background is applied if there is no background - // on the style or the explicitly set background - // matches our default background. - const s = self.style(cell); - const bg = s.bg(cell, palette) orelse return true; - if (bg.eql(default_background)) return true; - }, - } - } - - return false; - } - /// Iterators. These are the same as PageList iterator funcs but operate /// on pins rather than points. This is MUCH more efficient than calling /// pointFromPin and building up the iterator from points.