curly underlines

This commit is contained in:
Mitchell Hashimoto
2022-11-27 16:11:15 -08:00
parent fee681ac78
commit bfc657395a
5 changed files with 58 additions and 1 deletions

View File

@ -18,6 +18,7 @@ pub const Sprite = enum(u32) {
underline_double = start + 1, underline_double = start + 1,
underline_dotted = start + 2, underline_dotted = start + 2,
underline_dashed = start + 3, underline_dashed = start + 3,
underline_curly = start + 4,
// Note: we don't currently put the box drawing glyphs in here because // Note: we don't currently put the box drawing glyphs in here because
// there are a LOT and I'm lazy. What I want to do is spend more time // there are a LOT and I'm lazy. What I want to do is spend more time

View File

@ -87,6 +87,7 @@ const Kind = enum {
.underline_double, .underline_double,
.underline_dotted, .underline_dotted,
.underline_dashed, .underline_dashed,
.underline_curly,
=> .underline, => .underline,
}, },

View File

@ -71,6 +71,7 @@ const Draw = struct {
.underline_double => self.drawDouble(canvas), .underline_double => self.drawDouble(canvas),
.underline_dotted => self.drawDotted(canvas), .underline_dotted => self.drawDotted(canvas),
.underline_dashed => self.drawDashed(canvas), .underline_dashed => self.drawDashed(canvas),
.underline_curly => self.drawCurly(canvas),
} }
} }
@ -130,6 +131,41 @@ const Draw = struct {
}, .on); }, .on);
} }
} }
/// Draw a curly underline. Thanks to Wez Furlong for providing
/// the basic math structure for this since I was lazy with the
/// geometry.
fn drawCurly(self: Draw, canvas: *font.sprite.Canvas) void {
// This is the lowest that the curl can go.
const y_max = self.height - 1;
// The full heightof the wave can be from the bottom to the
// underline position. We also calculate our starting y which is
// slightly below our descender since our wave will move about that.
const wave_height = @intToFloat(f64, y_max - self.pos);
const half_height = wave_height / 4;
const y = self.pos + @floatToInt(u32, half_height);
const x_factor = (2 * std.math.pi) / @intToFloat(f64, self.width);
var x: u32 = 0;
while (x < self.width) : (x += 1) {
const vertical = @floatToInt(
u32,
(-1 * half_height) * @sin(@intToFloat(f64, x) * x_factor) + half_height,
);
var row: u32 = 0;
while (row < self.thickness) : (row += 1) {
const y1 = @min(row + y + vertical, y_max);
canvas.rect(.{
.x = x,
.y = y1,
.width = 1,
.height = 1,
}, .on);
}
}
}
}; };
test "single" { test "single" {
@ -149,3 +185,21 @@ test "single" {
2, 2,
); );
} }
test "curly" {
const testing = std.testing;
const alloc = testing.allocator;
var atlas_greyscale = try Atlas.init(alloc, 512, .greyscale);
defer atlas_greyscale.deinit(alloc);
_ = try renderGlyph(
alloc,
&atlas_greyscale,
.underline_curly,
36,
18,
9,
2,
);
}

View File

@ -1011,7 +1011,7 @@ pub fn updateCell(
.double => .underline_double, .double => .underline_double,
.dotted => .underline_dotted, .dotted => .underline_dotted,
.dashed => .underline_dashed, .dashed => .underline_dashed,
else => .underline, .curly => .underline_curly,
}; };
const underline_glyph = try self.font_group.renderGlyph( const underline_glyph = try self.font_group.renderGlyph(

View File

@ -137,6 +137,7 @@ pub const Parser = struct {
0 => return Attribute{ .reset_underline = {} }, 0 => return Attribute{ .reset_underline = {} },
1 => return Attribute{ .underline = .single }, 1 => return Attribute{ .underline = .single },
2 => return Attribute{ .underline = .double }, 2 => return Attribute{ .underline = .double },
3 => return Attribute{ .underline = .curly },
4 => return Attribute{ .underline = .dotted }, 4 => return Attribute{ .underline = .dotted },
5 => return Attribute{ .underline = .dashed }, 5 => return Attribute{ .underline = .dashed },