Compare commits
3 Commits
c2ba2efd76
...
a2bca12bc7
Author | SHA1 | Date | |
---|---|---|---|
a2bca12bc7 | |||
bd8b3a1da3 | |||
8c1381daf4 |
29
.github/workflows/zig-build.yaml
vendored
Normal file
29
.github/workflows/zig-build.yaml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
name: Generic zig build
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
- '!zig-develop*'
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: elerch/setup-zig@v3
|
||||||
|
with:
|
||||||
|
version: 0.12.0
|
||||||
|
- uses: elerch/zig-action-cache@v1.1.6
|
||||||
|
- name: Build project
|
||||||
|
run: zig build --summary all
|
||||||
|
- name: Run tests
|
||||||
|
run: zig build test --summary all
|
||||||
|
- name: Notify
|
||||||
|
uses: elerch/action-notify-ntfy@v2.github
|
||||||
|
if: env.GITEA_ACTIONS == 'true'
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.NTFY_HOST }}
|
||||||
|
topic: ${{ secrets.NTFY_TOPIC }}
|
||||||
|
status: ${{ job.status }}
|
||||||
|
user: ${{ secrets.NTFY_USER }}
|
||||||
|
password: ${{ secrets.NTFY_PASSWORD }}
|
|
@ -11,7 +11,7 @@ path: []const u8,
|
||||||
pub fn create(b: *std.build.Builder, opt: struct {
|
pub fn create(b: *std.build.Builder, opt: struct {
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
}) *AsciiPrintableStep {
|
}) *AsciiPrintableStep {
|
||||||
var result = b.allocator.create(AsciiPrintableStep) catch @panic("OOM");
|
const result = b.allocator.create(AsciiPrintableStep) catch @panic("OOM");
|
||||||
result.* = AsciiPrintableStep{
|
result.* = AsciiPrintableStep{
|
||||||
.step = std.build.Step.init(.{
|
.step = std.build.Step.init(.{
|
||||||
.id = .custom,
|
.id = .custom,
|
||||||
|
@ -40,7 +40,7 @@ fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.St
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make(step: *std.build.Step, _: *std.Progress.Node) !void {
|
fn make(step: *std.build.Step, _: *std.Progress.Node) !void {
|
||||||
const self = @fieldParentPtr(AsciiPrintableStep, "step", step);
|
const self: AsciiPrintableStep = @fieldParentPtr("step", step);
|
||||||
|
|
||||||
const zig_file = std.fmt.allocPrint(self.builder.allocator, "{s}/images.zig", .{self.path}) catch @panic("OOM");
|
const zig_file = std.fmt.allocPrint(self.builder.allocator, "{s}/images.zig", .{self.path}) catch @panic("OOM");
|
||||||
defer self.builder.allocator.free(zig_file);
|
defer self.builder.allocator.free(zig_file);
|
||||||
|
@ -67,7 +67,7 @@ fn make(step: *std.build.Step, _: *std.Progress.Node) !void {
|
||||||
// try writer.print(" \"\",\n", .{});
|
// try writer.print(" \"\",\n", .{});
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
const char_str = [_]u8{@intCast(u8, i)};
|
const char_str = [_]u8{@intCast(i)};
|
||||||
// Need to escape the following chars: 32 (' ') 92 ('\')
|
// Need to escape the following chars: 32 (' ') 92 ('\')
|
||||||
const label_param = parm: {
|
const label_param = parm: {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
|
|
19
build.zig
19
build.zig
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const AsciiPrintableStep = @import("AsciiPrintableStep.zig");
|
const AsciiPrintableStep = @import("AsciiPrintableStep.zig");
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) !void {
|
pub fn build(b: *std.Build) !void {
|
||||||
// comptime {
|
// comptime {
|
||||||
// const current_zig = builtin.zig_version;
|
// const current_zig = builtin.zig_version;
|
||||||
// const min_zig = std.SemanticVersion.parse("0.11.0-dev.1254+1f8f79cd5") catch return; // add helper functions to std.zig.Ast
|
// const min_zig = std.SemanticVersion.parse("0.11.0-dev.1254+1f8f79cd5") catch return; // add helper functions to std.zig.Ast
|
||||||
|
@ -31,7 +31,10 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
i2cdriver.addCSourceFile("lib/i2cdriver/i2cdriver.c", &[_][]const u8{ "-Wall", "-Wpointer-sign", "-Werror" });
|
i2cdriver.addCSourceFile(.{
|
||||||
|
.file = b.path("lib/i2cdriver/i2cdriver.c"),
|
||||||
|
.flags = &[_][]const u8{ "-Wall", "-Wpointer-sign", "-Werror" },
|
||||||
|
});
|
||||||
i2cdriver.linkLibC();
|
i2cdriver.linkLibC();
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
|
@ -43,8 +46,8 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
exe.linkLibrary(im_dep.artifact("MagickWand"));
|
exe.linkLibrary(im_dep.artifact("MagickWand"));
|
||||||
exe.linkLibrary(z_dep.artifact("z"));
|
exe.linkLibrary(z_dep.artifact("z"));
|
||||||
exe.linkLibrary(i2cdriver);
|
exe.linkLibrary(i2cdriver);
|
||||||
exe.addIncludePath("lib/i2cdriver");
|
exe.addIncludePath(b.path("lib/i2cdriver"));
|
||||||
exe.install();
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const exe_fontgen = b.addExecutable(.{
|
const exe_fontgen = b.addExecutable(.{
|
||||||
.name = "fontgen",
|
.name = "fontgen",
|
||||||
|
@ -54,11 +57,11 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
});
|
});
|
||||||
exe_fontgen.linkLibrary(im_dep.artifact("MagickWand"));
|
exe_fontgen.linkLibrary(im_dep.artifact("MagickWand"));
|
||||||
exe_fontgen.linkLibrary(z_dep.artifact("z"));
|
exe_fontgen.linkLibrary(z_dep.artifact("z"));
|
||||||
exe.step.dependOn(&exe_fontgen.run().step);
|
exe.step.dependOn(&b.addRunArtifact(exe_fontgen).step);
|
||||||
|
|
||||||
// If image based characters are needed, uncomment this
|
// If image based characters are needed, uncomment this
|
||||||
// exe.step.dependOn(&AsciiPrintableStep.create(b, .{ .path = "src/images" }).step);
|
// exe.step.dependOn(&AsciiPrintableStep.create(b, .{ .path = "src/images" }).step);
|
||||||
const run_cmd = exe.run();
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
|
@ -75,10 +78,10 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
exe_tests.linkLibrary(im_dep.artifact("MagickWand"));
|
exe_tests.linkLibrary(im_dep.artifact("MagickWand"));
|
||||||
exe_tests.linkLibrary(z_dep.artifact("z"));
|
exe_tests.linkLibrary(z_dep.artifact("z"));
|
||||||
exe_tests.linkLibrary(i2cdriver);
|
exe_tests.linkLibrary(i2cdriver);
|
||||||
exe_tests.addIncludePath("lib/i2cdriver");
|
exe_tests.addIncludePath(b.path("lib/i2cdriver"));
|
||||||
|
|
||||||
const test_step = b.step("test", "Run unit tests");
|
const test_step = b.step("test", "Run unit tests");
|
||||||
test_step.dependOn(&exe_tests.run().step);
|
test_step.dependOn(&b.addRunArtifact(exe_tests).step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be able to remove this
|
// Should be able to remove this
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
.{
|
.{
|
||||||
.name = "i2c",
|
.name = "i2c",
|
||||||
.version = "0.0.1",
|
.version = "0.0.1",
|
||||||
|
.paths = .{
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.ImageMagick = .{
|
.ImageMagick = .{
|
||||||
.url = "https://github.com/elerch/ImageMagick/archive/0c78c43ba348fe2d764593b074b4f53d087a3a26.tar.gz",
|
.url = "https://github.com/elerch/ImageMagick/archive/91d7290d02188139486fd5078446ddd88e57aebe.tar.gz",
|
||||||
.hash = "12208162dcc0b1f2e5fb6376136fe5266b2b493a38ca8f30eff94b735f7da6ada462",
|
.hash = "1220a49c78df0938f80aca90d23ac694a1550d5329fe0594918c000fbcf0c9354822",
|
||||||
},
|
},
|
||||||
.libz = .{
|
.libz = .{
|
||||||
.url="https://github.com/andrewrk/libz/archive/9e71b746b83d2b5bf5eb247663eb65a52cf0f68f.tar.gz",
|
.url = "https://github.com/elerch/libz/archive/1632972f211c6876d6dd8fcfdc13414a26b55c65.tar.gz",
|
||||||
.hash = "12204ea3490e5bdf379f56aa11784d906aed6d4c553c724fa5427169915f2cf4a651",
|
.hash = "12200d3858388c9f74ef769cab3762cfddb4aee33133a5e08c96ee68130b2664f13a",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,9 @@ pub fn main() !void {
|
||||||
const generated_file = try proj_path.createFile("src/fonts/fonts.zig", .{
|
const generated_file = try proj_path.createFile("src/fonts/fonts.zig", .{
|
||||||
.read = false,
|
.read = false,
|
||||||
.truncate = true,
|
.truncate = true,
|
||||||
.lock = .Exclusive,
|
.lock = .exclusive,
|
||||||
.lock_nonblocking = false,
|
.lock_nonblocking = false,
|
||||||
.mode = 0o666,
|
.mode = 0o666,
|
||||||
.intended_io_mode = .blocking,
|
|
||||||
});
|
});
|
||||||
defer generated_file.close();
|
defer generated_file.close();
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ pub fn main() !void {
|
||||||
// try writer.print(" \"\",\n", .{});
|
// try writer.print(" \"\",\n", .{});
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
const char_str = [_]u8{@intCast(u8, i)};
|
const char_str = [_]u8{@intCast(i)};
|
||||||
// Need to escape the following chars: 32 (' ') 92 ('\')
|
// Need to escape the following chars: 32 (' ') 92 ('\')
|
||||||
const label_param = parm: {
|
const label_param = parm: {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
|
@ -155,11 +154,11 @@ fn run(allocator: std.mem.Allocator, argv: []const []const u8) !void {
|
||||||
}
|
}
|
||||||
std.log.debug("[RUN] {s}", .{msg.items});
|
std.log.debug("[RUN] {s}", .{msg.items});
|
||||||
}
|
}
|
||||||
std.os.exit(0xff);
|
std.posix.exit(0xff);
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
std.log.err("command failed with: {}", .{result});
|
std.log.err("command failed with: {}", .{result});
|
||||||
std.os.exit(0xff);
|
std.posix.exit(0xff);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,8 +171,8 @@ pub fn unpackBits(pixels: *[GLYPH_WIDTH * GLYPH_HEIGHT]u8) void {
|
||||||
// overwrites
|
// overwrites
|
||||||
var i: isize = (GLYPH_WIDTH * GLYPH_HEIGHT / 8 - 1);
|
var i: isize = (GLYPH_WIDTH * GLYPH_HEIGHT / 8 - 1);
|
||||||
while (i >= 0) {
|
while (i >= 0) {
|
||||||
const start = @intCast(usize, i) * 8;
|
const start = @as(usize, @intCast(i)) * 8;
|
||||||
const packed_byte = pixels[@intCast(usize, i)];
|
const packed_byte = pixels[@intCast(i)];
|
||||||
pixels[start + 7] = ((packed_byte & 0b10000000) >> 7) * 0xFF;
|
pixels[start + 7] = ((packed_byte & 0b10000000) >> 7) * 0xFF;
|
||||||
pixels[start + 6] = ((packed_byte & 0b01000000) >> 6) * 0xFF;
|
pixels[start + 6] = ((packed_byte & 0b01000000) >> 6) * 0xFF;
|
||||||
pixels[start + 5] = ((packed_byte & 0b00100000) >> 5) * 0xFF;
|
pixels[start + 5] = ((packed_byte & 0b00100000) >> 5) * 0xFF;
|
||||||
|
@ -235,7 +234,7 @@ fn convertImage(filename: [:0]u8, pixels: *[GLYPH_WIDTH * GLYPH_HEIGHT]u8) !void
|
||||||
if (status == c.MagickFalse)
|
if (status == c.MagickFalse)
|
||||||
return error.CouldNotQuantizeImage;
|
return error.CouldNotQuantizeImage;
|
||||||
|
|
||||||
status = c.MagickExportImagePixels(mw, 0, 0, GLYPH_WIDTH, GLYPH_HEIGHT, "I", c.CharPixel, @ptrCast(*anyopaque, pixels));
|
status = c.MagickExportImagePixels(mw, 0, 0, GLYPH_WIDTH, GLYPH_HEIGHT, "I", c.CharPixel, @as(*anyopaque, @ptrCast(pixels)));
|
||||||
|
|
||||||
if (status == c.MagickFalse)
|
if (status == c.MagickFalse)
|
||||||
return error.CouldNotExportImage;
|
return error.CouldNotExportImage;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn ioctl(handle: std.os.fd_t, request: u32, arg: usize) !void {
|
pub fn ioctl(handle: std.posix.fd_t, request: u32, arg: usize) !void {
|
||||||
const rc = std.os.linux.ioctl(handle, request, arg);
|
const rc = std.os.linux.ioctl(handle, request, arg);
|
||||||
try throwReturnCodeError(rc);
|
try throwReturnCodeError(rc);
|
||||||
return;
|
return;
|
||||||
|
@ -8,7 +8,7 @@ pub fn ioctl(handle: std.os.fd_t, request: u32, arg: usize) !void {
|
||||||
|
|
||||||
pub fn throwReturnCodeError(return_code: usize) LinuxGenericError!void {
|
pub fn throwReturnCodeError(return_code: usize) LinuxGenericError!void {
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
switch (std.os.errno(return_code)) {
|
switch (std.posix.errno(return_code)) {
|
||||||
.SUCCESS => return,
|
.SUCCESS => return,
|
||||||
.PERM => return LinuxGenericError.OperationNotPermittedError,
|
.PERM => return LinuxGenericError.OperationNotPermittedError,
|
||||||
.NOENT => return LinuxGenericError.NoSuchFileOrDirectoryError,
|
.NOENT => return LinuxGenericError.NoSuchFileOrDirectoryError,
|
||||||
|
|
42
src/main.zig
42
src/main.zig
|
@ -34,7 +34,7 @@ fn usage(args: [][]u8) !void {
|
||||||
try writer.print("usage: {s} <device> [-bg <image file>] [-<num> text]...\n", .{args[0]});
|
try writer.print("usage: {s} <device> [-bg <image file>] [-<num> text]...\n", .{args[0]});
|
||||||
try writer.print("\t-<num> text: line number and text to display\n", .{});
|
try writer.print("\t-<num> text: line number and text to display\n", .{});
|
||||||
try writer.print("\te.g. \"-1 'hello world'\" will display \"hello world\" on line 1\n", .{});
|
try writer.print("\te.g. \"-1 'hello world'\" will display \"hello world\" on line 1\n", .{});
|
||||||
std.os.exit(1);
|
std.posix.exit(1);
|
||||||
}
|
}
|
||||||
const Options = struct {
|
const Options = struct {
|
||||||
background_filename: [:0]u8,
|
background_filename: [:0]u8,
|
||||||
|
@ -76,7 +76,7 @@ pub fn main() !void {
|
||||||
try std.io.getStdErr().writer().print("ERROR: data provided exceeds what can be sent to device!\n", .{});
|
try std.io.getStdErr().writer().print("ERROR: data provided exceeds what can be sent to device!\n", .{});
|
||||||
try usage(args);
|
try usage(args);
|
||||||
}
|
}
|
||||||
var read_data = stdin_data[0..read];
|
const read_data = stdin_data[0..read];
|
||||||
var it = std.mem.split(u8, read_data, "\n");
|
var it = std.mem.split(u8, read_data, "\n");
|
||||||
while (it.next()) |line| {
|
while (it.next()) |line| {
|
||||||
if (line.len == 0) continue;
|
if (line.len == 0) continue;
|
||||||
|
@ -153,7 +153,7 @@ fn processArgs(args: [][:0]u8, line_array: *[display.LINES]*const [:0]u8) !Optio
|
||||||
"ERROR: text for line {d} has {d} chars, exceeding maximum length {d}\n",
|
"ERROR: text for line {d} has {d} chars, exceeding maximum length {d}\n",
|
||||||
.{ line, arg.len, display.CHARS_PER_LINE },
|
.{ line, arg.len, display.CHARS_PER_LINE },
|
||||||
);
|
);
|
||||||
std.os.exit(1);
|
std.posix.exit(1);
|
||||||
}
|
}
|
||||||
std.log.debug("line {d} text: \"{s}\"\n", .{ line, arg });
|
std.log.debug("line {d} text: \"{s}\"\n", .{ line, arg });
|
||||||
line_array.*[line] = &args[i];
|
line_array.*[line] = &args[i];
|
||||||
|
@ -181,7 +181,7 @@ fn flipImage(pixels: *[display.WIDTH * display.HEIGHT]u8) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addTextToImage(allocator: std.mem.Allocator, pixels: *[display.WIDTH * display.HEIGHT]u8, data: []*[]u8) !void {
|
fn addTextToImage(allocator: std.mem.Allocator, pixels: *[display.WIDTH * display.HEIGHT]u8, data: []*[]u8) !void {
|
||||||
var maybe_font_data = try getFontData(allocator, DEFAULT_FONT);
|
const maybe_font_data = try getFontData(allocator, DEFAULT_FONT);
|
||||||
|
|
||||||
if (maybe_font_data == null) return error.FontNotFound;
|
if (maybe_font_data == null) return error.FontNotFound;
|
||||||
var font_data = maybe_font_data.?;
|
var font_data = maybe_font_data.?;
|
||||||
|
@ -220,7 +220,7 @@ fn getFontData(allocator: std.mem.Allocator, font_name: []const u8) !?FontInnerH
|
||||||
if (font_arena == null) {
|
if (font_arena == null) {
|
||||||
font_arena = std.heap.ArenaAllocator.init(allocator);
|
font_arena = std.heap.ArenaAllocator.init(allocator);
|
||||||
}
|
}
|
||||||
var alloc = font_arena.?.allocator();
|
const alloc = font_arena.?.allocator();
|
||||||
// The bit lookup will be a bit tricky because we have runtime value to look up
|
// The bit lookup will be a bit tricky because we have runtime value to look up
|
||||||
// We can use an inline for but compute complexity is a bit crazy. Best to use a
|
// We can use an inline for but compute complexity is a bit crazy. Best to use a
|
||||||
// hashmap here
|
// hashmap here
|
||||||
|
@ -277,7 +277,7 @@ fn getFontMap(allocator: std.mem.Allocator, comptime font_name: []const u8) !*Fo
|
||||||
.{fmtSliceHexLower(@field(font_struct, point.name))},
|
.{fmtSliceHexLower(@field(font_struct, point.name))},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
var key_ptr = try allocator.create(u21);
|
const key_ptr = try allocator.create(u21);
|
||||||
key_ptr.* = std.fmt.parseInt(u21, point.name, 10) catch unreachable;
|
key_ptr.* = std.fmt.parseInt(u21, point.name, 10) catch unreachable;
|
||||||
map.putAssumeCapacity(
|
map.putAssumeCapacity(
|
||||||
key_ptr.*,
|
key_ptr.*,
|
||||||
|
@ -344,7 +344,7 @@ fn sendPixelsThroughI2CDriver(pixels: []const u8, file: [*:0]const u8, device_id
|
||||||
.ccitt_crc = 0,
|
.ccitt_crc = 0,
|
||||||
.e_ccitt_crc = 0,
|
.e_ccitt_crc = 0,
|
||||||
};
|
};
|
||||||
const c_file = @ptrCast([*c]const u8, file);
|
const c_file: [*c]const u8 = @ptrCast(file);
|
||||||
const stdout_file = std.io.getStdOut().writer();
|
const stdout_file = std.io.getStdOut().writer();
|
||||||
var bw = std.io.bufferedWriter(stdout_file);
|
var bw = std.io.bufferedWriter(stdout_file);
|
||||||
const stdout = bw.writer();
|
const stdout = bw.writer();
|
||||||
|
@ -382,7 +382,7 @@ fn sendPixelsThroughI2CDriver(pixels: []const u8, file: [*:0]const u8, device_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i2cWrite(i2c: *c.I2CDriver, bytes: []const u8) !void {
|
fn i2cWrite(i2c: *c.I2CDriver, bytes: []const u8) !void {
|
||||||
var rc = c.i2c_write(i2c, @ptrCast([*c]const u8, bytes), bytes.len); // nn is size of array
|
const rc = c.i2c_write(i2c, @ptrCast(bytes), bytes.len); // nn is size of array
|
||||||
if (rc != 1)
|
if (rc != 1)
|
||||||
return error.BadWrite;
|
return error.BadWrite;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ fn formatSliceGreyscaleImage(
|
||||||
fn reportMagickError(mw: ?*c.MagickWand) !void {
|
fn reportMagickError(mw: ?*c.MagickWand) !void {
|
||||||
var severity: c.ExceptionType = undefined;
|
var severity: c.ExceptionType = undefined;
|
||||||
var description = c.MagickGetException(mw, &severity);
|
var description = c.MagickGetException(mw, &severity);
|
||||||
defer description = @ptrCast([*c]u8, c.MagickRelinquishMemory(description));
|
defer description = @ptrCast(c.MagickRelinquishMemory(description));
|
||||||
try std.io.getStdErr().writer().print("{s}\n", .{description});
|
try std.io.getStdErr().writer().print("{s}\n", .{description});
|
||||||
}
|
}
|
||||||
fn textForLine(line: usize) []u8 {
|
fn textForLine(line: usize) []u8 {
|
||||||
|
@ -514,8 +514,8 @@ fn convertImage(filename: [:0]u8, pixels: *[display.WIDTH * display.HEIGHT]u8, t
|
||||||
mw,
|
mw,
|
||||||
display.WIDTH,
|
display.WIDTH,
|
||||||
display.HEIGHT,
|
display.HEIGHT,
|
||||||
-@intCast(isize, (display.WIDTH - resize_dimensions.width) / 2),
|
-@as(isize, @intCast((display.WIDTH - resize_dimensions.width) / 2)),
|
||||||
-@intCast(isize, (display.HEIGHT - resize_dimensions.height) / 2),
|
-@as(isize, @intCast((display.HEIGHT - resize_dimensions.height) / 2)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (status == c.MagickFalse)
|
if (status == c.MagickFalse)
|
||||||
|
@ -525,7 +525,7 @@ fn convertImage(filename: [:0]u8, pixels: *[display.WIDTH * display.HEIGHT]u8, t
|
||||||
const text = text_fn(i);
|
const text = text_fn(i);
|
||||||
if (text.len == 0) continue;
|
if (text.len == 0) continue;
|
||||||
// We have text!
|
// We have text!
|
||||||
const y: isize = display.FONT_HEIGHT * @intCast(isize, i);
|
const y: isize = display.FONT_HEIGHT * @as(isize, @intCast(i));
|
||||||
var x: isize = display.BORDER_LEFT;
|
var x: isize = display.BORDER_LEFT;
|
||||||
var left_spaces: isize = 0;
|
var left_spaces: isize = 0;
|
||||||
for (text) |ch| {
|
for (text) |ch| {
|
||||||
|
@ -536,7 +536,7 @@ fn convertImage(filename: [:0]u8, pixels: *[display.WIDTH * display.HEIGHT]u8, t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
x += (display.FONT_WIDTH * left_spaces);
|
x += (display.FONT_WIDTH * left_spaces);
|
||||||
mw = try drawString(mw, text[@intCast(usize, left_spaces)..], x, y);
|
mw = try drawString(mw, text[@intCast(left_spaces)..], x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We make the image monochrome by quantizing the image with 2 colors in the
|
// We make the image monochrome by quantizing the image with 2 colors in the
|
||||||
|
@ -558,7 +558,7 @@ fn convertImage(filename: [:0]u8, pixels: *[display.WIDTH * display.HEIGHT]u8, t
|
||||||
if (status == c.MagickFalse)
|
if (status == c.MagickFalse)
|
||||||
return error.CouldNotQuantizeImage;
|
return error.CouldNotQuantizeImage;
|
||||||
|
|
||||||
status = c.MagickExportImagePixels(mw, 0, 0, display.WIDTH, display.HEIGHT, "I", c.CharPixel, @ptrCast(*anyopaque, pixels));
|
status = c.MagickExportImagePixels(mw, 0, 0, display.WIDTH, display.HEIGHT, "I", c.CharPixel, @as(*anyopaque, @ptrCast(pixels)));
|
||||||
|
|
||||||
if (status == c.MagickFalse)
|
if (status == c.MagickFalse)
|
||||||
return error.CouldNotExportImage;
|
return error.CouldNotExportImage;
|
||||||
|
@ -577,7 +577,7 @@ fn drawString(mw: ?*c.MagickWand, str: []const u8, x: isize, y: isize) !?*c.Magi
|
||||||
rc = try drawCharacter(
|
rc = try drawCharacter(
|
||||||
rc,
|
rc,
|
||||||
ch,
|
ch,
|
||||||
-(x + @intCast(isize, display.FONT_WIDTH * i)),
|
-(x + @as(isize, @intCast(display.FONT_WIDTH * i))),
|
||||||
-y,
|
-y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -596,7 +596,7 @@ fn drawCharacter(mw: ?*c.MagickWand, char: u8, x: isize, y: isize) !?*c.MagickWa
|
||||||
}
|
}
|
||||||
const image_char = chars[char];
|
const image_char = chars[char];
|
||||||
if (image_char.len == 0) return error.CharacterNotSupported;
|
if (image_char.len == 0) return error.CharacterNotSupported;
|
||||||
var status = c.MagickReadImageBlob(cw, @ptrCast(?*const anyopaque, image_char), image_char.len);
|
var status = c.MagickReadImageBlob(cw, @ptrCast(image_char), image_char.len);
|
||||||
if (status == c.MagickFalse) unreachable; // Something is terribly wrong if this fails
|
if (status == c.MagickFalse) unreachable; // Something is terribly wrong if this fails
|
||||||
|
|
||||||
// For character placement, we need to set the image to the correct
|
// For character placement, we need to set the image to the correct
|
||||||
|
@ -650,20 +650,20 @@ const Dimensions = struct {
|
||||||
fn getNewDimensions(width: usize, height: usize, desired_width: usize, desired_height: usize) Dimensions {
|
fn getNewDimensions(width: usize, height: usize, desired_width: usize, desired_height: usize) Dimensions {
|
||||||
// assuming we're shrinking for now.
|
// assuming we're shrinking for now.
|
||||||
// TODO: Handle expansion
|
// TODO: Handle expansion
|
||||||
const width_ratio = @intToFloat(f64, width) / @intToFloat(f64, desired_width);
|
const width_ratio = @as(f64, @floatFromInt(width)) / @as(f64, @floatFromInt(desired_width));
|
||||||
const height_ratio = @intToFloat(f64, height) / @intToFloat(f64, desired_height);
|
const height_ratio = @as(f64, @floatFromInt(height)) / @as(f64, @floatFromInt(desired_height));
|
||||||
const resize_ratio = if (width_ratio > height_ratio) width_ratio else height_ratio;
|
const resize_ratio = if (width_ratio > height_ratio) width_ratio else height_ratio;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.width = @floatToInt(usize, @intToFloat(f64, width) / resize_ratio), // 48,
|
.width = @intFromFloat(@as(f64, @floatFromInt(width)) / resize_ratio), // 48,
|
||||||
.height = @floatToInt(usize, @intToFloat(f64, height) / resize_ratio), // 64,
|
.height = @intFromFloat(@as(f64, @floatFromInt(height)) / resize_ratio), // 64,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
test "gets proper font data" {
|
test "gets proper font data" {
|
||||||
// std.testing.log_level = .debug;
|
// std.testing.log_level = .debug;
|
||||||
std.log.debug("\n", .{});
|
std.log.debug("\n", .{});
|
||||||
defer deinit();
|
defer deinit();
|
||||||
var maybe_font_data = try getFontData(std.testing.allocator, DEFAULT_FONT);
|
const maybe_font_data = try getFontData(std.testing.allocator, DEFAULT_FONT);
|
||||||
try std.testing.expect(maybe_font_data != null);
|
try std.testing.expect(maybe_font_data != null);
|
||||||
var font_data = maybe_font_data.?;
|
var font_data = maybe_font_data.?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user