lib/pdf/src/font.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 const cmap = @import("cmap.zig");
4
5 pub const Font = struct {
6 map: ?cmap.Map = null,
7 };
8
9 pub const Entry = struct {
10 name: []const u8,
11 font: *const Font,
12 };
13
14 pub const Set = struct {
15 entries: []const Entry = &.{},
16
17 pub fn get(self: Set, name: []const u8) ?*const Font {
18 for (self.entries) |entry| {
19 if (std.mem.eql(u8, entry.name, name)) return entry.font;
20 }
21 return null;
22 }
23 };
24
25 pub fn appendText(current: ?*const Font, allocator: std.mem.Allocator, out: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory}!void {
26 if (current) |selected| {
27 if (selected.map) |map| return map.appendDecoded(allocator, out, bytes);
28 }
29 out.appendSlice(allocator, bytes) catch return error.OutOfMemory;
30 }
31
32 test "font set resolves names and unmapped fonts pass bytes through" {
33 const plain = Font{};
34 const set = Set{ .entries = &.{.{ .name = "F1", .font = &plain }} };
35 try std.testing.expect(set.get("F1") != null);
36 try std.testing.expect(set.get("F2") == null);
37 var out = std.ArrayList(u8).empty;
38 defer out.deinit(std.testing.allocator);
39 try appendText(set.get("F1"), std.testing.allocator, &out, "raw bytes");
40 try appendText(null, std.testing.allocator, &out, "!");
41 try std.testing.expectEqualStrings("raw bytes!", out.items);
42 }