terminal/kitty-gfx: add placement function get selection

This commit is contained in:
Mitchell Hashimoto
2023-08-22 13:15:00 -07:00
parent e4e952d077
commit e6155b7f19
2 changed files with 38 additions and 27 deletions

View File

@ -10,15 +10,16 @@ const Command = command.Command;
const Response = command.Response;
const LoadingImage = image.LoadingImage;
const Image = image.Image;
const ImageStorage = @import("graphics_storage.zig").ImageStorage;
const log = std.log.scoped(.kitty_gfx);
// TODO:
// - delete
// - shared memory transmit
// - terminal state around deleting images (i.e. CSI J)
// - terminal state around deleting placements (i.e. scrolling)
// (not exhaustive, almost every op is ignoring additional config)
/// Execute a Kitty graphics command against the given terminal. This
/// will never fail, but the response may indicate an error and the
/// terminal state may not be updated to reflect the command. This will
@ -167,9 +168,8 @@ fn display(
}).toScreen(&terminal.screen);
// Add the placement
storage.addPlacement(alloc, img.id, d.placement_id, .{
.point = placement_point,
}) catch |err| {
const p: ImageStorage.Placement = .{ .point = placement_point };
storage.addPlacement(alloc, img.id, d.placement_id, p) catch |err| {
encodeError(&result, err);
return result;
};
@ -178,31 +178,11 @@ fn display(
switch (d.cursor_movement) {
.none => {},
.after => {
// Determine the rectangle of the image in grid cells
const image_grid_size: struct {
columns: u32,
rows: u32,
} = grid_size: {
// Calculate our cell size.
const terminal_width_f64: f64 = @floatFromInt(terminal.width_px);
const terminal_height_f64: f64 = @floatFromInt(terminal.height_px);
const grid_columns_f64: f64 = @floatFromInt(terminal.cols);
const grid_rows_f64: f64 = @floatFromInt(terminal.rows);
const cell_width_f64 = terminal_width_f64 / grid_columns_f64;
const cell_height_f64 = terminal_height_f64 / grid_rows_f64;
// Calculate our image size in grid cells
const width_f64: f64 = @floatFromInt(img.width);
const height_f64: f64 = @floatFromInt(img.height);
const width_cells: u32 = @intFromFloat(@ceil(width_f64 / cell_width_f64));
const height_cells: u32 = @intFromFloat(@ceil(height_f64 / cell_height_f64));
break :grid_size .{ .columns = width_cells, .rows = height_cells };
};
const p_sel = p.selection(img, terminal);
// If we are moving beneath the screen we need to scroll.
// TODO: handle scroll regions
var new_y = terminal.screen.cursor.y + image_grid_size.rows + 1;
var new_y = p_sel.end.y + 1;
if (new_y >= terminal.rows) {
const scroll_amount = (new_y + 1) - terminal.rows;
terminal.screen.scroll(.{ .screen = @intCast(scroll_amount) }) catch |err| {
@ -216,7 +196,7 @@ fn display(
// Move the cursor
terminal.setCursorPos(
new_y,
terminal.screen.cursor.x + image_grid_size.columns,
p_sel.end.x,
);
},
}

View File

@ -3,6 +3,7 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const terminal = @import("../main.zig");
const point = @import("../point.zig");
const command = @import("graphics_command.zig");
const Screen = @import("../Screen.zig");
@ -154,5 +155,35 @@ pub const ImageStorage = struct {
pub const Placement = struct {
/// The location of the image on the screen.
point: ScreenPoint,
/// Returns a selection of the entire rectangle this placement
/// occupies within the screen.
pub fn selection(
self: Placement,
image: Image,
t: *const terminal.Terminal,
) terminal.Selection {
// Calculate our cell size.
const terminal_width_f64: f64 = @floatFromInt(t.width_px);
const terminal_height_f64: f64 = @floatFromInt(t.height_px);
const grid_columns_f64: f64 = @floatFromInt(t.cols);
const grid_rows_f64: f64 = @floatFromInt(t.rows);
const cell_width_f64 = terminal_width_f64 / grid_columns_f64;
const cell_height_f64 = terminal_height_f64 / grid_rows_f64;
// Calculate our image size in grid cells
const width_f64: f64 = @floatFromInt(image.width);
const height_f64: f64 = @floatFromInt(image.height);
const width_cells: u32 = @intFromFloat(@ceil(width_f64 / cell_width_f64));
const height_cells: u32 = @intFromFloat(@ceil(height_f64 / cell_height_f64));
return .{
.start = self.point,
.end = .{
.x = @min(t.cols - 1, self.point.x + width_cells),
.y = self.point.y + height_cells,
},
};
}
};
};