chore: import upstream snapshot with attribution
Test / build-libghostty-vt (x86_64-windows-gnu) (push) Has been cancelled
Test / build-libghostty-vt-macos (aarch64-ios) (push) Has been cancelled
Test / build-libghostty-vt-macos (aarch64-macos) (push) Has been cancelled
Test / build-libghostty-vt-macos (x86_64-macos) (push) Has been cancelled
Test / build-nix (namespace-profile-ghostty-md-arm64) (push) Has been cancelled
Test / build-dist (push) Has been cancelled
Test / GTK x11=true wayland=true (push) Has been cancelled
Test / Build -Dsimd=false (push) Has been cancelled
Test / Build -Dsimd=true (push) Has been cancelled
Test / Build -Dsentry=false (push) Has been cancelled
Test / Build -Dsentry=true (push) Has been cancelled
Test / zig-fmt (push) Has been cancelled
Test / GitHub Actions Pins (push) Has been cancelled
Test / prettier (push) Has been cancelled
Test / swiftlint (push) Has been cancelled
Test / alejandra (push) Has been cancelled
Test / typos (push) Has been cancelled
Nix / Required Checks: Nix (push) Has been cancelled
Nix / check-zig-cache-hash (push) Has been cancelled
Test / skip (push) Has been cancelled
Test / Required Checks: Test (push) Has been cancelled
Test / build-bench (push) Has been cancelled
Test / list-examples (push) Has been cancelled
Test / Example ${{ matrix.dir }} (Windows) (push) Has been cancelled
Test / build-cmake (push) Has been cancelled
Test / test-lib-vt-pkgconfig (push) Has been cancelled
Test / build-flatpak (push) Has been cancelled
Test / build-snap (push) Has been cancelled
Test / build-libghostty-vt (aarch64-linux) (push) Has been cancelled
Test / build-libghostty-vt (aarch64-macos) (push) Has been cancelled
Test / build-libghostty-vt (wasm32-freestanding) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-linux) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-linux-musl) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-macos) (push) Has been cancelled
Test / build-libghostty-vt-android (aarch64-linux-android) (push) Has been cancelled
Test / build-libghostty-vt-android (arm-linux-androideabi) (push) Has been cancelled
Test / build-libghostty-vt-android (x86_64-linux-android) (push) Has been cancelled
Test / build-libghostty-vt-windows (push) Has been cancelled
Test / build-libghostty-windows-gnu (push) Has been cancelled
Test / build-linux (namespace-profile-ghostty-md) (push) Has been cancelled
Test / build-linux (namespace-profile-ghostty-md-arm64) (push) Has been cancelled
Test / build-linux-libghostty (push) Has been cancelled
Test / build-nix (namespace-profile-ghostty-md) (push) Has been cancelled
Test / build-dist-lib-vt (push) Has been cancelled
Test / trigger-snap (push) Has been cancelled
Test / trigger-flatpak (push) Has been cancelled
Test / build-macos (push) Has been cancelled
Test / build-macos-freetype (push) Has been cancelled
Test / test (push) Has been cancelled
Test / test-lib-vt (push) Has been cancelled
Test / GTK x11=false wayland=false (push) Has been cancelled
Test / GTK x11=true wayland=false (push) Has been cancelled
Test / GTK x11=false wayland=true (push) Has been cancelled
Test / test-macos (push) Has been cancelled
Test / test-windows (push) Has been cancelled
Test / Build -Di18n=false (push) Has been cancelled
Test / Build -Di18n=true (push) Has been cancelled
Test / Build test/fuzz-libghostty (push) Has been cancelled
Test / shellcheck (push) Has been cancelled
Test / translations (push) Has been cancelled
Test / blueprint-compiler (push) Has been cancelled
Test / Test pkg/wuffs (push) Has been cancelled
Test / Test build on Debian 13 (push) Has been cancelled
Test / valgrind (push) Has been cancelled
Test / Example ${{ matrix.dir }} (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:02:48 +08:00
commit bd44b5aa08
5770 changed files with 506778 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
pub const c = @cImport({
for (defines) |d| @cDefine(d, "1");
@cInclude("wuffs-v0.4.c");
});
/// All the C macros defined so that the header matches the build.
pub const defines: []const []const u8 = &[_][]const u8{
"WUFFS_CONFIG__MODULES",
"WUFFS_CONFIG__MODULE__AUX__BASE",
"WUFFS_CONFIG__MODULE__AUX__IMAGE",
"WUFFS_CONFIG__MODULE__BASE",
"WUFFS_CONFIG__MODULE__ADLER32",
"WUFFS_CONFIG__MODULE__CRC32",
"WUFFS_CONFIG__MODULE__DEFLATE",
"WUFFS_CONFIG__MODULE__JPEG",
"WUFFS_CONFIG__MODULE__PNG",
"WUFFS_CONFIG__MODULE__ZLIB",
};
+13
View File
@@ -0,0 +1,13 @@
const std = @import("std");
const c = @import("c.zig").c;
pub const Error = std.mem.Allocator.Error || error{ WuffsError, Overflow };
pub fn check(log: anytype, status: *const c.struct_wuffs_base__status__struct) error{WuffsError}!void {
if (!c.wuffs_base__status__is_ok(status)) {
const e = c.wuffs_base__status__message(status);
log.warn("decode err={s}", .{e});
return error.WuffsError;
}
}
+151
View File
@@ -0,0 +1,151 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const c = @import("c.zig").c;
const Error = @import("error.zig").Error;
const check = @import("error.zig").check;
const ImageData = @import("main.zig").ImageData;
const maximum_image_size = @import("main.zig").maximum_image_size;
const mul = std.math.mul;
const log = std.log.scoped(.wuffs_jpeg);
/// Decode a JPEG image.
pub fn decode(alloc: Allocator, data: []const u8) Error!ImageData {
// Work around some weirdness in WUFFS/Zig, there are some structs that
// are defined as "extern" by the Zig compiler which means that Zig won't
// allocate them on the stack at compile time. WUFFS has functions for
// dynamically allocating these structs but they use the C malloc/free. This
// gets around that by using the Zig allocator to allocate enough memory for
// the struct and then casts it to the appropriate pointer.
const decoder_buf = try alloc.alloc(u8, c.sizeof__wuffs_jpeg__decoder());
defer alloc.free(decoder_buf);
const decoder: ?*c.wuffs_jpeg__decoder = @ptrCast(decoder_buf);
{
const status = c.wuffs_jpeg__decoder__initialize(
decoder,
c.sizeof__wuffs_jpeg__decoder(),
c.WUFFS_VERSION,
0,
);
try check(log, &status);
}
var source_buffer: c.wuffs_base__io_buffer = .{
.data = .{ .ptr = @ptrCast(@constCast(data.ptr)), .len = data.len },
.meta = .{
.wi = data.len,
.ri = 0,
.pos = 0,
.closed = true,
},
};
var image_config: c.wuffs_base__image_config = undefined;
{
const status = c.wuffs_jpeg__decoder__decode_image_config(
decoder,
&image_config,
&source_buffer,
);
try check(log, &status);
}
const width = c.wuffs_base__pixel_config__width(&image_config.pixcfg);
const height = c.wuffs_base__pixel_config__height(&image_config.pixcfg);
c.wuffs_base__pixel_config__set(
&image_config.pixcfg,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL,
c.WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
width,
height,
);
const size: usize = try mul(
usize,
try mul(usize, width, height),
@sizeOf(c.wuffs_base__color_u32_argb_premul),
);
if (size > maximum_image_size) {
log.warn("image size {d} is larger than the maximum allowed ({d})", .{ size, maximum_image_size });
return error.Overflow;
}
const destination = try alloc.alloc(
u8,
size,
);
errdefer alloc.free(destination);
// temporary buffer for intermediate processing of image
const work_buffer = try alloc.alloc(
u8,
// The type of this is a u64 on all systems but our allocator
// uses a usize which is a u32 on 32-bit systems.
std.math.cast(
usize,
c.wuffs_jpeg__decoder__workbuf_len(decoder).max_incl,
) orelse return error.OutOfMemory,
);
defer alloc.free(work_buffer);
const work_slice = c.wuffs_base__make_slice_u8(
work_buffer.ptr,
work_buffer.len,
);
var pixel_buffer: c.wuffs_base__pixel_buffer = undefined;
{
const status = c.wuffs_base__pixel_buffer__set_from_slice(
&pixel_buffer,
&image_config.pixcfg,
c.wuffs_base__make_slice_u8(destination.ptr, destination.len),
);
try check(log, &status);
}
{
const status = c.wuffs_jpeg__decoder__decode_frame(
decoder,
&pixel_buffer,
&source_buffer,
c.WUFFS_BASE__PIXEL_BLEND__SRC,
work_slice,
null,
);
try check(log, &status);
}
return .{
.width = width,
.height = height,
.data = destination,
};
}
test "jpeg_decode_000000" {
const data = try decode(std.testing.allocator, @embedFile("1x1#000000.jpg"));
defer std.testing.allocator.free(data.data);
try std.testing.expectEqual(1, data.width);
try std.testing.expectEqual(1, data.height);
try std.testing.expectEqualSlices(u8, &.{ 0, 0, 0, 255 }, data.data);
}
test "jpeg_decode_FFFFFF" {
const data = try decode(std.testing.allocator, @embedFile("1x1#FFFFFF.jpg"));
defer std.testing.allocator.free(data.data);
try std.testing.expectEqual(1, data.width);
try std.testing.expectEqual(1, data.height);
try std.testing.expectEqualSlices(u8, &.{ 255, 255, 255, 255 }, data.data);
}
test "jpeg: too big" {
const data = decode(std.testing.allocator, @embedFile("too_big.jpg"));
try std.testing.expectError(error.Overflow, data);
}
+20
View File
@@ -0,0 +1,20 @@
const std = @import("std");
pub const png = @import("png.zig");
pub const jpeg = @import("jpeg.zig");
pub const swizzle = @import("swizzle.zig");
pub const Error = @import("error.zig").Error;
/// The maximum image size, based on the 4G limit of Ghostty's
/// `image-storage-limit` config.
pub const maximum_image_size = 4 * 1024 * 1024 * 1024;
pub const ImageData = struct {
width: u32,
height: u32,
data: []u8,
};
test {
std.testing.refAllDeclsRecursive(@This());
}
+151
View File
@@ -0,0 +1,151 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const c = @import("c.zig").c;
const Error = @import("error.zig").Error;
const check = @import("error.zig").check;
const ImageData = @import("main.zig").ImageData;
const maximum_image_size = @import("main.zig").maximum_image_size;
const mul = std.math.mul;
const log = std.log.scoped(.wuffs_png);
/// Decode a PNG image.
pub fn decode(alloc: Allocator, data: []const u8) Error!ImageData {
// Work around some weirdness in WUFFS/Zig, there are some structs that
// are defined as "extern" by the Zig compiler which means that Zig won't
// allocate them on the stack at compile time. WUFFS has functions for
// dynamically allocating these structs but they use the C malloc/free. This
// gets around that by using the Zig allocator to allocate enough memory for
// the struct and then casts it to the appropriate pointer.
const decoder_buf = try alloc.alloc(u8, c.sizeof__wuffs_png__decoder());
defer alloc.free(decoder_buf);
const decoder: ?*c.wuffs_png__decoder = @ptrCast(decoder_buf);
{
const status = c.wuffs_png__decoder__initialize(
decoder,
c.sizeof__wuffs_png__decoder(),
c.WUFFS_VERSION,
0,
);
try check(log, &status);
}
var source_buffer: c.wuffs_base__io_buffer = .{
.data = .{ .ptr = @ptrCast(@constCast(data.ptr)), .len = data.len },
.meta = .{
.wi = data.len,
.ri = 0,
.pos = 0,
.closed = true,
},
};
var image_config: c.wuffs_base__image_config = undefined;
{
const status = c.wuffs_png__decoder__decode_image_config(
decoder,
&image_config,
&source_buffer,
);
try check(log, &status);
}
const width = c.wuffs_base__pixel_config__width(&image_config.pixcfg);
const height = c.wuffs_base__pixel_config__height(&image_config.pixcfg);
c.wuffs_base__pixel_config__set(
&image_config.pixcfg,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL,
c.WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
width,
height,
);
const size: usize = try mul(
usize,
try mul(usize, width, height),
@sizeOf(c.wuffs_base__color_u32_argb_premul),
);
if (size > maximum_image_size) {
log.warn("image size {d} is larger than the maximum allowed ({d})", .{ size, maximum_image_size });
return error.Overflow;
}
const destination = try alloc.alloc(
u8,
size,
);
errdefer alloc.free(destination);
// temporary buffer for intermediate processing of image
const work_buffer = try alloc.alloc(
u8,
// The type of this is a u64 on all systems but our allocator
// uses a usize which is a u32 on 32-bit systems.
std.math.cast(
usize,
c.wuffs_png__decoder__workbuf_len(decoder).max_incl,
) orelse return error.OutOfMemory,
);
defer alloc.free(work_buffer);
const work_slice = c.wuffs_base__make_slice_u8(
work_buffer.ptr,
work_buffer.len,
);
var pixel_buffer: c.wuffs_base__pixel_buffer = undefined;
{
const status = c.wuffs_base__pixel_buffer__set_from_slice(
&pixel_buffer,
&image_config.pixcfg,
c.wuffs_base__make_slice_u8(destination.ptr, destination.len),
);
try check(log, &status);
}
{
const status = c.wuffs_png__decoder__decode_frame(
decoder,
&pixel_buffer,
&source_buffer,
c.WUFFS_BASE__PIXEL_BLEND__SRC,
work_slice,
null,
);
try check(log, &status);
}
return .{
.width = width,
.height = height,
.data = destination,
};
}
test "png_decode_000000" {
const data = try decode(std.testing.allocator, @embedFile("1x1#000000.png"));
defer std.testing.allocator.free(data.data);
try std.testing.expectEqual(1, data.width);
try std.testing.expectEqual(1, data.height);
try std.testing.expectEqualSlices(u8, &.{ 0, 0, 0, 255 }, data.data);
}
test "png_decode_FFFFFF" {
const data = try decode(std.testing.allocator, @embedFile("1x1#FFFFFF.png"));
defer std.testing.allocator.free(data.data);
try std.testing.expectEqual(1, data.width);
try std.testing.expectEqual(1, data.height);
try std.testing.expectEqualSlices(u8, &.{ 255, 255, 255, 255 }, data.data);
}
test "png: too big" {
const data = decode(std.testing.allocator, @embedFile("too_big.png"));
try std.testing.expectError(error.Overflow, data);
}
+121
View File
@@ -0,0 +1,121 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const c = @import("c.zig").c;
const Error = @import("error.zig").Error;
const log = std.log.scoped(.wuffs_swizzler);
pub fn gToRgba(alloc: Allocator, src: []const u8) Error![]u8 {
return swizzle(
alloc,
src,
c.WUFFS_BASE__PIXEL_FORMAT__Y,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
);
}
pub fn gaToRgba(alloc: Allocator, src: []const u8) Error![]u8 {
return swizzle(
alloc,
src,
c.WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
);
}
pub fn rgbToRgba(alloc: Allocator, src: []const u8) Error![]u8 {
return swizzle(
alloc,
src,
c.WUFFS_BASE__PIXEL_FORMAT__RGB,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
);
}
pub fn bgrToRgba(alloc: Allocator, src: []const u8) Error![]u8 {
return swizzle(
alloc,
src,
c.WUFFS_BASE__PIXEL_FORMAT__BGR,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
);
}
pub fn bgraToRgba(alloc: Allocator, src: []const u8) Error![]u8 {
return swizzle(
alloc,
src,
c.WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
c.WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL,
);
}
fn swizzle(
alloc: Allocator,
src: []const u8,
comptime src_pixel_format: u32,
comptime dst_pixel_format: u32,
) Error![]u8 {
const src_slice = c.wuffs_base__make_slice_u8(
@constCast(src.ptr),
src.len,
);
const dst_fmt = c.wuffs_base__make_pixel_format(
dst_pixel_format,
);
assert(c.wuffs_base__pixel_format__is_direct(&dst_fmt));
assert(c.wuffs_base__pixel_format__is_interleaved(&dst_fmt));
assert(c.wuffs_base__pixel_format__bits_per_pixel(&dst_fmt) % 8 == 0);
const dst_size = c.wuffs_base__pixel_format__bits_per_pixel(&dst_fmt) / 8;
const src_fmt = c.wuffs_base__make_pixel_format(
src_pixel_format,
);
assert(c.wuffs_base__pixel_format__is_direct(&src_fmt));
assert(c.wuffs_base__pixel_format__is_interleaved(&src_fmt));
assert(c.wuffs_base__pixel_format__bits_per_pixel(&src_fmt) % 8 == 0);
const src_size = c.wuffs_base__pixel_format__bits_per_pixel(&src_fmt) / 8;
assert(src.len % src_size == 0);
const dst = try alloc.alloc(u8, src.len * dst_size / src_size);
errdefer alloc.free(dst);
const dst_slice = c.wuffs_base__make_slice_u8(
dst.ptr,
dst.len,
);
var swizzler: c.wuffs_base__pixel_swizzler = undefined;
{
const status = c.wuffs_base__pixel_swizzler__prepare(
&swizzler,
dst_fmt,
c.wuffs_base__empty_slice_u8(),
src_fmt,
c.wuffs_base__empty_slice_u8(),
c.WUFFS_BASE__PIXEL_BLEND__SRC,
);
if (!c.wuffs_base__status__is_ok(&status)) {
const e = c.wuffs_base__status__message(&status);
log.warn("{s}", .{e});
return error.WuffsError;
}
}
{
_ = c.wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
&swizzler,
dst_slice,
c.wuffs_base__empty_slice_u8(),
src_slice,
);
}
return dst;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 KiB