mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: swap codepointwidth implementations
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
# - "ascii", uniform random ASCII bytes
|
||||
# - "utf8", uniform random unicode characters, encoded as utf8
|
||||
# - "rand", pure random data, will contain many invalid code sequences.
|
||||
DATA="ascii"
|
||||
DATA="utf8"
|
||||
SIZE="25000000"
|
||||
|
||||
# Add additional arguments
|
||||
|
@ -187,12 +187,15 @@ static_assert(std::size(eaw_gte) == std::size(eaw_lte));
|
||||
static_assert(std::size(zero_gte) == std::size(zero_lte));
|
||||
static_assert(std::size(nsm_gte) == std::size(nsm_lte));
|
||||
|
||||
/// Vectorized implementation of Unicode display width. Determining width
|
||||
/// unfortunately requires many small range checks, so we test some fast paths
|
||||
/// and otherwise try to do N (vector lane width) range checks at a time.
|
||||
template <class D>
|
||||
int8_t CodepointWidthImpl(D d, T input) {
|
||||
// If the input is ASCII, then we return 1. We do NOT check for
|
||||
// control characters because we assume that the input has already
|
||||
// been checked for that case.
|
||||
if (input < 0xFF) {
|
||||
if (input <= 0xFF) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -201,14 +204,6 @@ int8_t CodepointWidthImpl(D d, T input) {
|
||||
const hn::Vec<D> input_vec = Set(d, input);
|
||||
|
||||
{
|
||||
// Thes are the ranges (inclusive) of the codepoints that are DEFINITELY
|
||||
// width 2. We will check as many in parallel as possible.
|
||||
//
|
||||
// The zero padding is so that we can always load aligned directly into
|
||||
// a vector register of any size up to 16 bytes (AVX512).
|
||||
//
|
||||
// Ranges: two-em dash, gbp.isRegionalIndicator, CJK...
|
||||
//
|
||||
// NOTE: 0x2E3B is technically width 3 but for our terminal we only
|
||||
// handle up to width 2 as wide so we will treat it as width 2.
|
||||
HWY_ALIGN constexpr T gte_keys[] = {
|
||||
@ -233,7 +228,6 @@ int8_t CodepointWidthImpl(D d, T input) {
|
||||
}
|
||||
|
||||
{
|
||||
// Definitely width 0
|
||||
HWY_ALIGN constexpr T gte_keys[] = {
|
||||
0x1160, 0x2060, 0xFFF0, 0xE0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ const ziglyph = @import("ziglyph");
|
||||
const testing = std.testing;
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const simd = @import("../simd/main.zig");
|
||||
|
||||
const ansi = @import("ansi.zig");
|
||||
const modes = @import("modes.zig");
|
||||
@ -869,10 +870,13 @@ pub fn print(self: *Terminal, c: u21) !void {
|
||||
|
||||
// Determine the width of this character so we can handle
|
||||
// non-single-width characters properly.
|
||||
const width: usize = @intCast(@min(
|
||||
@max(0, ziglyph.display_width.codePointWidth(c, .half)),
|
||||
2,
|
||||
));
|
||||
const width: usize = @intCast(simd.codepointWidth(c));
|
||||
|
||||
// Old implementation, 3x slower on ASCII, 2x slower on CJK, etc.
|
||||
// const width: usize = @intCast(@min(
|
||||
// @max(0, ziglyph.display_width.codePointWidth(c, .half)),
|
||||
// 2,
|
||||
// ));
|
||||
|
||||
// Note: it is possible to have a width of "3" and a width of "-1"
|
||||
// from ziglyph. We should look into those cases and handle them
|
||||
@ -2304,31 +2308,6 @@ test "Terminal: print over wide spacer tail" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: zero width chars with grapheme clustering can be put in their own cell" {
|
||||
var t = try init(testing.allocator, 5, 5);
|
||||
defer t.deinit(testing.allocator);
|
||||
|
||||
// Enable grapheme clustering
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
try t.print('x');
|
||||
try t.print(0x7F); // zero-width control character
|
||||
|
||||
{
|
||||
const str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("x", str);
|
||||
}
|
||||
|
||||
const row = t.screen.getRow(.{ .screen = 0 });
|
||||
{
|
||||
const cell = row.getCell(0);
|
||||
try testing.expectEqual(@as(u32, 'x'), cell.char);
|
||||
try testing.expect(!cell.attrs.wide);
|
||||
try testing.expect(!cell.attrs.grapheme);
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: VS15 to make narrow character" {
|
||||
var t = try init(testing.allocator, 5, 5);
|
||||
defer t.deinit(testing.allocator);
|
||||
|
Reference in New Issue
Block a user