Skip to content

Commit

Permalink
Add jpg support
Browse files Browse the repository at this point in the history
  • Loading branch information
yunusey committed Jan 3, 2025
1 parent c09ffa1 commit 2b64e69
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 108 deletions.
201 changes: 94 additions & 107 deletions src/config/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3189,6 +3189,86 @@ fn expandPaths(self: *Config, base: []const u8) !void {
}
}

/// Expand a relative path to an absolute path. This function is used by
/// the RepeatablePath and SinglePath to expand the paths they store.
fn expandPath(
alloc: Allocator,
base: []const u8,
path: []const u8,
diags: *cli.DiagnosticList,
) ![]const u8 {
assert(std.fs.path.isAbsolute(base));
var dir = try std.fs.cwd().openDir(base, .{});
defer dir.close();

// If it is already absolute we can just return it
if (path.len == 0 or std.fs.path.isAbsolute(path)) return path;

// If it isn't absolute, we need to make it absolute relative
// to the base.
var buf: [std.fs.max_path_bytes]u8 = undefined;

// Check if the path starts with a tilde and expand it to the
// home directory on Linux/macOS. We explicitly look for "~/"
// because we don't support alternate users such as "~alice/"
if (std.mem.startsWith(u8, path, "~/")) expand: {
// Windows isn't supported yet
if (comptime builtin.os.tag == .windows) break :expand;

const expanded: []const u8 = internal_os.expandHome(
path,
&buf,
) catch |err| {
try diags.append(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"error expanding home directory for path {s}: {}",
.{ path, err },
),
});

// We can't expand this path so return an empty string
return "";
};

log.debug(
"expanding file path from home directory: path={s}",
.{expanded},
);

return expanded;
}

const abs = dir.realpath(path, &buf) catch |err| abs: {
if (err == error.FileNotFound) {
// The file doesn't exist. Try to resolve the relative path
// another way.
const resolved = try std.fs.path.resolve(alloc, &.{ base, path });
defer alloc.free(resolved);
@memcpy(buf[0..resolved.len], resolved);
break :abs buf[0..resolved.len];
}

try diags.append(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"error resolving file path {s}: {}",
.{ path, err },
),
});

// We can't expand this path so return an empty string
return "";
};

log.debug(
"expanding file path relative={s} abs={s}",
.{ path, abs },
);

return abs;
}

fn loadTheme(self: *Config, theme: Theme) !void {
// Load the correct theme depending on the conditional state.
// Dark/light themes were programmed prior to conditional configuration
Expand Down Expand Up @@ -4288,52 +4368,22 @@ pub const SinglePath = struct {
try formatter.formatEntry([]const u8, value);
}

/// Expand all the paths relative to the base directory.
pub fn expand(
self: *Self,
alloc: Allocator,
base: []const u8,
diags: *cli.DiagnosticList,
) !void {
assert(std.fs.path.isAbsolute(base));
var dir = try std.fs.cwd().openDir(base, .{});
defer dir.close();

// If it is already absolute we can ignore it.
// Try expanding path relative to the base.
const path = self.value orelse return;
if (std.fs.path.isAbsolute(path)) return;

// If it isn't absolute, we need to make it absolute relative
// to the base.
var buf: [std.fs.max_path_bytes]u8 = undefined;
const abs = dir.realpath(path, &buf) catch |err| abs: {
if (err == error.FileNotFound) {
// The file doesn't exist. Try to resolve the relative path
// another way.
const resolved = try std.fs.path.resolve(alloc, &.{ base, path });
defer alloc.free(resolved);
@memcpy(buf[0..resolved.len], resolved);
break :abs buf[0..resolved.len];
}

try diags.append(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"error resolving file path {s}: {}",
.{ path, err },
),
});
const abs = try expandPath(alloc, base, path, diags);

if (abs.len == 0) {
// Blank this path so that we don't attempt to resolve it again
self.value = null;

return;
};

log.debug(
"expanding file path relative={s} abs={s}",
.{ path, abs },
);

}
self.value = try alloc.dupeZ(u8, abs);
}
};
Expand Down Expand Up @@ -4569,88 +4619,20 @@ pub const RepeatablePath = struct {
base: []const u8,
diags: *cli.DiagnosticList,
) !void {
assert(std.fs.path.isAbsolute(base));
var dir = try std.fs.cwd().openDir(base, .{});
defer dir.close();

for (0..self.value.items.len) |i| {
const path = switch (self.value.items[i]) {
.optional, .required => |path| path,
};

// If it is already absolute we can ignore it.
if (path.len == 0 or std.fs.path.isAbsolute(path)) continue;

// If it isn't absolute, we need to make it absolute relative
// to the base.
var buf: [std.fs.max_path_bytes]u8 = undefined;

// Check if the path starts with a tilde and expand it to the
// home directory on Linux/macOS. We explicitly look for "~/"
// because we don't support alternate users such as "~alice/"
if (std.mem.startsWith(u8, path, "~/")) expand: {
// Windows isn't supported yet
if (comptime builtin.os.tag == .windows) break :expand;

const expanded: []const u8 = internal_os.expandHome(
path,
&buf,
) catch |err| {
try diags.append(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"error expanding home directory for path {s}: {}",
.{ path, err },
),
});

// Blank this path so that we don't attempt to resolve it
// again
self.value.items[i] = .{ .required = "" };

continue;
};

log.debug(
"expanding file path from home directory: path={s}",
.{expanded},
);

switch (self.value.items[i]) {
.optional, .required => |*p| p.* = try alloc.dupeZ(u8, expanded),
}

continue;
}

const abs = dir.realpath(path, &buf) catch |err| abs: {
if (err == error.FileNotFound) {
// The file doesn't exist. Try to resolve the relative path
// another way.
const resolved = try std.fs.path.resolve(alloc, &.{ base, path });
defer alloc.free(resolved);
@memcpy(buf[0..resolved.len], resolved);
break :abs buf[0..resolved.len];
}

try diags.append(alloc, .{
.message = try std.fmt.allocPrintZ(
alloc,
"error resolving file path {s}: {}",
.{ path, err },
),
});
// Try expanding path relative to the base.
const abs = try expandPath(alloc, base, path, diags);

if (abs.len == 0) {
// Blank this path so that we don't attempt to resolve it again
self.value.items[i] = .{ .required = "" };

continue;
};

log.debug(
"expanding file path relative={s} abs={s}",
.{ path, abs },
);
}

switch (self.value.items[i]) {
.optional, .required => |*p| p.* = try alloc.dupeZ(u8, abs),
Expand Down Expand Up @@ -5705,6 +5687,11 @@ pub const GraphemeWidthMethod = enum {
};

/// See background-image-mode
///
/// This enum is used to set the background image mode. The shader expects
/// a `uint`, so we use `u8` here. The values for each mode should be kept
/// in sync with the values in the vertex shader used to render the
/// background image (`bgimage`).
pub const BackgroundImageMode = enum(u8) {
zoomed = 0,
stretched = 1,
Expand Down
17 changes: 16 additions & 1 deletion src/renderer/OpenGL.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,22 @@ pub fn prepBackgroundImage(self: *OpenGL) !void {
defer self.alloc.free(file_content);

// Decode the png (currently, we only support png)
const decoded_image = try wuffs.png.decode(self.alloc, file_content);
const decoded_image: wuffs.ImageData = blk: {
// Extract the file extension
const ext = std.fs.path.extension(path);
const ext_lower = try std.ascii.allocLowerString(self.alloc, ext);
defer self.alloc.free(ext_lower);

// Match based on extension
if (std.mem.eql(u8, ext_lower, ".png")) {
break :blk try wuffs.png.decode(self.alloc, file_content);
} else if (std.mem.eql(u8, ext_lower, ".jpg") or std.mem.eql(u8, ext_lower, ".jpeg")) {
break :blk try wuffs.jpeg.decode(self.alloc, file_content);
} else {
log.warn("unsupported image format: {s}", .{ext});
return error.InvalidData;
}
};
defer self.alloc.free(decoded_image.data);

// Copy the data into the pending state
Expand Down
3 changes: 3 additions & 0 deletions src/renderer/shaders/bgimage.v.glsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#version 330 core

// These are the possible modes that "mode" can be set to.
//
// NOTE: this must be kept in sync with the BackgroundImageMode
const uint MODE_ZOOMED = 0u;
const uint MODE_STRETCHED = 1u;
const uint MODE_TILED = 2u;
Expand Down

0 comments on commit 2b64e69

Please sign in to comment.