diff --git a/src/font/sprite/canvas.zig b/src/font/sprite/canvas.zig index 83d924008..e7072f56a 100644 --- a/src/font/sprite/canvas.zig +++ b/src/font/sprite/canvas.zig @@ -433,6 +433,10 @@ const PixmanImpl = struct { }, }; + assert(boxes[0].x1 >= 0); + assert(boxes[0].y1 >= 0); + assert(boxes[0].x2 <= @as(i32, @intCast(self.image.getWidth()))); + assert(boxes[0].y2 <= @as(i32, @intCast(self.image.getHeight()))); self.image.fillBoxes(.src, color.pixmanColor(), boxes) catch {}; } diff --git a/src/font/sprite/underline.zig b/src/font/sprite/underline.zig index 55a29d80c..064efc74f 100644 --- a/src/font/sprite/underline.zig +++ b/src/font/sprite/underline.zig @@ -80,13 +80,14 @@ const Draw = struct { // Ensure we never overflow out of bounds on the canvas const y_max = self.height -| 1; const bottom = @min(self.pos + self.thickness, y_max); - const y = @as(i32, @intCast(bottom - self.thickness)); + const y = bottom -| self.thickness; + const max_height = self.height - y; canvas.rect(.{ .x = 0, - .y = y, + .y = @intCast(y), .width = self.width, - .height = self.thickness, + .height = @min(self.thickness, max_height), }, .on); } @@ -224,6 +225,26 @@ test "single" { ); } +test "single large thickness" { + const testing = std.testing; + const alloc = testing.allocator; + + var atlas_greyscale = try font.Atlas.init(alloc, 512, .greyscale); + defer atlas_greyscale.deinit(alloc); + + // unrealistic thickness but used to cause a crash + // https://github.com/mitchellh/ghostty/pull/1548 + _ = try renderGlyph( + alloc, + &atlas_greyscale, + .underline, + 36, + 18, + 9, + 200, + ); +} + test "curly" { const testing = std.testing; const alloc = testing.allocator;