cleaning up codebase, adding unicode support
This commit is contained in:
parent
bc3ff140b1
commit
44869a7926
|
@ -1,12 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
|
const zg = b.dependency("zg", .{});
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "proxy-print",
|
.name = "proxy-print",
|
||||||
.root_source_file = b.path("src/print.zig"),
|
.root_source_file = b.path("src/print.zig"),
|
||||||
|
@ -20,12 +19,13 @@ pub fn build(b: *std.Build) void {
|
||||||
});
|
});
|
||||||
exe.addIncludePath(b.path("include"));
|
exe.addIncludePath(b.path("include"));
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
|
exe.root_module.addImport("grapheme", zg.module("grapheme"));
|
||||||
|
exe.root_module.addImport("DisplayWidth", zg.module("DisplayWidth"));
|
||||||
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
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| {
|
||||||
|
|
|
@ -15,14 +15,10 @@
|
||||||
// Once all dependencies are fetched, `zig build` no longer requires
|
// Once all dependencies are fetched, `zig build` no longer requires
|
||||||
// internet connectivity.
|
// internet connectivity.
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
//.@"zig-msgpack" = .{
|
.zg = .{
|
||||||
// .url = "https://github.com/zigcc/zig-msgpack/archive/main.tar.gz",
|
.url = "https://codeberg.org/dude_the_builder/zg/archive/v0.13.2.tar.gz",
|
||||||
// .hash = "1220e4669d29190ac809cd3a7726c20b6b49ea7425b7b89cab16d4dc3172016982bc",
|
.hash = "122055beff332830a391e9895c044d33b15ea21063779557024b46169fb1984c6e40",
|
||||||
//},
|
},
|
||||||
//.clap = .{
|
|
||||||
// .url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.8.0.tar.gz",
|
|
||||||
// .hash = "1220949d4e88864579067b6d4cdad6476c6176f27e782782c2c39b7f2c4817a10efb",
|
|
||||||
//},
|
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
// This makes *all* files, recursively, included in this package. It is generally
|
// This makes *all* files, recursively, included in this package. It is generally
|
||||||
|
|
2588
output.pdf
2588
output.pdf
File diff suppressed because it is too large
Load Diff
|
@ -1438,6 +1438,9 @@ static int utf8_to_pdfencoding(struct pdf_doc *pdf, const char *utf8, int len,
|
||||||
case 0x2dc: // Small Tilde
|
case 0x2dc: // Small Tilde
|
||||||
*res = 0230;
|
*res = 0230;
|
||||||
break;
|
break;
|
||||||
|
case 0x2212:
|
||||||
|
*res = 0226;
|
||||||
|
break;
|
||||||
case 0x2013: // Endash
|
case 0x2013: // Endash
|
||||||
*res = 0226;
|
*res = 0226;
|
||||||
break;
|
break;
|
||||||
|
|
113
src/print.zig
113
src/print.zig
|
@ -3,6 +3,7 @@
|
||||||
//
|
//
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const clap = @import("clap");
|
const clap = @import("clap");
|
||||||
|
const DisplayWidth = @import("DisplayWidth");
|
||||||
const c = @cImport({
|
const c = @cImport({
|
||||||
@cInclude("pdfgen.h");
|
@cInclude("pdfgen.h");
|
||||||
});
|
});
|
||||||
|
@ -69,15 +70,12 @@ pub fn main() !void {
|
||||||
const parsedJson = try json.parseFromTokenSource([]Card, allocator, &jsonReader, .{ .ignore_unknown_fields = true });
|
const parsedJson = try json.parseFromTokenSource([]Card, allocator, &jsonReader, .{ .ignore_unknown_fields = true });
|
||||||
|
|
||||||
var cardNames = std.ArrayList([]const u8).init(allocator);
|
var cardNames = std.ArrayList([]const u8).init(allocator);
|
||||||
const listReader = (try cwd.openFile(listFileName, .{})).reader();
|
const listText = try cwd.readFileAlloc(allocator, listFileName, 1024 * 100);
|
||||||
var line = std.ArrayList(u8).init(allocator);
|
var listLines = std.mem.splitAny(u8, listText, "\n");
|
||||||
while (listReader.streamUntilDelimiter(line.writer(), '\n', null)) {
|
while (listLines.next()) |line| {
|
||||||
defer line.clearRetainingCapacity();
|
if (line.len < 5) break;
|
||||||
const cardName = line.items[indexOf(u8, line.items, " ").? + 1 .. indexOf(u8, line.items, "(").? - 1];
|
const cardName = line[indexOf(u8, line, " ").? + 1 .. indexOf(u8, line, "(").? - 1];
|
||||||
try cardNames.append(try allocator.dupe(u8, cardName));
|
try cardNames.append(try allocator.dupe(u8, cardName));
|
||||||
} else |err| switch (err) {
|
|
||||||
error.EndOfStream => {},
|
|
||||||
else => return err,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cards = std.StringArrayHashMap(TextCard).init(allocator);
|
var cards = std.StringArrayHashMap(TextCard).init(allocator);
|
||||||
|
@ -91,13 +89,12 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var allPrinted = std.ArrayList(u8).init(allocator);
|
var allPrinted = std.ArrayList([]const u8).init(allocator);
|
||||||
|
|
||||||
const pdf_doc: *c.pdf_doc = @ptrCast(c.pdf_create(c.PDF_A4_WIDTH, c.PDF_A4_HEIGHT, &c.pdf_info{ .creator = ("My Software" ++ " " ** 53).* }).?);
|
const pdf_doc: *c.pdf_doc = @ptrCast(c.pdf_create(c.PDF_A4_WIDTH, c.PDF_A4_HEIGHT, &c.pdf_info{ .creator = ("My Software" ++ " " ** 53).* }).?);
|
||||||
_ = c.pdf_set_font(pdf_doc, "Times-Roman");
|
_ = c.pdf_set_font(pdf_doc, "Times-Roman");
|
||||||
|
|
||||||
var rowToPrint = std.ArrayList(TextCard).init(allocator);
|
var rowToPrint = std.ArrayList(TextCard).init(allocator);
|
||||||
// var cardIterator = cards.valueIterator();
|
|
||||||
for (cards.values()) |cardText| {
|
for (cards.values()) |cardText| {
|
||||||
try rowToPrint.append(cardText);
|
try rowToPrint.append(cardText);
|
||||||
if (rowToPrint.items.len >= 3) {
|
if (rowToPrint.items.len >= 3) {
|
||||||
|
@ -106,26 +103,22 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try cardRow.print(allocator, rowToPrint.items, &allPrinted);
|
try cardRow.print(allocator, rowToPrint.items, &allPrinted);
|
||||||
std.debug.print("{s}", .{allPrinted.items});
|
for (allPrinted.items) |printLine| {
|
||||||
//TODO (fixme):
|
print("{s}", .{printLine});
|
||||||
// wrong type error when not using ptrCast, nothing printed when using it
|
}
|
||||||
// _ = c.pdf_add_text(pdf_doc, page, allPrinted.items[0..50], 12, 10, c.PDF_A4_HEIGHT - 12, c.PDF_BLACK);
|
// std.debug.print("{s}", .{allPrinted.items});
|
||||||
// _ = c.pdf_add_text(pdf_doc, page, allPrinted.items[0..50], 12, 10, c.PDF_A4_HEIGHT - 12, c.PDF_BLACK);
|
|
||||||
// _ = c.pdf_add_text(pdf_doc, page, "HELLO WEST VIRGINIA", 12, 10, c.PDF_A4_HEIGHT - 12, c.PDF_BLACK);
|
|
||||||
rowToPrint.clearAndFree();
|
rowToPrint.clearAndFree();
|
||||||
}
|
}
|
||||||
var rowsPrinted: f32 = 0;
|
|
||||||
var page = c.pdf_append_page(pdf_doc);
|
var page = c.pdf_append_page(pdf_doc);
|
||||||
var textIterator = std.mem.splitAny(u8, allPrinted.items, "\n");
|
|
||||||
_ = c.pdf_set_font(pdf_doc, "Courier");
|
_ = c.pdf_set_font(pdf_doc, "Courier");
|
||||||
while (textIterator.next()) |text| {
|
for (allPrinted.items, 1..) |text, rowNum| {
|
||||||
if (rowsPrinted < pageHeight) {
|
const pageRelative = rowNum % pageHeight;
|
||||||
rowsPrinted += 1;
|
const pageOffset: f32 = 12 * @as(f32, @floatFromInt(pageRelative));
|
||||||
_ = c.pdf_add_text(pdf_doc, page, try std.mem.Allocator.dupeZ(allocator, u8, text), 8, 10, c.PDF_A4_HEIGHT - (12 * rowsPrinted), c.PDF_BLACK);
|
if (pageRelative != 0) {
|
||||||
|
_ = c.pdf_add_text(pdf_doc, page, try std.mem.Allocator.dupeZ(allocator, u8, text), 8, 10, c.PDF_A4_HEIGHT - pageOffset, c.PDF_BLACK);
|
||||||
} else {
|
} else {
|
||||||
rowsPrinted = 1;
|
|
||||||
page = c.pdf_append_page(pdf_doc);
|
page = c.pdf_append_page(pdf_doc);
|
||||||
_ = c.pdf_add_text(pdf_doc, page, try std.mem.Allocator.dupeZ(allocator, u8, text), 8, 10, c.PDF_A4_HEIGHT - (12 * rowsPrinted), c.PDF_BLACK);
|
_ = c.pdf_add_text(pdf_doc, page, try std.mem.Allocator.dupeZ(allocator, u8, text), 8, 10, c.PDF_A4_HEIGHT - pageOffset, c.PDF_BLACK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,27 +161,28 @@ fn card(
|
||||||
}
|
}
|
||||||
|
|
||||||
var line = std.ArrayList(u8).init(allocator);
|
var line = std.ArrayList(u8).init(allocator);
|
||||||
var word = std.ArrayList(u8).init(allocator);
|
// var word = std.ArrayList(u8).init(allocator);
|
||||||
|
|
||||||
for (fullUnformattedText.items) |char| {
|
var wordIterator = std.mem.splitAny(u8, fullUnformattedText.items, "\n ");
|
||||||
try switch (char) {
|
while (wordIterator.next()) |word| {
|
||||||
'\n', ' ' => addWord(&word, &line, &cardText),
|
if (line.items.len + word.len + 1 < cardWidth) {
|
||||||
else => if (std.ascii.isASCII(char)) {
|
try line.appendSlice(word);
|
||||||
try word.append(char);
|
try line.append(' ');
|
||||||
},
|
assert(line.items.len < 30);
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
try addWord(&word, &line, &cardText);
|
try cardText.append(try line.toOwnedSlice());
|
||||||
const lineToBeAdded = std.mem.trimRight(u8, try line.toOwnedSlice(), " ");
|
|
||||||
// const lineToBeAdded = try line.toOwnedSlice();
|
|
||||||
try cardText.append(lineToBeAdded);
|
|
||||||
line.clearAndFree();
|
line.clearAndFree();
|
||||||
|
try line.appendSlice(word);
|
||||||
|
try line.append(' ');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
try cardText.append(try line.toOwnedSlice());
|
||||||
|
}
|
||||||
|
|
||||||
while (wrongCardHeight(cardText.items.len)) {
|
while (wrongCardHeight(cardText.items.len)) {
|
||||||
try cardText.append(" " ** (cardWidth - 2));
|
try cardText.append(" " ** (cardWidth - 2));
|
||||||
}
|
}
|
||||||
try cardText.append(" " ** (cardWidth - 2));
|
try cardText.append(" " ** (cardWidth - 2));
|
||||||
// return cardText.items;
|
|
||||||
return TextCard{ .lines = try cardText.toOwnedSlice() };
|
return TextCard{ .lines = try cardText.toOwnedSlice() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,29 +190,20 @@ fn wrongCardHeight(length: usize) bool {
|
||||||
return (!heightMayVary and length < cardHeight) or length < minCardHeight;
|
return (!heightMayVary and length < cardHeight) or length < minCardHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addWord(word: *std.ArrayList(u8), line: *std.ArrayList(u8), cardText: *std.ArrayList([]const u8)) !void {
|
|
||||||
if (line.items.len + word.items.len >= (cardWidth)) {
|
|
||||||
const lineToBeAdded = std.mem.trimRight(u8, try line.toOwnedSlice(), " ");
|
|
||||||
assert(lineToBeAdded.len < 30);
|
|
||||||
try cardText.append(lineToBeAdded);
|
|
||||||
line.clearAndFree();
|
|
||||||
}
|
|
||||||
try line.appendSlice(word.items);
|
|
||||||
try line.append(' ');
|
|
||||||
word.clearAndFree();
|
|
||||||
}
|
|
||||||
const linesList = std.MultiArrayList(cardRow);
|
const linesList = std.MultiArrayList(cardRow);
|
||||||
const cardRow = struct {
|
const cardRow = struct {
|
||||||
first: []const u8 = spacer,
|
first: []const u8 = spacer,
|
||||||
second: []const u8 = spacer,
|
second: []const u8 = spacer,
|
||||||
third: []const u8 = spacer,
|
third: []const u8 = spacer,
|
||||||
last: []const u8 = "\n",
|
last: []const u8 = "\n",
|
||||||
fn print(allocator: std.mem.Allocator, cards: []TextCard, allPrinted: *std.ArrayList(u8)) !void {
|
fn print(allocator: std.mem.Allocator, cards: []TextCard, allPrinted: *std.ArrayList([]const u8)) !void {
|
||||||
_ = allocator;
|
// _ = allocator;
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
|
||||||
var lines = linesList{};
|
var lines = linesList{};
|
||||||
defer lines.deinit(gpa.allocator());
|
defer lines.deinit(gpa.allocator());
|
||||||
|
const dwd = try DisplayWidth.DisplayWidthData.init(allocator);
|
||||||
|
const dw = DisplayWidth{ .data = &dwd };
|
||||||
|
|
||||||
for (cards, 0..) |cardObj, cardNo| {
|
for (cards, 0..) |cardObj, cardNo| {
|
||||||
//const cardText = try card(cardObj);
|
//const cardText = try card(cardObj);
|
||||||
|
@ -227,9 +212,12 @@ const cardRow = struct {
|
||||||
//this step is probably unnecessary
|
//this step is probably unnecessary
|
||||||
const strippedLine = std.mem.trimRight(u8, line, " ");
|
const strippedLine = std.mem.trimRight(u8, line, " ");
|
||||||
const paddedLine = try std.fmt.allocPrint(gpa.allocator(), lineFormatter, .{strippedLine});
|
const paddedLine = try std.fmt.allocPrint(gpa.allocator(), lineFormatter, .{strippedLine});
|
||||||
const theoreticalLength = (paddedLine.len * 3) + 1;
|
// const theoreticalLength = (paddedLine.len * 3) + 1;
|
||||||
assert(paddedLine.len == spacer.len);
|
std.debug.print("{s}\n", .{paddedLine});
|
||||||
assert(theoreticalLength == pageWidth);
|
std.debug.print("expected {d}, got: ", .{dw.strWidth(spacer)});
|
||||||
|
std.debug.print("{d}\n", .{dw.strWidth(paddedLine)});
|
||||||
|
assert(dw.strWidth(paddedLine) == dw.strWidth(spacer));
|
||||||
|
// assert(theoreticalLength == pageWidth);
|
||||||
const placeholder = if (idx < lines.items(.first).len) lines.get(idx) else cardRow{};
|
const placeholder = if (idx < lines.items(.first).len) lines.get(idx) else cardRow{};
|
||||||
const new: cardRow = switch (cardNo) {
|
const new: cardRow = switch (cardNo) {
|
||||||
0 => .{ .first = paddedLine },
|
0 => .{ .first = paddedLine },
|
||||||
|
@ -245,28 +233,19 @@ const cardRow = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const rowHeight = lines.items(.first).len;
|
const rowHeight = lines.items(.first).len;
|
||||||
while (remainingPage(allPrinted.items.len) <= rowHeight) {
|
while (pageHeight - (allPrinted.items.len % pageHeight) <= rowHeight) {
|
||||||
try allPrinted.appendSlice(fullWidthSpacer);
|
try allPrinted.append(fullWidthSpacer);
|
||||||
}
|
}
|
||||||
for (lines.items(.first), 0..) |_, idx| {
|
for (lines.items(.first), 0..) |_, idx| {
|
||||||
const line = lines.get(idx);
|
const line = lines.get(idx);
|
||||||
const printedWidth = line.first.len + line.second.len + line.third.len + line.last.len;
|
// const printedWidth = line + line.second.len + line.third.len + line.last.len;
|
||||||
assert(printedWidth == pageWidth);
|
// assert(printedWidth == pageWidth);
|
||||||
const fullLine = try std.mem.concat(gpa.allocator(), u8, &[_][]const u8{ line.first, line.second, line.third, line.last });
|
const fullLine = try std.mem.concat(gpa.allocator(), u8, &[_][]const u8{ line.first, line.second, line.third, line.last });
|
||||||
try allPrinted.appendSlice(fullLine);
|
try allPrinted.append(fullLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "Remaining page length" {
|
|
||||||
try expect(remainingPage(67) == 0);
|
|
||||||
try expect(remainingPage(1) == 0);
|
|
||||||
}
|
|
||||||
fn remainingPage(length: usize) usize {
|
|
||||||
assert(length % pageWidth == 0);
|
|
||||||
return pageHeight - ((length / pageWidth) % pageHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stringToBool(str: ?[]const u8) bool {
|
fn stringToBool(str: ?[]const u8) bool {
|
||||||
return std.mem.eql(u8, (str orelse "false"), "true");
|
return std.mem.eql(u8, (str orelse "false"), "true");
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue