Fix z2d StaticPath usage (#3084)

There was an accidental use of `undefined` which I believe is the source
of crashes people are experiencing when drawing Powerline chevrons
(#3083). I've resolved this by using the slice from the path's internal
`ArrayList` instead of the backing array (`z2d` should probably
introduce a `getNodes()` method or similar to `StaticPath`), and also
annotated all `StaticPath` uses counting the maximum number of nodes
that may be required.

(**Edit**: confirmed, fixes #3083)
This commit is contained in:
Mitchell Hashimoto
2024-12-23 06:50:25 -08:00
committed by GitHub
3 changed files with 46 additions and 51 deletions

View File

@ -2515,19 +2515,19 @@ fn draw_smooth_mosaic(
const right: f64 = @floatFromInt(self.metrics.cell_width);
var path: z2d.StaticPath(12) = .{};
path.init();
path.init(); // nodes.len = 0
if (mosaic.tl) path.lineTo(left, top);
if (mosaic.ul) path.lineTo(left, upper);
if (mosaic.ll) path.lineTo(left, lower);
if (mosaic.bl) path.lineTo(left, bottom);
if (mosaic.bc) path.lineTo(center, bottom);
if (mosaic.br) path.lineTo(right, bottom);
if (mosaic.lr) path.lineTo(right, lower);
if (mosaic.ur) path.lineTo(right, upper);
if (mosaic.tr) path.lineTo(right, top);
if (mosaic.tc) path.lineTo(center, top);
path.close();
if (mosaic.tl) path.lineTo(left, top); // +1, nodes.len = 1
if (mosaic.ul) path.lineTo(left, upper); // +1, nodes.len = 2
if (mosaic.ll) path.lineTo(left, lower); // +1, nodes.len = 3
if (mosaic.bl) path.lineTo(left, bottom); // +1, nodes.len = 4
if (mosaic.bc) path.lineTo(center, bottom); // +1, nodes.len = 5
if (mosaic.br) path.lineTo(right, bottom); // +1, nodes.len = 6
if (mosaic.lr) path.lineTo(right, lower); // +1, nodes.len = 7
if (mosaic.ur) path.lineTo(right, upper); // +1, nodes.len = 8
if (mosaic.tr) path.lineTo(right, top); // +1, nodes.len = 9
if (mosaic.tc) path.lineTo(center, top); // +1, nodes.len = 10
path.close(); // +2, nodes.len = 12
try z2d.painter.fill(
canvas.alloc,
@ -2535,7 +2535,7 @@ fn draw_smooth_mosaic(
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(Shade.on) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{},
);
}
@ -2560,12 +2560,12 @@ fn draw_edge_triangle(
};
var path: z2d.StaticPath(5) = .{};
path.init();
path.init(); // nodes.len = 0
path.moveTo(center, middle);
path.lineTo(x0, y0);
path.lineTo(x1, y1);
path.close();
path.moveTo(center, middle); // +1, nodes.len = 1
path.lineTo(x0, y0); // +1, nodes.len = 2
path.lineTo(x1, y1); // +1, nodes.len = 3
path.close(); // +2, nodes.len = 5
try z2d.painter.fill(
canvas.alloc,
@ -2573,7 +2573,7 @@ fn draw_edge_triangle(
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(Shade.on) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{},
);
}

View File

@ -123,7 +123,6 @@ fn draw_chevron(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !void {
var p3_x: u32 = 0;
var p3_y: u32 = 0;
switch (cp) {
0xE0B1 => {
p1_x = 0;
@ -143,17 +142,13 @@ fn draw_chevron(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !void {
},
else => unreachable,
}
try canvas.triangle_outline(.{
.p0 = .{ .x = @floatFromInt(p1_x), .y = @floatFromInt(p1_y) },
.p1 = .{ .x = @floatFromInt(p2_x), .y = @floatFromInt(p2_y) },
.p2 = .{ .x = @floatFromInt(p3_x), .y = @floatFromInt(p3_y) },
},
@floatFromInt(Thickness.light.height(self.thickness)),
.on);
}, @floatFromInt(Thickness.light.height(self.thickness)), .on);
}
fn draw_wedge_triangle(self: Powerline, canvas: *font.sprite.Canvas, cp: u32) !void {

View File

@ -184,13 +184,13 @@ pub const Canvas = struct {
/// Draw and fill a quad.
pub fn quad(self: *Canvas, q: Quad(f64), color: Color) !void {
var path: z2d.StaticPath(6) = .{};
path.init();
path.init(); // nodes.len = 0
path.moveTo(q.p0.x, q.p0.y);
path.lineTo(q.p1.x, q.p1.y);
path.lineTo(q.p2.x, q.p2.y);
path.lineTo(q.p3.x, q.p3.y);
path.close();
path.moveTo(q.p0.x, q.p0.y); // +1, nodes.len = 1
path.lineTo(q.p1.x, q.p1.y); // +1, nodes.len = 2
path.lineTo(q.p2.x, q.p2.y); // +1, nodes.len = 3
path.lineTo(q.p3.x, q.p3.y); // +1, nodes.len = 4
path.close(); // +2, nodes.len = 6
try z2d.painter.fill(
self.alloc,
@ -198,7 +198,7 @@ pub const Canvas = struct {
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{},
);
}
@ -206,12 +206,12 @@ pub const Canvas = struct {
/// Draw and fill a triangle.
pub fn triangle(self: *Canvas, t: Triangle(f64), color: Color) !void {
var path: z2d.StaticPath(5) = .{};
path.init();
path.init(); // nodes.len = 0
path.moveTo(t.p0.x, t.p0.y);
path.lineTo(t.p1.x, t.p1.y);
path.lineTo(t.p2.x, t.p2.y);
path.close();
path.moveTo(t.p0.x, t.p0.y); // +1, nodes.len = 1
path.lineTo(t.p1.x, t.p1.y); // +1, nodes.len = 2
path.lineTo(t.p2.x, t.p2.y); // +1, nodes.len = 3
path.close(); // +2, nodes.len = 5
try z2d.painter.fill(
self.alloc,
@ -219,18 +219,18 @@ pub const Canvas = struct {
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{},
);
}
pub fn triangle_outline(self: *Canvas, t: Triangle(f64), thickness: f64, color: Color) !void {
var path: z2d.StaticPath(5) = .{};
path.init();
var path: z2d.StaticPath(3) = .{};
path.init(); // nodes.len = 0
path.moveTo(t.p0.x, t.p0.y);
path.lineTo(t.p1.x, t.p1.y);
path.lineTo(t.p2.x, t.p2.y);
path.moveTo(t.p0.x, t.p0.y); // +1, nodes.len = 1
path.lineTo(t.p1.x, t.p1.y); // +1, nodes.len = 2
path.lineTo(t.p2.x, t.p2.y); // +1, nodes.len = 3
try z2d.painter.stroke(
self.alloc,
@ -238,7 +238,7 @@ pub const Canvas = struct {
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{
.line_cap_mode = .round,
.line_width = thickness,
@ -248,11 +248,11 @@ pub const Canvas = struct {
/// Stroke a line.
pub fn line(self: *Canvas, l: Line(f64), thickness: f64, color: Color) !void {
var path: z2d.StaticPath(3) = .{};
path.init();
var path: z2d.StaticPath(2) = .{};
path.init(); // nodes.len = 0
path.moveTo(l.p0.x, l.p0.y);
path.lineTo(l.p1.x, l.p1.y);
path.moveTo(l.p0.x, l.p0.y); // +1, nodes.len = 1
path.lineTo(l.p1.x, l.p1.y); // +1, nodes.len = 2
try z2d.painter.stroke(
self.alloc,
@ -260,7 +260,7 @@ pub const Canvas = struct {
&.{ .opaque_pattern = .{
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
} },
&path.nodes,
path.wrapped_path.nodes.items,
.{
.line_cap_mode = .round,
.line_width = thickness,