mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-06 09:56:34 +00:00
temrinal/kitty: really basic row/col diacritic decoding
This commit is contained in:
@@ -3224,7 +3224,7 @@ pub const Pin = struct {
|
|||||||
|
|
||||||
/// Returns the grapheme codepoints for the given cell. These are only
|
/// Returns the grapheme codepoints for the given cell. These are only
|
||||||
/// the EXTRA codepoints and not the first codepoint.
|
/// the EXTRA codepoints and not the first codepoint.
|
||||||
pub fn grapheme(self: Pin, cell: *pagepkg.Cell) ?[]u21 {
|
pub fn grapheme(self: Pin, cell: *const pagepkg.Cell) ?[]u21 {
|
||||||
return self.page.data.lookupGrapheme(cell);
|
return self.page.data.lookupGrapheme(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,21 +32,60 @@ pub const PlacementIterator = struct {
|
|||||||
// A row must have graphemes to possibly have virtual placements
|
// A row must have graphemes to possibly have virtual placements
|
||||||
// since virtual placements are done via diacritics.
|
// since virtual placements are done via diacritics.
|
||||||
if (row.rowAndCell().row.grapheme) {
|
if (row.rowAndCell().row.grapheme) {
|
||||||
|
// TODO: document
|
||||||
|
const prev: ?Placement = null;
|
||||||
|
_ = prev;
|
||||||
|
|
||||||
// Iterate over our remaining cells and find one with a placeholder.
|
// Iterate over our remaining cells and find one with a placeholder.
|
||||||
const cells = row.cells(.right);
|
const cells = row.cells(.right);
|
||||||
for (cells, row.x..) |cell, x| {
|
for (cells, row.x..) |*cell, x| {
|
||||||
if (cell.codepoint() != placeholder) continue;
|
if (cell.codepoint() != placeholder) continue;
|
||||||
|
|
||||||
|
// TODO: we need to support non-grapheme cells that just
|
||||||
|
// do continuations all the way through.
|
||||||
|
assert(cell.hasGrapheme());
|
||||||
|
|
||||||
|
// "row" now points to the top-left pin of the placement.
|
||||||
|
row.x = @intCast(x);
|
||||||
|
|
||||||
|
// Build our placement
|
||||||
|
var p: Placement = .{
|
||||||
|
.pin = row.*,
|
||||||
|
|
||||||
|
// Filled in below. Marked as undefined so we can catch
|
||||||
|
// bugs with safety checks.
|
||||||
|
.col = undefined,
|
||||||
|
.row = undefined,
|
||||||
|
|
||||||
|
// For now we don't build runs and we always produce
|
||||||
|
// single cell placements.
|
||||||
|
.width = 1,
|
||||||
|
.height = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine our row/col by looking at the diacritics.
|
||||||
|
const cps: []const u21 = row.grapheme(cell) orelse &.{};
|
||||||
|
if (cps.len > 0) {
|
||||||
|
p.row = getIndex(cps[0]) orelse @panic("TODO: invalid");
|
||||||
|
if (cps.len > 1) {
|
||||||
|
p.col = getIndex(cps[1]) orelse @panic("TODO: invalid");
|
||||||
|
if (cps.len > 2) {
|
||||||
|
@panic("TODO: higher 8 bits of image ID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else @panic("TODO: continuations");
|
||||||
|
|
||||||
if (x == cells.len - 1) {
|
if (x == cells.len - 1) {
|
||||||
// We are at the end of this row so move to the next row
|
// We are at the end of this row so move to the next row
|
||||||
self.row = self.row_it.next();
|
self.row = self.row_it.next();
|
||||||
} else {
|
} else {
|
||||||
// We can move right to the next cell.
|
// We can move right to the next cell. row is a pointer
|
||||||
row.x = @intCast(x + 1);
|
// to self.row so we can modify it directly.
|
||||||
|
assert(@intFromPtr(row) == @intFromPtr(&self.row));
|
||||||
|
row.x += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
return p;
|
||||||
return .{};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,16 +99,30 @@ pub const PlacementIterator = struct {
|
|||||||
|
|
||||||
/// A virtual placement in the terminal. This can represent more than
|
/// A virtual placement in the terminal. This can represent more than
|
||||||
/// one cell if the cells combine to be a run.
|
/// one cell if the cells combine to be a run.
|
||||||
pub const Placement = struct {};
|
pub const Placement = struct {
|
||||||
|
/// The top-left pin of the placement. This can be used to get the
|
||||||
|
/// screen x/y.
|
||||||
|
pin: terminal.Pin,
|
||||||
|
|
||||||
|
/// Starting row/col index for the image itself. This is the "fragment"
|
||||||
|
/// of the image we want to show in this placement. This is 0-indexed.
|
||||||
|
col: u32,
|
||||||
|
row: u32,
|
||||||
|
|
||||||
|
/// The width/height in cells of this placement.
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
};
|
||||||
|
|
||||||
/// Get the row/col index for a diacritic codepoint. These are 0-indexed.
|
/// Get the row/col index for a diacritic codepoint. These are 0-indexed.
|
||||||
pub fn getIndex(cp: u21) ?usize {
|
pub fn getIndex(cp: u21) ?u32 {
|
||||||
return std.sort.binarySearch(u21, cp, diacritics, {}, (struct {
|
const idx = std.sort.binarySearch(u21, cp, diacritics, {}, (struct {
|
||||||
fn order(context: void, lhs: u21, rhs: u21) std.math.Order {
|
fn order(context: void, lhs: u21, rhs: u21) std.math.Order {
|
||||||
_ = context;
|
_ = context;
|
||||||
return std.math.order(lhs, rhs);
|
return std.math.order(lhs, rhs);
|
||||||
}
|
}
|
||||||
}).order);
|
}).order) orelse return null;
|
||||||
|
return @intCast(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// These are the diacritics used with the Kitty graphics protocol
|
/// These are the diacritics used with the Kitty graphics protocol
|
||||||
@@ -425,7 +478,8 @@ test "unicode placement: single" {
|
|||||||
var it = placementIterator(pin, null);
|
var it = placementIterator(pin, null);
|
||||||
{
|
{
|
||||||
const p = it.next().?;
|
const p = it.next().?;
|
||||||
_ = p;
|
try testing.expectEqual(0, p.row);
|
||||||
|
try testing.expectEqual(0, p.col);
|
||||||
}
|
}
|
||||||
try testing.expect(it.next() == null);
|
try testing.expect(it.next() == null);
|
||||||
}
|
}
|
||||||
|
@@ -1220,7 +1220,7 @@ pub const Page = struct {
|
|||||||
/// Returns the codepoints for the given cell. These are the codepoints
|
/// Returns the codepoints for the given cell. These are the codepoints
|
||||||
/// in addition to the first codepoint. The first codepoint is NOT
|
/// in addition to the first codepoint. The first codepoint is NOT
|
||||||
/// included since it is on the cell itself.
|
/// included since it is on the cell itself.
|
||||||
pub fn lookupGrapheme(self: *const Page, cell: *Cell) ?[]u21 {
|
pub fn lookupGrapheme(self: *const Page, cell: *const Cell) ?[]u21 {
|
||||||
const cell_offset = getOffset(Cell, self.memory, cell);
|
const cell_offset = getOffset(Cell, self.memory, cell);
|
||||||
const map = self.grapheme_map.map(self.memory);
|
const map = self.grapheme_map.map(self.memory);
|
||||||
const slice = map.get(cell_offset) orelse return null;
|
const slice = map.get(cell_offset) orelse return null;
|
||||||
|
Reference in New Issue
Block a user