mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
draw octants directly rather than relying on font (#5433)
* implement `yQuads()` and `draw_octant()`, pretty obvious extensions of existing code. to allocate up to 3 potential remainder lines, consider that octants will often appear in a rectangular subset of the terminal. we want the distributed excess uniformly distributed across such a region. so: * one excess row: break symmetry in any direction (pick an arbitrary tetrad and use it everywhere) * two excess rows: go to alternating tetrads * three excess rows: break symmetry, do not use three contiguous tetrads * our `Octant`s are octary arrays of `bool`, provided as a somewhat opaque constant table * the 8-line copy-and-paste draw based on the `Octant` is not the prettiest thing in the known universe * we could generalize `draw_sextant()` and `draw_octant()` like notcurses did, almost certainly * oh bird thou never wert with that said, i don't think `draw_octant()` is actually being called lol, so let's not merge this yet. happy to hear early feedback, though.
This commit is contained in:
@ -184,6 +184,10 @@ const SmoothMosaic = packed struct(u10) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Octant range, inclusive
|
||||||
|
const octant_min = 0x1cd00;
|
||||||
|
const octant_max = 0x1cde5;
|
||||||
|
|
||||||
// Utility names for common fractions
|
// Utility names for common fractions
|
||||||
const one_eighth: f64 = 0.125;
|
const one_eighth: f64 = 0.125;
|
||||||
const one_quarter: f64 = 0.25;
|
const one_quarter: f64 = 0.25;
|
||||||
@ -581,6 +585,8 @@ fn draw(self: Box, alloc: Allocator, canvas: *font.sprite.Canvas, cp: u32) !void
|
|||||||
|
|
||||||
0x1fb00...0x1fb3b => self.draw_sextant(canvas, cp),
|
0x1fb00...0x1fb3b => self.draw_sextant(canvas, cp),
|
||||||
|
|
||||||
|
octant_min...octant_max => self.draw_octant(canvas, cp),
|
||||||
|
|
||||||
// '🬼'
|
// '🬼'
|
||||||
0x1fb3c => try self.draw_smooth_mosaic(canvas, SmoothMosaic.from(
|
0x1fb3c => try self.draw_smooth_mosaic(canvas, SmoothMosaic.from(
|
||||||
\\...
|
\\...
|
||||||
@ -2484,6 +2490,65 @@ fn draw_sextant(self: Box, canvas: *font.sprite.Canvas, cp: u32) void {
|
|||||||
if (sex.br) self.rect(canvas, x_halfs[1], y_thirds[1], self.metrics.cell_width, self.metrics.cell_height);
|
if (sex.br) self.rect(canvas, x_halfs[1], y_thirds[1], self.metrics.cell_width, self.metrics.cell_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_octant(self: Box, canvas: *font.sprite.Canvas, cp: u32) void {
|
||||||
|
assert(cp >= octant_min and cp <= octant_max);
|
||||||
|
|
||||||
|
// Octant representation. We use the funny numeric string keys
|
||||||
|
// so its easier to parse the actual name used in the Symbols for
|
||||||
|
// Legacy Computing spec.
|
||||||
|
const Octant = packed struct(u8) {
|
||||||
|
@"1": bool = false,
|
||||||
|
@"2": bool = false,
|
||||||
|
@"3": bool = false,
|
||||||
|
@"4": bool = false,
|
||||||
|
@"5": bool = false,
|
||||||
|
@"6": bool = false,
|
||||||
|
@"7": bool = false,
|
||||||
|
@"8": bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse the octant data. This is all done at comptime so this is
|
||||||
|
// static data that is embedded in the binary.
|
||||||
|
const octants_len = octant_max - octant_min + 1;
|
||||||
|
const octants: [octants_len]Octant = comptime octants: {
|
||||||
|
@setEvalBranchQuota(10_000);
|
||||||
|
|
||||||
|
var result: [octants_len]Octant = .{.{}} ** octants_len;
|
||||||
|
var i: usize = 0;
|
||||||
|
|
||||||
|
const data = @embedFile("octants.txt");
|
||||||
|
var it = std.mem.splitScalar(u8, data, '\n');
|
||||||
|
while (it.next()) |line| {
|
||||||
|
// Skip comments
|
||||||
|
if (line.len == 0 or line[0] == '#') continue;
|
||||||
|
|
||||||
|
const current = &result[i];
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
// Octants are in the format "BLOCK OCTANT-1235". The numbers
|
||||||
|
// at the end are keys into our packed struct. Since we're
|
||||||
|
// at comptime we can metaprogram it all.
|
||||||
|
const idx = std.mem.indexOfScalar(u8, line, '-').?;
|
||||||
|
for (line[idx + 1 ..]) |c| @field(current, &.{c}) = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(i == octants_len);
|
||||||
|
break :octants result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const x_halfs = self.xHalfs();
|
||||||
|
const y_quads = self.yQuads();
|
||||||
|
const oct = octants[cp - octant_min];
|
||||||
|
if (oct.@"1") self.rect(canvas, 0, 0, x_halfs[0], y_quads[0]);
|
||||||
|
if (oct.@"2") self.rect(canvas, x_halfs[1], 0, self.metrics.cell_width, y_quads[0]);
|
||||||
|
if (oct.@"3") self.rect(canvas, 0, y_quads[0], x_halfs[0], y_quads[1]);
|
||||||
|
if (oct.@"4") self.rect(canvas, x_halfs[1], y_quads[0], self.metrics.cell_width, y_quads[1]);
|
||||||
|
if (oct.@"5") self.rect(canvas, 0, y_quads[1], x_halfs[0], y_quads[2]);
|
||||||
|
if (oct.@"6") self.rect(canvas, x_halfs[1], y_quads[1], self.metrics.cell_width, y_quads[2]);
|
||||||
|
if (oct.@"7") self.rect(canvas, 0, y_quads[2], x_halfs[0], self.metrics.cell_height);
|
||||||
|
if (oct.@"8") self.rect(canvas, x_halfs[1], y_quads[2], self.metrics.cell_width, self.metrics.cell_height);
|
||||||
|
}
|
||||||
|
|
||||||
fn xHalfs(self: Box) [2]u32 {
|
fn xHalfs(self: Box) [2]u32 {
|
||||||
return .{
|
return .{
|
||||||
@as(u32, @intFromFloat(@round(@as(f64, @floatFromInt(self.metrics.cell_width)) / 2))),
|
@as(u32, @intFromFloat(@round(@as(f64, @floatFromInt(self.metrics.cell_width)) / 2))),
|
||||||
@ -2500,6 +2565,21 @@ fn yThirds(self: Box) [2]u32 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assume octants might be striped across multiple rows of cells. to maximize
|
||||||
|
// distance between excess pixellines, we want (1) an arbitrary region (there
|
||||||
|
// will be a pattern of 1'-3-1'-3-1'-3 no matter what), (2) discontiguous
|
||||||
|
// regions (0 and 2 or 1 and 3), and (3) an arbitrary three regions (there will
|
||||||
|
// be a pattern of 3-1-3-1-3-1 no matter what).
|
||||||
|
fn yQuads(self: Box) [3]u32 {
|
||||||
|
return switch (@mod(self.metrics.cell_height, 4)) {
|
||||||
|
0 => .{ self.metrics.cell_height / 4, 2 * self.metrics.cell_height / 4, 3 * self.metrics.cell_height / 4 },
|
||||||
|
1 => .{ self.metrics.cell_height / 4, 2 * self.metrics.cell_height / 4 + 1, 3 * self.metrics.cell_height / 4 },
|
||||||
|
2 => .{ self.metrics.cell_height / 4 + 1, 2 * self.metrics.cell_height / 4, 3 * self.metrics.cell_height / 4 + 1 },
|
||||||
|
3 => .{ self.metrics.cell_height / 4 + 1, 2 * self.metrics.cell_height / 4 + 1, 3 * self.metrics.cell_height / 4 },
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn draw_smooth_mosaic(
|
fn draw_smooth_mosaic(
|
||||||
self: Box,
|
self: Box,
|
||||||
canvas: *font.sprite.Canvas,
|
canvas: *font.sprite.Canvas,
|
||||||
@ -3064,7 +3144,7 @@ fn testRenderAll(self: Box, alloc: Allocator, atlas: *font.Atlas) !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Symbols for Legacy Computing Supplement.
|
// Symbols for Legacy Computing Supplement: Quadrants
|
||||||
//
|
//
|
||||||
cp = 0x1cc21;
|
cp = 0x1cc21;
|
||||||
while (cp <= 0x1cc2f) : (cp += 1) {
|
while (cp <= 0x1cc2f) : (cp += 1) {
|
||||||
@ -3077,6 +3157,19 @@ fn testRenderAll(self: Box, alloc: Allocator, atlas: *font.Atlas) !void {
|
|||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Symbols for Legacy Computing Supplement: Octants
|
||||||
|
cp = 0x1CD00;
|
||||||
|
while (cp <= 0x1CDE5) : (cp += 1) {
|
||||||
|
switch (cp) {
|
||||||
|
0x1CD00...0x1CDE5 => _ = try self.renderGlyph(
|
||||||
|
alloc,
|
||||||
|
atlas,
|
||||||
|
cp,
|
||||||
|
),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "render all sprites" {
|
test "render all sprites" {
|
||||||
|
@ -236,6 +236,8 @@ const Kind = enum {
|
|||||||
// (Geometric Shapes)
|
// (Geometric Shapes)
|
||||||
//
|
//
|
||||||
0x1FBCE...0x1FBEF,
|
0x1FBCE...0x1FBEF,
|
||||||
|
// (Octants)
|
||||||
|
0x1CD00...0x1CDE5,
|
||||||
=> .box,
|
=> .box,
|
||||||
|
|
||||||
// Branch drawing character set, used for drawing git-like
|
// Branch drawing character set, used for drawing git-like
|
||||||
|
234
src/font/sprite/octants.txt
Normal file
234
src/font/sprite/octants.txt
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
# This is the list of all the octants for the Symbols for Legacy
|
||||||
|
# Computing block. It is used at comptime to generate the lookup
|
||||||
|
# table for drawing them since we weren't able to discern a
|
||||||
|
# mathematical pattern for them.
|
||||||
|
BLOCK OCTANT-3
|
||||||
|
BLOCK OCTANT-23
|
||||||
|
BLOCK OCTANT-123
|
||||||
|
BLOCK OCTANT-4
|
||||||
|
BLOCK OCTANT-14
|
||||||
|
BLOCK OCTANT-124
|
||||||
|
BLOCK OCTANT-34
|
||||||
|
BLOCK OCTANT-134
|
||||||
|
BLOCK OCTANT-234
|
||||||
|
BLOCK OCTANT-5
|
||||||
|
BLOCK OCTANT-15
|
||||||
|
BLOCK OCTANT-25
|
||||||
|
BLOCK OCTANT-125
|
||||||
|
BLOCK OCTANT-135
|
||||||
|
BLOCK OCTANT-235
|
||||||
|
BLOCK OCTANT-1235
|
||||||
|
BLOCK OCTANT-45
|
||||||
|
BLOCK OCTANT-145
|
||||||
|
BLOCK OCTANT-245
|
||||||
|
BLOCK OCTANT-1245
|
||||||
|
BLOCK OCTANT-345
|
||||||
|
BLOCK OCTANT-1345
|
||||||
|
BLOCK OCTANT-2345
|
||||||
|
BLOCK OCTANT-12345
|
||||||
|
BLOCK OCTANT-6
|
||||||
|
BLOCK OCTANT-16
|
||||||
|
BLOCK OCTANT-26
|
||||||
|
BLOCK OCTANT-126
|
||||||
|
BLOCK OCTANT-36
|
||||||
|
BLOCK OCTANT-136
|
||||||
|
BLOCK OCTANT-236
|
||||||
|
BLOCK OCTANT-1236
|
||||||
|
BLOCK OCTANT-146
|
||||||
|
BLOCK OCTANT-246
|
||||||
|
BLOCK OCTANT-1246
|
||||||
|
BLOCK OCTANT-346
|
||||||
|
BLOCK OCTANT-1346
|
||||||
|
BLOCK OCTANT-2346
|
||||||
|
BLOCK OCTANT-12346
|
||||||
|
BLOCK OCTANT-56
|
||||||
|
BLOCK OCTANT-156
|
||||||
|
BLOCK OCTANT-256
|
||||||
|
BLOCK OCTANT-1256
|
||||||
|
BLOCK OCTANT-356
|
||||||
|
BLOCK OCTANT-1356
|
||||||
|
BLOCK OCTANT-2356
|
||||||
|
BLOCK OCTANT-12356
|
||||||
|
BLOCK OCTANT-456
|
||||||
|
BLOCK OCTANT-1456
|
||||||
|
BLOCK OCTANT-2456
|
||||||
|
BLOCK OCTANT-12456
|
||||||
|
BLOCK OCTANT-3456
|
||||||
|
BLOCK OCTANT-13456
|
||||||
|
BLOCK OCTANT-23456
|
||||||
|
BLOCK OCTANT-17
|
||||||
|
BLOCK OCTANT-27
|
||||||
|
BLOCK OCTANT-127
|
||||||
|
BLOCK OCTANT-37
|
||||||
|
BLOCK OCTANT-137
|
||||||
|
BLOCK OCTANT-237
|
||||||
|
BLOCK OCTANT-1237
|
||||||
|
BLOCK OCTANT-47
|
||||||
|
BLOCK OCTANT-147
|
||||||
|
BLOCK OCTANT-247
|
||||||
|
BLOCK OCTANT-1247
|
||||||
|
BLOCK OCTANT-347
|
||||||
|
BLOCK OCTANT-1347
|
||||||
|
BLOCK OCTANT-2347
|
||||||
|
BLOCK OCTANT-12347
|
||||||
|
BLOCK OCTANT-157
|
||||||
|
BLOCK OCTANT-257
|
||||||
|
BLOCK OCTANT-1257
|
||||||
|
BLOCK OCTANT-357
|
||||||
|
BLOCK OCTANT-2357
|
||||||
|
BLOCK OCTANT-12357
|
||||||
|
BLOCK OCTANT-457
|
||||||
|
BLOCK OCTANT-1457
|
||||||
|
BLOCK OCTANT-12457
|
||||||
|
BLOCK OCTANT-3457
|
||||||
|
BLOCK OCTANT-13457
|
||||||
|
BLOCK OCTANT-23457
|
||||||
|
BLOCK OCTANT-67
|
||||||
|
BLOCK OCTANT-167
|
||||||
|
BLOCK OCTANT-267
|
||||||
|
BLOCK OCTANT-1267
|
||||||
|
BLOCK OCTANT-367
|
||||||
|
BLOCK OCTANT-1367
|
||||||
|
BLOCK OCTANT-2367
|
||||||
|
BLOCK OCTANT-12367
|
||||||
|
BLOCK OCTANT-467
|
||||||
|
BLOCK OCTANT-1467
|
||||||
|
BLOCK OCTANT-2467
|
||||||
|
BLOCK OCTANT-12467
|
||||||
|
BLOCK OCTANT-3467
|
||||||
|
BLOCK OCTANT-13467
|
||||||
|
BLOCK OCTANT-23467
|
||||||
|
BLOCK OCTANT-123467
|
||||||
|
BLOCK OCTANT-567
|
||||||
|
BLOCK OCTANT-1567
|
||||||
|
BLOCK OCTANT-2567
|
||||||
|
BLOCK OCTANT-12567
|
||||||
|
BLOCK OCTANT-3567
|
||||||
|
BLOCK OCTANT-13567
|
||||||
|
BLOCK OCTANT-23567
|
||||||
|
BLOCK OCTANT-123567
|
||||||
|
BLOCK OCTANT-4567
|
||||||
|
BLOCK OCTANT-14567
|
||||||
|
BLOCK OCTANT-24567
|
||||||
|
BLOCK OCTANT-124567
|
||||||
|
BLOCK OCTANT-34567
|
||||||
|
BLOCK OCTANT-134567
|
||||||
|
BLOCK OCTANT-234567
|
||||||
|
BLOCK OCTANT-1234567
|
||||||
|
BLOCK OCTANT-18
|
||||||
|
BLOCK OCTANT-28
|
||||||
|
BLOCK OCTANT-128
|
||||||
|
BLOCK OCTANT-38
|
||||||
|
BLOCK OCTANT-138
|
||||||
|
BLOCK OCTANT-238
|
||||||
|
BLOCK OCTANT-1238
|
||||||
|
BLOCK OCTANT-48
|
||||||
|
BLOCK OCTANT-148
|
||||||
|
BLOCK OCTANT-248
|
||||||
|
BLOCK OCTANT-1248
|
||||||
|
BLOCK OCTANT-348
|
||||||
|
BLOCK OCTANT-1348
|
||||||
|
BLOCK OCTANT-2348
|
||||||
|
BLOCK OCTANT-12348
|
||||||
|
BLOCK OCTANT-58
|
||||||
|
BLOCK OCTANT-158
|
||||||
|
BLOCK OCTANT-258
|
||||||
|
BLOCK OCTANT-1258
|
||||||
|
BLOCK OCTANT-358
|
||||||
|
BLOCK OCTANT-1358
|
||||||
|
BLOCK OCTANT-2358
|
||||||
|
BLOCK OCTANT-12358
|
||||||
|
BLOCK OCTANT-458
|
||||||
|
BLOCK OCTANT-1458
|
||||||
|
BLOCK OCTANT-2458
|
||||||
|
BLOCK OCTANT-12458
|
||||||
|
BLOCK OCTANT-3458
|
||||||
|
BLOCK OCTANT-13458
|
||||||
|
BLOCK OCTANT-23458
|
||||||
|
BLOCK OCTANT-123458
|
||||||
|
BLOCK OCTANT-168
|
||||||
|
BLOCK OCTANT-268
|
||||||
|
BLOCK OCTANT-1268
|
||||||
|
BLOCK OCTANT-368
|
||||||
|
BLOCK OCTANT-2368
|
||||||
|
BLOCK OCTANT-12368
|
||||||
|
BLOCK OCTANT-468
|
||||||
|
BLOCK OCTANT-1468
|
||||||
|
BLOCK OCTANT-12468
|
||||||
|
BLOCK OCTANT-3468
|
||||||
|
BLOCK OCTANT-13468
|
||||||
|
BLOCK OCTANT-23468
|
||||||
|
BLOCK OCTANT-568
|
||||||
|
BLOCK OCTANT-1568
|
||||||
|
BLOCK OCTANT-2568
|
||||||
|
BLOCK OCTANT-12568
|
||||||
|
BLOCK OCTANT-3568
|
||||||
|
BLOCK OCTANT-13568
|
||||||
|
BLOCK OCTANT-23568
|
||||||
|
BLOCK OCTANT-123568
|
||||||
|
BLOCK OCTANT-4568
|
||||||
|
BLOCK OCTANT-14568
|
||||||
|
BLOCK OCTANT-24568
|
||||||
|
BLOCK OCTANT-124568
|
||||||
|
BLOCK OCTANT-34568
|
||||||
|
BLOCK OCTANT-134568
|
||||||
|
BLOCK OCTANT-234568
|
||||||
|
BLOCK OCTANT-1234568
|
||||||
|
BLOCK OCTANT-178
|
||||||
|
BLOCK OCTANT-278
|
||||||
|
BLOCK OCTANT-1278
|
||||||
|
BLOCK OCTANT-378
|
||||||
|
BLOCK OCTANT-1378
|
||||||
|
BLOCK OCTANT-2378
|
||||||
|
BLOCK OCTANT-12378
|
||||||
|
BLOCK OCTANT-478
|
||||||
|
BLOCK OCTANT-1478
|
||||||
|
BLOCK OCTANT-2478
|
||||||
|
BLOCK OCTANT-12478
|
||||||
|
BLOCK OCTANT-3478
|
||||||
|
BLOCK OCTANT-13478
|
||||||
|
BLOCK OCTANT-23478
|
||||||
|
BLOCK OCTANT-123478
|
||||||
|
BLOCK OCTANT-578
|
||||||
|
BLOCK OCTANT-1578
|
||||||
|
BLOCK OCTANT-2578
|
||||||
|
BLOCK OCTANT-12578
|
||||||
|
BLOCK OCTANT-3578
|
||||||
|
BLOCK OCTANT-13578
|
||||||
|
BLOCK OCTANT-23578
|
||||||
|
BLOCK OCTANT-123578
|
||||||
|
BLOCK OCTANT-4578
|
||||||
|
BLOCK OCTANT-14578
|
||||||
|
BLOCK OCTANT-24578
|
||||||
|
BLOCK OCTANT-124578
|
||||||
|
BLOCK OCTANT-34578
|
||||||
|
BLOCK OCTANT-134578
|
||||||
|
BLOCK OCTANT-234578
|
||||||
|
BLOCK OCTANT-1234578
|
||||||
|
BLOCK OCTANT-678
|
||||||
|
BLOCK OCTANT-1678
|
||||||
|
BLOCK OCTANT-2678
|
||||||
|
BLOCK OCTANT-12678
|
||||||
|
BLOCK OCTANT-3678
|
||||||
|
BLOCK OCTANT-13678
|
||||||
|
BLOCK OCTANT-23678
|
||||||
|
BLOCK OCTANT-123678
|
||||||
|
BLOCK OCTANT-4678
|
||||||
|
BLOCK OCTANT-14678
|
||||||
|
BLOCK OCTANT-24678
|
||||||
|
BLOCK OCTANT-124678
|
||||||
|
BLOCK OCTANT-34678
|
||||||
|
BLOCK OCTANT-134678
|
||||||
|
BLOCK OCTANT-234678
|
||||||
|
BLOCK OCTANT-1234678
|
||||||
|
BLOCK OCTANT-15678
|
||||||
|
BLOCK OCTANT-25678
|
||||||
|
BLOCK OCTANT-125678
|
||||||
|
BLOCK OCTANT-35678
|
||||||
|
BLOCK OCTANT-235678
|
||||||
|
BLOCK OCTANT-1235678
|
||||||
|
BLOCK OCTANT-45678
|
||||||
|
BLOCK OCTANT-145678
|
||||||
|
BLOCK OCTANT-1245678
|
||||||
|
BLOCK OCTANT-1345678
|
||||||
|
BLOCK OCTANT-2345678
|
BIN
src/font/sprite/testdata/Box.ppm
vendored
BIN
src/font/sprite/testdata/Box.ppm
vendored
Binary file not shown.
Reference in New Issue
Block a user