diff --git a/src/font/sprite/Box.zig b/src/font/sprite/Box.zig index f3942b83d..dd02f701b 100644 --- a/src/font/sprite/Box.zig +++ b/src/font/sprite/Box.zig @@ -2488,10 +2488,10 @@ fn draw_sextant(self: Box, canvas: *font.sprite.Canvas, cp: u32) void { if (sex.tl) self.rect(canvas, 0, 0, x_halfs[0], y_thirds[0]); if (sex.tr) self.rect(canvas, x_halfs[1], 0, self.metrics.cell_width, y_thirds[0]); - if (sex.ml) self.rect(canvas, 0, y_thirds[0], x_halfs[0], y_thirds[1]); - if (sex.mr) self.rect(canvas, x_halfs[1], y_thirds[0], self.metrics.cell_width, y_thirds[1]); - if (sex.bl) self.rect(canvas, 0, y_thirds[1], x_halfs[0], self.metrics.cell_height); - if (sex.br) self.rect(canvas, x_halfs[1], y_thirds[1], self.metrics.cell_width, self.metrics.cell_height); + if (sex.ml) self.rect(canvas, 0, y_thirds[1], x_halfs[0], y_thirds[2]); + if (sex.mr) self.rect(canvas, x_halfs[1], y_thirds[1], self.metrics.cell_width, y_thirds[2]); + if (sex.bl) self.rect(canvas, 0, y_thirds[3], x_halfs[0], self.metrics.cell_height); + if (sex.br) self.rect(canvas, x_halfs[1], y_thirds[3], self.metrics.cell_width, self.metrics.cell_height); } fn draw_octant(self: Box, canvas: *font.sprite.Canvas, cp: u32) void { @@ -2545,42 +2545,58 @@ fn draw_octant(self: Box, canvas: *font.sprite.Canvas, cp: u32) void { 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); + if (oct.@"3") self.rect(canvas, 0, y_quads[1], x_halfs[0], y_quads[2]); + if (oct.@"4") self.rect(canvas, x_halfs[1], y_quads[1], self.metrics.cell_width, y_quads[2]); + if (oct.@"5") self.rect(canvas, 0, y_quads[3], x_halfs[0], y_quads[4]); + if (oct.@"6") self.rect(canvas, x_halfs[1], y_quads[3], self.metrics.cell_width, y_quads[4]); + if (oct.@"7") self.rect(canvas, 0, y_quads[5], x_halfs[0], self.metrics.cell_height); + if (oct.@"8") self.rect(canvas, x_halfs[1], y_quads[5], self.metrics.cell_width, self.metrics.cell_height); } +/// xHalfs[0] should be used as the right edge of a left-aligned half. +/// xHalfs[1] should be used as the left edge of a right-aligned half. fn xHalfs(self: Box) [2]u32 { + const float_width: f64 = @floatFromInt(self.metrics.cell_width); + const half_width: u32 = @intFromFloat(@round(0.5 * float_width)); + return .{ half_width, self.metrics.cell_width - half_width }; +} + +/// Use these values as such: +/// yThirds[0] bottom edge of the first third. +/// yThirds[1] top edge of the second third. +/// yThirds[2] bottom edge of the second third. +/// yThirds[3] top edge of the final third. +fn yThirds(self: Box) [4]u32 { + const float_height: f64 = @floatFromInt(self.metrics.cell_height); + const one_third_height: u32 = @intFromFloat(@round(one_third * float_height)); + const two_thirds_height: u32 = @intFromFloat(@round(two_thirds * float_height)); return .{ - @as(u32, @intFromFloat(@round(@as(f64, @floatFromInt(self.metrics.cell_width)) / 2))), - @as(u32, @intFromFloat(@as(f64, @floatFromInt(self.metrics.cell_width)) / 2)), + one_third_height, + self.metrics.cell_height - two_thirds_height, + two_thirds_height, + self.metrics.cell_height - one_third_height, }; } -fn yThirds(self: Box) [2]u32 { - return switch (@mod(self.metrics.cell_height, 3)) { - 0 => .{ self.metrics.cell_height / 3, 2 * self.metrics.cell_height / 3 }, - 1 => .{ self.metrics.cell_height / 3, 2 * self.metrics.cell_height / 3 + 1 }, - 2 => .{ self.metrics.cell_height / 3 + 1, 2 * self.metrics.cell_height / 3 }, - else => unreachable, - }; -} - -// 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, +/// Use these values as such: +/// yQuads[0] bottom edge of first quarter. +/// yQuads[1] top edge of second quarter. +/// yQuads[2] bottom edge of second quarter. +/// yQuads[3] top edge of third quarter. +/// yQuads[4] bottom edge of third quarter +/// yQuads[5] top edge of fourth quarter. +fn yQuads(self: Box) [6]u32 { + const float_height: f64 = @floatFromInt(self.metrics.cell_height); + const quarter_height: u32 = @intFromFloat(@round(0.25 * float_height)); + const half_height: u32 = @intFromFloat(@round(0.50 * float_height)); + const three_quarters_height: u32 = @intFromFloat(@round(0.75 * float_height)); + return .{ + quarter_height, + self.metrics.cell_height - three_quarters_height, + half_height, + self.metrics.cell_height - half_height, + three_quarters_height, + self.metrics.cell_height - quarter_height, }; } @@ -2591,8 +2607,12 @@ fn draw_smooth_mosaic( ) !void { const y_thirds = self.yThirds(); const top: f64 = 0.0; - const upper: f64 = @floatFromInt(y_thirds[0]); - const lower: f64 = @floatFromInt(y_thirds[1]); + // We average the edge positions for the y_thirds boundaries here + // rather than having to deal with varying alignments depending on + // the surrounding pieces. The most this will be off by is half of + // a pixel, so hopefully it's not noticeable. + const upper: f64 = 0.5 * (@as(f64, @floatFromInt(y_thirds[0])) + @as(f64, @floatFromInt(y_thirds[1]))); + const lower: f64 = 0.5 * (@as(f64, @floatFromInt(y_thirds[2])) + @as(f64, @floatFromInt(y_thirds[3]))); const bottom: f64 = @floatFromInt(self.metrics.cell_height); const left: f64 = 0.0; const center: f64 = @round(@as(f64, @floatFromInt(self.metrics.cell_width)) / 2); diff --git a/src/font/sprite/testdata/Box.ppm b/src/font/sprite/testdata/Box.ppm index 0feb3ebe4..d5a6cc729 100644 Binary files a/src/font/sprite/testdata/Box.ppm and b/src/font/sprite/testdata/Box.ppm differ