mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +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
|
||||
const one_eighth: f64 = 0.125;
|
||||
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),
|
||||
|
||||
octant_min...octant_max => self.draw_octant(canvas, cp),
|
||||
|
||||
// '🬼'
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
return .{
|
||||
@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(
|
||||
self: Box,
|
||||
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;
|
||||
while (cp <= 0x1cc2f) : (cp += 1) {
|
||||
@ -3077,6 +3157,19 @@ fn testRenderAll(self: Box, alloc: Allocator, atlas: *font.Atlas) !void {
|
||||
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" {
|
||||
|
@ -236,6 +236,8 @@ const Kind = enum {
|
||||
// (Geometric Shapes)
|
||||
//
|
||||
0x1FBCE...0x1FBEF,
|
||||
// (Octants)
|
||||
0x1CD00...0x1CDE5,
|
||||
=> .box,
|
||||
|
||||
// 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