summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/gui.zig139
1 files changed, 75 insertions, 64 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index a1e21dc0..ff99bd39 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -1779,8 +1779,8 @@ const Gui = struct {
tagline_percent: u8,
tagline_width: u32,
tagline_height: u32,
- attached_layers: ?*const [pardes.MAX_PANES]pardes.BodyLayer = null,
- attached_tag_layers: ?*const [pardes.MAX_TAG_LAYERS]pardes.TagLayer = null,
+ attached_layers: ?*const [pardes.MAX_PANES]pardes.Layer = null,
+ attached_tag_layers: ?*const [pardes.MAX_TAG_LAYERS]pardes.Layer = null,
cell_w: u32,
cell_h: u32,
ascent: i32,
@@ -3517,7 +3517,7 @@ fn gridCellAtDimensions(
var point: MouseCell = .{ .col = @intFromFloat(@min(@floor(@max(x, 0) / @max(body_w, 1)), 10_000)), .row = row };
if (core) |p| if (p.presentation.pointerFractional(p.screen_w, p.screen_h, x / @max(body_w, 1), y / @max(body_h, 1))) |mapped| {
for (p.surface.tagLayers()) |*layer| {
- if (layer.hitAt(mapped.x * body_w, mapped.y * body_h, body_w, body_h, tagline_w, @floatFromInt(p.row_metrics.tagline_h))) |hit| {
+ if (layer.tagHit(mapped.x * body_w, mapped.y * body_h, body_w, body_h, tagline_w, @floatFromInt(p.row_metrics.tagline_h))) |hit| {
point.tag_hit = hit;
break;
}
@@ -3529,19 +3529,19 @@ fn gridCellAtDimensions(
fn gridCellAtPixels(g: *const Gui, core: ?*const pardes.Pardes, x: f32, y: f32) MouseCell {
var point = gridCellAtDimensions(core, x, y, @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width));
if (core) |p| if (p.presentation.pointerFractional(p.screen_w, p.screen_h, x / @as(f32, @floatFromInt(g.cell_w)), y / @as(f32, @floatFromInt(g.cell_h)))) |mapped| for (p.surface.bodyLayers()) |*layer| {
- if (layer.hitAt(mapped.x * @as(f32, @floatFromInt(g.cell_w)), mapped.y * @as(f32, @floatFromInt(g.cell_h)), @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |hit| {
+ if (layer.bodyHit(mapped.x * @as(f32, @floatFromInt(g.cell_w)), mapped.y * @as(f32, @floatFromInt(g.cell_h)), @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |hit| {
point.body_hit = hit;
break;
}
};
if (core == null) if (g.attached_layers) |layers| for (layers) |*layer| {
- if (layer.hitAt(x, y, @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |body_hit| {
+ if (layer.bodyHit(x, y, @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |body_hit| {
point.body_hit = body_hit;
break;
}
};
if (core == null) if (g.attached_tag_layers) |layers| for (layers) |*layer| {
- if (layer.hitAt(x, y, @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |hit| {
+ if (layer.tagHit(x, y, @floatFromInt(g.cell_w), @floatFromInt(g.cell_h), @floatFromInt(g.tagline_width), @floatFromInt(g.tagline_height))) |hit| {
point.tag_hit = hit;
break;
}
@@ -5203,18 +5203,18 @@ fn renderFrame(
}
}
for (surface.tagLayers()) |*layer| {
- if (layer.cols == 0) continue;
+ if (layer.rows == 0) continue;
const batch = &paint_plan.batches[paintBatchAt(&paint_plan, layer.viewport.x, layer.viewport.y)];
- batch.cell_count += tagLayerCellCount(g, layer) + 1;
+ batch.cell_count += (tagLayerCellCount(g, layer) + 1) * layer.rows;
}
for (paint_plan.batches[1..paint_plan.len], 1..) |batch, batch_index| {
const track = batch.track.?;
const under = track.effect == .vertical and track.phase == .opening;
if (!under and track.phase != .closing and track.effect != .dissolve) continue;
for (surface.previous_tag_layers) |*layer| {
- if (layer.cols == 0 or layer.kind != .pane or layer.serial != track.serial) continue;
+ if (layer.rows == 0 or layer.kind != .pane or layer.serial != track.serial) continue;
const destination = if (under) &paint_plan.batches[0] else &paint_plan.batches[batch_index];
- destination.cell_count += tagLayerCellCount(g, layer) + 1;
+ destination.cell_count += (tagLayerCellCount(g, layer) + 1) * layer.rows;
}
}
var cell_next: [pardes.MAX_PANES * 2 + 1]u32 = @splat(0);
@@ -5303,7 +5303,7 @@ fn renderFrame(
emitBodyLayer(g, instances, &cell_next[batch_index], layer, win_w, win_h, paint_plan.batches[batch_index].track, page, paint_plan.len == 1, false, topbar_pane_border_rgb);
}
for (surface.tagLayers()) |*layer| {
- if (layer.cols == 0) continue;
+ if (layer.rows == 0) continue;
const batch_index = paintBatchAt(&paint_plan, layer.viewport.x, layer.viewport.y);
emitTagLayer(g, instances, &cell_next[batch_index], layer, win_w, win_h, paint_plan.batches[batch_index].track, page, paint_plan.len == 1, false);
}
@@ -5312,7 +5312,7 @@ fn renderFrame(
const under = track.effect == .vertical and track.phase == .opening;
if (!under and track.phase != .closing and track.effect != .dissolve) continue;
for (surface.previous_tag_layers) |*layer| {
- if (layer.cols == 0 or layer.kind != .pane or layer.serial != track.serial) continue;
+ if (layer.rows == 0 or layer.kind != .pane or layer.serial != track.serial) continue;
const destination: usize = if (under) 0 else batch_index;
emitTagLayer(g, instances, &cell_next[destination], layer, win_w, win_h, if (under) null else track, page, false, track.effect == .dissolve);
}
@@ -5621,10 +5621,10 @@ test "compact column and pane underlays share focus tint without tinting the glo
try std.testing.expectEqual(chrome.tag_bg, taglineBaseRgb(core, active.x, pardes.TOPBAR_H));
}
-fn tagLayerIn(layers: []const pardes.TagLayer, col: u16, row: u16) ?*const pardes.TagLayer {
+fn tagLayerIn(layers: []const pardes.Layer, col: u16, row: u16) ?*const pardes.Layer {
for (layers) |*layer| {
const r = layer.viewport;
- if (layer.cols > 0 and row == r.y and col >= r.x and col - r.x < r.w) return layer;
+ if (layer.rows > 0 and row >= r.y and row - r.y < layer.rows and col >= r.x and col - r.x < r.w) return layer;
}
return null;
}
@@ -5633,9 +5633,9 @@ fn tagLayerIn(layers: []const pardes.TagLayer, col: u16, row: u16) ?*const parde
/// themselves: the grid's cell loops skip them. Filling each layer's rectangle
/// once replaces scanning every layer for every cell, which was a third of the
/// gui's CPU on a full screen of text. It marks exactly the cells bodyLayerIn
-/// and tagLayerIn find a layer for: a tag layer covers only its viewport's
-/// first row, and a viewport past the grid covers the grid's part of it.
-fn coverLayers(cover: []bool, cols: u16, rows: u16, body_layers: []const pardes.BodyLayer, tag_layers: []const pardes.TagLayer) void {
+/// and tagLayerIn find a layer for: a tag layer covers its rows, and a
+/// viewport past the grid covers the grid's part of it.
+fn coverLayers(cover: []bool, cols: u16, rows: u16, body_layers: []const pardes.Layer, tag_layers: []const pardes.Layer) void {
@memset(cover, false);
for (body_layers) |*layer| {
const r = layer.viewport;
@@ -5647,12 +5647,13 @@ fn coverLayers(cover: []bool, cols: u16, rows: u16, body_layers: []const pardes.
for (tag_layers) |*layer| {
const r = layer.viewport;
const right = @min(cols, @as(u32, r.x) + r.w);
- if (layer.cols == 0 or r.y >= rows or r.x >= right) continue;
- @memset(cover[@as(usize, r.y) * cols ..][r.x..right], true);
+ if (layer.rows == 0 or r.x >= right) continue;
+ var y: u32 = r.y;
+ while (y < @min(rows, @as(u32, r.y) + layer.rows)) : (y += 1) @memset(cover[y * cols ..][r.x..right], true);
}
}
-fn expectCoverIsScan(cover: []const bool, cols: u16, rows: u16, body_layers: []const pardes.BodyLayer, tag_layers: []const pardes.TagLayer) !void {
+fn expectCoverIsScan(cover: []const bool, cols: u16, rows: u16, body_layers: []const pardes.Layer, tag_layers: []const pardes.Layer) !void {
for (0..rows) |row| for (0..cols) |col| {
const scan = bodyLayerIn(body_layers, @intCast(col), @intCast(row)) != null or tagLayerIn(tag_layers, @intCast(col), @intCast(row)) != null;
try std.testing.expectEqual(scan, cover[row * cols + col]);
@@ -5685,7 +5686,7 @@ test "the layer cover is the per-cell layer scan, over a core's layouts and rand
@memset(&cover, true); // what an earlier frame left
coverLayers(&cover, s.cols, s.rows, s.bodyLayers(), s.tagLayers());
try expectCoverIsScan(&cover, s.cols, s.rows, s.bodyLayers(), s.tagLayers());
- for (s.tagLayers()) |layer| notices = notices or (layer.cols != 0 and layer.kind == .notice);
+ for (s.tagLayers()) |layer| notices = notices or (layer.rows != 0 and layer.kind == .notice);
}
try std.testing.expect(notices);
@@ -5702,8 +5703,8 @@ test "the layer cover is the per-cell layer scan, over a core's layouts and rand
};
var prng = std.Random.DefaultPrng.init(0x6c61796572);
const random = prng.random();
- var body: [pardes.MAX_PANES]pardes.BodyLayer = undefined;
- var tag: [pardes.MAX_TAG_LAYERS]pardes.TagLayer = undefined;
+ var body: [pardes.MAX_PANES]pardes.Layer = undefined;
+ var tag: [pardes.MAX_TAG_LAYERS]pardes.Layer = undefined;
var grid: [64 * 40]bool = undefined;
for (0..3000) |_| {
const cols = random.intRangeAtMost(u16, 1, 64);
@@ -5720,12 +5721,12 @@ test "the layer cover is the per-cell layer scan, over a core's layouts and rand
}
}
-fn tagLayerCellCount(g: *const Gui, layer: *const pardes.TagLayer) u32 {
+fn tagLayerCellCount(g: *const Gui, layer: *const pardes.Layer) u32 {
const pixels = @as(u32, layer.viewport.w) * g.cell_w;
return @min(layer.cols, (pixels + g.tagline_width - 1) / g.tagline_width);
}
-fn emitTagLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.TagLayer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool) void {
+fn emitTagLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.Layer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool) void {
const bw: f32 = @floatFromInt(g.cell_w);
const bh: f32 = @floatFromInt(g.cell_h);
const tw: f32 = @floatFromInt(g.tagline_width);
@@ -5735,20 +5736,25 @@ fn emitTagLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const p
// A band sliding into place is drawn offset and cut at its row's top, so
// it comes out from under whatever is above it.
const slide = layer.slide * bh;
- const top = @as(f32, @floatFromInt(layer.viewport.y)) * bh;
// A window is rarely a whole number of cells wide: a band that ends at
// the last column runs on through the leftover pixels to the edge.
const band_right = if (win_w - right < bw) @max(right, win_w) else right;
- emitInstance(g, instances, next.*, 0, layer.viewport.y, .{ .w = band_right - left, .h = bh, .x_off = left, .y_off = slide }, win_w, win_h, track, .body, (&background)[0..1], 0, null, old_layer, false, page);
- if (slide != 0) clipInstanceTop(&instances[next.*], top, win_h);
- next.* += 1;
- const line_cursor: ?usize = if (layer.cursor) |cu| cu.col else null;
- for (0..tagLayerCellCount(g, layer)) |col| {
- const cursor = if (layer.cursor) |cu| show_cursor and !cu.bar and cu.col == col else false;
- emitInstance(g, instances, next.*, @intCast(col), layer.viewport.y, .{ .w = tw, .h = bh, .x_off = left, .y_off = slide }, win_w, win_h, track, .tagline, layer.cells[0..layer.cols], col, line_cursor, old_layer, cursor, page);
- clipInstanceRight(&instances[next.*], right, win_w);
+ // A row to each line, each a grid row with the tagline's glyphs.
+ for (0..layer.rows) |index| {
+ const y = layer.viewport.y + @as(u16, @intCast(index));
+ const top = @as(f32, @floatFromInt(y)) * bh;
+ emitInstance(g, instances, next.*, 0, y, .{ .w = band_right - left, .h = bh, .x_off = left, .y_off = slide }, win_w, win_h, track, .body, (&background)[0..1], 0, null, old_layer, false, page);
if (slide != 0) clipInstanceTop(&instances[next.*], top, win_h);
next.* += 1;
+ const cells = layer.cells[index * layer.cols ..][0..layer.cols];
+ const line_cursor: ?usize = if (layer.cursor) |cu| (if (cu.y == index) cu.x else null) else null;
+ for (0..tagLayerCellCount(g, layer)) |col| {
+ const cursor = if (layer.cursor) |cu| show_cursor and !cu.bar and cu.x == col and cu.y == index else false;
+ emitInstance(g, instances, next.*, @intCast(col), y, .{ .w = tw, .h = bh, .x_off = left, .y_off = slide }, win_w, win_h, track, .tagline, cells, col, line_cursor, old_layer, cursor, page);
+ clipInstanceRight(&instances[next.*], right, win_w);
+ if (slide != 0) clipInstanceTop(&instances[next.*], top, win_h);
+ next.* += 1;
+ }
}
}
@@ -5760,11 +5766,11 @@ fn clipInstanceTop(instance: *CellInstance, top: f32, win_h: f32) void {
instance.y0 = @max(instance.y1, limit);
}
-fn bodyLayerAt(surface: *const pardes.Surface, col: u16, row: u16) ?*const pardes.BodyLayer {
+fn bodyLayerAt(surface: *const pardes.Surface, col: u16, row: u16) ?*const pardes.Layer {
return bodyLayerIn(surface.bodyLayers(), col, row);
}
-fn bodyLayerIn(layers: []const pardes.BodyLayer, col: u16, row: u16) ?*const pardes.BodyLayer {
+fn bodyLayerIn(layers: []const pardes.Layer, col: u16, row: u16) ?*const pardes.Layer {
for (layers) |*layer| {
const r = layer.viewport;
if (layer.rows > 0 and col >= r.x and col - r.x < r.w and row >= r.y and row - r.y < r.h) return layer;
@@ -5788,7 +5794,7 @@ fn clipBodyInstance(instance: *CellInstance, bottom: f32, win_h: f32) void {
instance.y1 = limit;
}
-fn emitBodyLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.BodyLayer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool, border_rgb: [3]u8) void {
+fn emitBodyLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.Layer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool, border_rgb: [3]u8) void {
const bw: f32 = @floatFromInt(g.cell_w);
const bh: f32 = @floatFromInt(g.cell_h);
const tw: f32 = @floatFromInt(g.tagline_width);
@@ -5851,11 +5857,11 @@ fn gripCellChanged(surface: *const pardes.Surface, col: u16, row: u16) bool {
return false;
}
-fn paneGripCell(layers: []const pardes.TagLayer, cells: []const pardes.Cell, cols: u16, col: u16, row: u16) ?GripCell {
+fn paneGripCell(layers: []const pardes.Layer, cells: []const pardes.Cell, cols: u16, col: u16, row: u16) ?GripCell {
const at = @as(usize, row) * cols + col;
if (at >= cells.len or cells[at].default or cells[at].style.font_role != .tagline) return null;
for (layers) |layer| {
- if (layer.cols == 0 or layer.kind != .pane or layer.viewport.x < pardes.TAG_TEXT_INSET or layer.viewport.y != row) continue;
+ if (layer.rows == 0 or layer.kind != .pane or layer.viewport.x < pardes.TAG_TEXT_INSET or row < layer.viewport.y or row - layer.viewport.y >= layer.rows) continue;
const x = layer.viewport.x - pardes.TAG_TEXT_INSET;
if (col < x or col - x >= config.GUTTER) continue;
const index = @as(usize, row) * cols + x;
@@ -6607,7 +6613,7 @@ test "pane indicator halves share dissolve changes and safe exhausted atlas" {
cells[0].text[0] = '$';
var previous = cells;
previous[0].text[0] = '^';
- var layers = [_]pardes.TagLayer{.{ .kind = .pane, .serial = 1, .viewport = .{ .x = pardes.TAG_TEXT_INSET, .y = 0, .w = 3, .h = 1 }, .cols = 3 }};
+ var layers = [_]pardes.Layer{.{ .kind = .pane, .serial = 1, .viewport = .{ .x = pardes.TAG_TEXT_INSET, .y = 0, .w = 3, .h = 1 }, .cols = 3, .rows = 1 }};
var diffs: [12]pardes.PanelCellDiff = @splat(.unchanged);
diffs[0] = pardes.PanelCellDiff.between(&previous[0], &cells[0]);
var surface: pardes.Surface = .{ .cols = 6, .rows = 2, .cells = &cells, .previous_cells = &previous, .previous_tag_layers = &layers, .cell_diffs = &diffs };
@@ -7316,16 +7322,17 @@ fn buildOverlay(
}
};
if (transient_on) for (surface.tagLayers()) |*layer| {
- if (layer.cols == 0) continue;
+ if (layer.rows == 0) continue;
const cursor = layer.cursor orelse continue;
- if (!cursor.bar or cursor.col >= layer.cols) continue;
+ if (!cursor.bar or cursor.x >= layer.cols or cursor.y >= layer.rows) continue;
const width: f32 = @floatFromInt(g.tagline_width);
const left = @as(f32, @floatFromInt(layer.viewport.x)) * layout.w;
const right = left + @as(f32, @floatFromInt(layer.viewport.w)) * layout.w;
- const x = left + @as(f32, @floatFromInt(cursor.col)) * width;
+ const x = left + @as(f32, @floatFromInt(cursor.x)) * width;
if (x >= right) continue;
- const top = @as(f32, @floatFromInt(layer.viewport.y)) * layout.h + @as(f32, @floatFromInt(taglineBandOffset(layer.viewport.y, builder.win_h, g.cell_h, g.tagline_height)));
- builder.addRect(x, top, @min(right, x + @max(1, width / 8)), top + @as(f32, @floatFromInt(g.tagline_height)), overlayRgb(cursorColor(core, &layer.cells[cursor.col], .tagline)));
+ const y = layer.viewport.y + cursor.y;
+ const top = @as(f32, @floatFromInt(y)) * layout.h + @as(f32, @floatFromInt(taglineBandOffset(y, builder.win_h, g.cell_h, g.tagline_height)));
+ builder.addRect(x, top, @min(right, x + @max(1, width / 8)), top + @as(f32, @floatFromInt(g.tagline_height)), overlayRgb(cursorColor(core, &layer.cells[@as(usize, cursor.y) * layer.cols + cursor.x], .tagline)));
};
if (transient_on) appendTouchOverlay(g, &builder, debug_on);
return @intCast(builder.len);
@@ -7506,7 +7513,7 @@ fn appendPaneChrome(
// off from the text beneath it the way a tagline is: the same colour and
// thickness along its bottom, running to the window edge when it does.
for (surface.tagLayers()) |*layer| {
- if (layer.cols == 0 or layer.kind != .notice) continue;
+ if (layer.rows == 0 or layer.kind != .notice) continue;
const x0 = @as(f32, @floatFromInt(layer.viewport.x)) * layout.w;
const x1 = x0 + @as(f32, @floatFromInt(layer.viewport.w)) * layout.w;
const rule_x1 = if (builder.win_w - x1 < layout.w) @max(x1, builder.win_w) else x1;
@@ -7528,21 +7535,25 @@ fn appendPaneChrome(
fn appendTagGrips(g: *const Gui, surface: *const pardes.Surface, layout: CellLayout, builder: *OverlayBuilder) void {
if (g.tagline_height < 6 or g.tagline_width < 3) return;
for (surface.tagLayers()) |layer| {
- if (layer.cols == 0 or layer.kind != .pane or layer.viewport.x < pardes.TAG_TEXT_INSET) continue;
+ if (layer.rows == 0 or layer.kind != .pane or layer.viewport.x < pardes.TAG_TEXT_INSET) continue;
const x = layer.viewport.x - pardes.TAG_TEXT_INSET;
- const y = layer.viewport.y;
- if (x >= surface.cols or y >= surface.rows) continue;
- const cell = &surface.cells[@as(usize, y) * surface.cols + x];
- if (cell.default or cell.printableAscii() != ' ') continue;
- const rgb = switch (cell.style.fg) {
- .rgb => |rgb| rgb,
- else => continue,
- };
- const center_x = (@as(f32, @floatFromInt(x)) + @as(f32, @floatFromInt(config.GUTTER)) / 2) * layout.w + @as(f32, @floatFromInt(anchorInset(g, y, builder.win_h) / 2));
- const center_y = @as(f32, @floatFromInt(y)) * layout.h + @as(f32, @floatFromInt(taglineBandOffset(y, builder.win_h, g.cell_h, g.tagline_height))) + @as(f32, @floatFromInt(g.tagline_height)) / 2;
- const half_w = @max(1, @min(3, layout.w - 2));
- builder.addRect(@floor(center_x - half_w), @floor(center_y - 2), @floor(center_x + half_w), @floor(center_y - 1), overlayRgb(rgb));
- builder.addRect(@floor(center_x - half_w), @floor(center_y + 1), @floor(center_x + half_w), @floor(center_y + 2), overlayRgb(rgb));
+ // A mark on each of the tag's rows whose grip cell is blank: every
+ // row but the one with the mode's glyph.
+ for (0..layer.rows) |index| {
+ const y = layer.viewport.y + @as(u16, @intCast(index));
+ if (x >= surface.cols or y >= surface.rows) continue;
+ const cell = &surface.cells[@as(usize, y) * surface.cols + x];
+ if (cell.default or cell.printableAscii() != ' ') continue;
+ const rgb = switch (cell.style.fg) {
+ .rgb => |rgb| rgb,
+ else => continue,
+ };
+ const center_x = (@as(f32, @floatFromInt(x)) + @as(f32, @floatFromInt(config.GUTTER)) / 2) * layout.w + @as(f32, @floatFromInt(anchorInset(g, y, builder.win_h) / 2));
+ const center_y = @as(f32, @floatFromInt(y)) * layout.h + @as(f32, @floatFromInt(taglineBandOffset(y, builder.win_h, g.cell_h, g.tagline_height))) + @as(f32, @floatFromInt(g.tagline_height)) / 2;
+ const half_w = @max(1, @min(3, layout.w - 2));
+ builder.addRect(@floor(center_x - half_w), @floor(center_y - 2), @floor(center_x + half_w), @floor(center_y - 1), overlayRgb(rgb));
+ builder.addRect(@floor(center_x - half_w), @floor(center_y + 1), @floor(center_x + half_w), @floor(center_y + 2), overlayRgb(rgb));
+ }
}
}
@@ -7553,8 +7564,8 @@ test "column grips stay unmarked while pane marks retain physical centering" {
g.cell_h = 20;
var cells: [80]pardes.Cell = @splat(.{ .default = false, .style = .{ .fg = .{ .rgb = .{ 100, 120, 140 } } } });
var surface: pardes.Surface = .{ .cols = 20, .rows = 4, .cells = &cells };
- surface.tag_layers[0] = .{ .kind = .column, .viewport = .{ .x = 8, .y = 1, .w = 13, .h = 1 }, .cols = 20 };
- surface.tag_layers[1] = .{ .kind = .pane, .viewport = .{ .x = 8, .y = 3, .w = 13, .h = 1 }, .cols = 20 };
+ surface.tag_layers[0] = .{ .kind = .column, .viewport = .{ .x = 8, .y = 1, .w = 13, .h = 1 }, .cols = 20, .rows = 1 };
+ surface.tag_layers[1] = .{ .kind = .pane, .viewport = .{ .x = 8, .y = 3, .w = 13, .h = 1 }, .cols = 20, .rows = 1 };
var vertices: [24]OverlayVertex = undefined;
var builder: OverlayBuilder = .{ .vertices = &vertices, .win_w = 200, .win_h = 80 };
appendTagGrips(&g, &surface, .{ .w = 10, .h = 20, .x_off = 0, .y_off = 0 }, &builder);
@@ -7927,7 +7938,7 @@ test "compact body layer rendering fills recovered rows and clips the final glyp
g.tagline_height = 12;
g.space_slot = .{ .u = 0, .v = 0 };
var cells: [24]pardes.Cell = @splat(.{});
- var layer: pardes.BodyLayer = .{
+ var layer: pardes.Layer = .{
.viewport = .{ .x = 3, .y = 2, .w = 2, .h = 5 },
.cols = 2,
.rows = 12,
@@ -7967,7 +7978,7 @@ test "compact tag layers fill available width and clip at their physical edge" {
g.tagline_height = 12;
g.space_slot = .{ .u = 0, .v = 0 };
var cells: [6]pardes.Cell = @splat(.{});
- const layer: pardes.TagLayer = .{ .kind = .pane, .id = 0, .serial = 7, .viewport = .{ .x = 2, .y = 3, .w = 3, .h = 1 }, .cols = 6, .cells = &cells, .bg = .{ 20, 30, 40 } };
+ const layer: pardes.Layer = .{ .kind = .pane, .id = 0, .serial = 7, .viewport = .{ .x = 2, .y = 3, .w = 3, .h = 1 }, .cols = 6, .rows = 1, .cells = &cells, .bg = .{ 20, 30, 40 } };
var instances: [8]CellInstance = undefined;
var next: u32 = 0;
emitTagLayer(&g, &instances, &next, &layer, 100, 100, null, Ground.opaqueRgb(bg_default), false, false);