font/sprite: update to z2d 0.12.1, use native path insetting
This change updates z2d to 0.12.1 and changes the sprite font path insetting functionality to use the new path offset abilities released in the update. In addition, there has been a slight change to the drawing of E0B5 and its respective reflection; we now add a 1-pixel horizontal line segment to each end to force them to be perpendicular. This is because offsetting pre-expands the curves and ultimately causes the end segments of the curve itself to have slight non-horizontal angles, which produce small artifacts at the ends without the forced horizontal ends.
@@ -30,8 +30,8 @@
|
||||
},
|
||||
.z2d = .{
|
||||
// vancluever/z2d
|
||||
.url = "https://deps.files.ghostty.org/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR.tar.gz",
|
||||
.hash = "z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR",
|
||||
.url = "https://github.com/vancluever/z2d/archive/7dbae85c81784dba9988320bf9543ed9a81350c8.tar.gz",
|
||||
.hash = "z2d-0.12.1-j5P_Hsw8EQAKyZTQICCQnAH2xYkLDW8k9uefbsYdfPZ-",
|
||||
.lazy = true,
|
||||
},
|
||||
.zig_objc = .{
|
||||
|
||||
6
build.zig.zon.json
generated
@@ -154,10 +154,10 @@
|
||||
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
|
||||
"hash": "sha256-nkzSCr6W5sTG7enDBXEIhgEm574uLD41UVR2wlC+HBM="
|
||||
},
|
||||
"z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR": {
|
||||
"z2d-0.12.1-j5P_Hsw8EQAKyZTQICCQnAH2xYkLDW8k9uefbsYdfPZ-": {
|
||||
"name": "z2d",
|
||||
"url": "https://deps.files.ghostty.org/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR.tar.gz",
|
||||
"hash": "sha256-/Yje2P+ro7IrPodQ26YKk7RsPSYj1Cqx6bdrmykXEKA="
|
||||
"url": "https://github.com/vancluever/z2d/archive/7dbae85c81784dba9988320bf9543ed9a81350c8.tar.gz",
|
||||
"hash": "sha256-Fjr1ORn0ozxU7QY09o2ZOZQHIJsXfVw0UCdZxTKmZJ0="
|
||||
},
|
||||
"zf-0.11.0-OIRy8X-RAAAwaRXHMYpj2uvBnuGTZWEE_3V7acqHQNtW": {
|
||||
"name": "zf",
|
||||
|
||||
6
build.zig.zon.nix
generated
@@ -377,11 +377,11 @@ in
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR";
|
||||
name = "z2d-0.12.1-j5P_Hsw8EQAKyZTQICCQnAH2xYkLDW8k9uefbsYdfPZ-";
|
||||
path = fetchZigArtifact {
|
||||
name = "z2d";
|
||||
url = "https://deps.files.ghostty.org/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR.tar.gz";
|
||||
hash = "sha256-/Yje2P+ro7IrPodQ26YKk7RsPSYj1Cqx6bdrmykXEKA=";
|
||||
url = "https://github.com/vancluever/z2d/archive/7dbae85c81784dba9988320bf9543ed9a81350c8.tar.gz";
|
||||
hash = "sha256-Fjr1ORn0ozxU7QY09o2ZOZQHIJsXfVw0UCdZxTKmZJ0=";
|
||||
unpack = true;
|
||||
};
|
||||
}
|
||||
|
||||
2
build.zig.zon.txt
generated
@@ -30,9 +30,9 @@ https://deps.files.ghostty.org/wayland-0.6.0-lQa1kqz8AQADQmdNJsNhLoNHcnEGEUjrOaP
|
||||
https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz
|
||||
https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz
|
||||
https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz
|
||||
https://deps.files.ghostty.org/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR.tar.gz
|
||||
https://deps.files.ghostty.org/zf-c35c421f84895193246db06c40683c1a30e616ef.tar.gz
|
||||
https://deps.files.ghostty.org/zig_js-3c23860e47fdcdc5af805efb7fd0bdac5fd3e9bc.tar.gz
|
||||
https://deps.files.ghostty.org/zig_objc-c8de82ff80281215ad92900866dab7103a8efa8b.tar.gz
|
||||
https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz
|
||||
https://github.com/vancluever/arocc/archive/ecbc5c799574e0da2758a961b12efa586007f03c.tar.gz
|
||||
https://github.com/vancluever/z2d/archive/7dbae85c81784dba9988320bf9543ed9a81350c8.tar.gz
|
||||
|
||||
@@ -187,9 +187,9 @@
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://deps.files.ghostty.org/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR.tar.gz",
|
||||
"dest": "vendor/p/z2d-0.11.0-j5P_HtLzDwBGyQt49DrT0v4BuVqI_SRs6CXsuj7eBVhR",
|
||||
"sha256": "d48b117307f767ca379bf31bd171880e66dcafb89eca4a8f923222619992fcb4"
|
||||
"url": "https://github.com/vancluever/z2d/archive/7dbae85c81784dba9988320bf9543ed9a81350c8.tar.gz",
|
||||
"dest": "vendor/p/z2d-0.12.1-j5P_Hsw8EQAKyZTQICCQnAH2xYkLDW8k9uefbsYdfPZ-",
|
||||
"sha256": "e55c9d0b156edaddfea32fb1c0e3597e1b6306b9a4ec1888e2f8008c598bced8"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
|
||||
@@ -375,85 +375,17 @@ pub const Canvas = struct {
|
||||
);
|
||||
}
|
||||
|
||||
/// Do an inner stroke on a z2d path, right now this involves a pretty
|
||||
/// heavy workaround that uses two extra surfaces; in the future, z2d
|
||||
/// should add inner and outer strokes natively.
|
||||
/// Do an inner stroke using a 1/2 stroke width inset of the supplied
|
||||
/// `path`.
|
||||
pub fn innerStrokePath(
|
||||
self: *Canvas,
|
||||
path: z2d.Path,
|
||||
opts: z2d.painter.StrokeOptions,
|
||||
color: Color,
|
||||
) (z2d.painter.StrokeError || z2d.painter.FillError)!void {
|
||||
// On one surface we fill the shape, this will be a mask we
|
||||
// multiply with the double-width stroke so that only the
|
||||
// part inside is used.
|
||||
var fill_sfc: z2d.Surface = try .init(
|
||||
.image_surface_alpha8,
|
||||
self.alloc,
|
||||
self.sfc.getWidth(),
|
||||
self.sfc.getHeight(),
|
||||
);
|
||||
defer fill_sfc.deinit(self.alloc);
|
||||
|
||||
// On the other we'll do the double width stroke.
|
||||
var stroke_sfc: z2d.Surface = try .init(
|
||||
.image_surface_alpha8,
|
||||
self.alloc,
|
||||
self.sfc.getWidth(),
|
||||
self.sfc.getHeight(),
|
||||
);
|
||||
defer stroke_sfc.deinit(self.alloc);
|
||||
|
||||
// Make a closed version of the path for our fill, so
|
||||
// that we can support open paths for inner stroke.
|
||||
var closed_path = path;
|
||||
closed_path.nodes = try path.nodes.clone(self.alloc);
|
||||
defer closed_path.deinit(self.alloc);
|
||||
try closed_path.close(self.alloc);
|
||||
|
||||
// Fill the shape in white to the fill surface, we use
|
||||
// white because this is a mask that we'll multiply with
|
||||
// the stroke, we want everything inside to be the stroke
|
||||
// color.
|
||||
try z2d.painter.fill(
|
||||
self.alloc,
|
||||
&fill_sfc,
|
||||
&.{ .opaque_pattern = .{
|
||||
.pixel = .{ .alpha8 = .{ .a = 255 } },
|
||||
} },
|
||||
closed_path.nodes.items,
|
||||
.{},
|
||||
);
|
||||
|
||||
// Stroke the shape with double the desired width.
|
||||
var mut_opts = opts;
|
||||
mut_opts.line_width *= 2;
|
||||
try z2d.painter.stroke(
|
||||
self.alloc,
|
||||
&stroke_sfc,
|
||||
&.{ .opaque_pattern = .{
|
||||
.pixel = .{ .alpha8 = .{ .a = @intFromEnum(color) } },
|
||||
} },
|
||||
path.nodes.items,
|
||||
mut_opts,
|
||||
);
|
||||
|
||||
// We multiply the stroke sfc on to the fill surface.
|
||||
// The z2d composite operation doesn't seem to work for
|
||||
// this with alpha8 surfaces, so we have to do it manually.
|
||||
for (
|
||||
std.mem.sliceAsBytes(fill_sfc.image_surface_alpha8.buf),
|
||||
std.mem.sliceAsBytes(stroke_sfc.image_surface_alpha8.buf),
|
||||
) |*d, s| {
|
||||
d.* = @intFromFloat(@round(
|
||||
255.0 *
|
||||
(@as(f64, @floatFromInt(s)) / 255.0) *
|
||||
(@as(f64, @floatFromInt(d.*)) / 255.0),
|
||||
));
|
||||
}
|
||||
|
||||
// Then we composite the result on to the main surface.
|
||||
self.sfc.composite(&fill_sfc, .src_over, 0, 0, .{});
|
||||
) (z2d.Path.OffsetError || z2d.painter.StrokeError)!void {
|
||||
var inset_path = try path.offset(self.alloc, -opts.line_width / 2.0);
|
||||
defer inset_path.deinit(self.alloc);
|
||||
return self.strokePath(inset_path, opts, color);
|
||||
}
|
||||
|
||||
/// Fill a z2d path.
|
||||
|
||||
@@ -292,8 +292,13 @@ pub fn drawE0B5(
|
||||
|
||||
const radius: f64 = @min(float_width, float_height / 2);
|
||||
|
||||
var path = canvas.staticPath(4);
|
||||
// Note on the first/final lineTo moves: this is to enforce horizontal
|
||||
// lines on both ends. This ensures that when the path is offset and
|
||||
// stroked, the ends are butt-capped entirely perpendicularly; curveTo
|
||||
// lerping would produce very slight slopes otherwise.
|
||||
var path = canvas.staticPath(6);
|
||||
path.moveTo(0, 0);
|
||||
path.lineTo(1, 0);
|
||||
path.curveTo(
|
||||
radius * c,
|
||||
0,
|
||||
@@ -308,9 +313,10 @@ pub fn drawE0B5(
|
||||
float_height - radius + radius * c,
|
||||
radius * c,
|
||||
float_height,
|
||||
0,
|
||||
1,
|
||||
float_height,
|
||||
);
|
||||
path.lineTo(0, float_height);
|
||||
|
||||
try canvas.innerStrokePath(path.wrapped_path, .{
|
||||
.line_width = @floatFromInt(metrics.box_thickness),
|
||||
|
||||
BIN
src/font/sprite/testdata/U+2500...U+25FF-11x21+2.png
vendored
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
src/font/sprite/testdata/U+2500...U+25FF-9x17+1.png
vendored
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
src/font/sprite/testdata/U+E000...U+E0FF-11x21+2.png
vendored
|
Before Width: | Height: | Size: 1009 B After Width: | Height: | Size: 1.0 KiB |
BIN
src/font/sprite/testdata/U+E000...U+E0FF-12x24+3.png
vendored
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
src/font/sprite/testdata/U+E000...U+E0FF-18x36+4.png
vendored
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
src/font/sprite/testdata/U+E000...U+E0FF-9x17+1.png
vendored
|
Before Width: | Height: | Size: 832 B After Width: | Height: | Size: 834 B |