@tbsoft-gmbh/signature-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ declare const FONT_8X13: Record<string, number[]>;
2
+
3
+ export { FONT_8X13 };
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/font-8x13.ts
21
+ var font_8x13_exports = {};
22
+ __export(font_8x13_exports, {
23
+ FONT_8X13: () => FONT_8X13
24
+ });
25
+ module.exports = __toCommonJS(font_8x13_exports);
26
+ var FONT_8X13 = {
27
+ // ─── Space ───────────────────────────────────────────────────────────────
28
+ " ": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
29
+ // ─── Digits ──────────────────────────────────────────────────────────────
30
+ "0": [0, 0, 60, 102, 110, 118, 102, 102, 102, 60, 0, 0, 0],
31
+ "1": [0, 0, 24, 56, 24, 24, 24, 24, 24, 126, 0, 0, 0],
32
+ "2": [0, 0, 60, 102, 6, 12, 24, 48, 96, 126, 0, 0, 0],
33
+ "3": [0, 0, 60, 102, 6, 28, 6, 6, 102, 60, 0, 0, 0],
34
+ "4": [0, 0, 12, 28, 44, 76, 126, 12, 12, 12, 0, 0, 0],
35
+ "5": [0, 0, 126, 96, 96, 124, 6, 6, 102, 60, 0, 0, 0],
36
+ "6": [0, 0, 28, 48, 96, 124, 102, 102, 102, 60, 0, 0, 0],
37
+ "7": [0, 0, 126, 6, 12, 24, 24, 48, 48, 48, 0, 0, 0],
38
+ "8": [0, 0, 60, 102, 102, 60, 102, 102, 102, 60, 0, 0, 0],
39
+ "9": [0, 0, 60, 102, 102, 102, 62, 6, 12, 56, 0, 0, 0],
40
+ // ─── Uppercase A–Z ───────────────────────────────────────────────────────
41
+ "A": [0, 0, 24, 60, 102, 102, 126, 102, 102, 102, 0, 0, 0],
42
+ "B": [0, 0, 124, 102, 102, 124, 102, 102, 102, 124, 0, 0, 0],
43
+ "C": [0, 0, 60, 102, 96, 96, 96, 96, 102, 60, 0, 0, 0],
44
+ "D": [0, 0, 120, 108, 102, 102, 102, 102, 108, 120, 0, 0, 0],
45
+ "E": [0, 0, 126, 96, 96, 124, 96, 96, 96, 126, 0, 0, 0],
46
+ "F": [0, 0, 126, 96, 96, 124, 96, 96, 96, 96, 0, 0, 0],
47
+ "G": [0, 0, 60, 102, 96, 96, 110, 102, 102, 62, 0, 0, 0],
48
+ "H": [0, 0, 102, 102, 102, 126, 102, 102, 102, 102, 0, 0, 0],
49
+ "I": [0, 0, 60, 24, 24, 24, 24, 24, 24, 60, 0, 0, 0],
50
+ "J": [0, 0, 30, 6, 6, 6, 6, 6, 102, 60, 0, 0, 0],
51
+ "K": [0, 0, 102, 108, 120, 112, 120, 108, 102, 102, 0, 0, 0],
52
+ "L": [0, 0, 96, 96, 96, 96, 96, 96, 96, 126, 0, 0, 0],
53
+ "M": [0, 0, 66, 102, 126, 126, 90, 66, 66, 66, 0, 0, 0],
54
+ "N": [0, 0, 98, 114, 122, 110, 102, 102, 102, 102, 0, 0, 0],
55
+ "O": [0, 0, 60, 102, 102, 102, 102, 102, 102, 60, 0, 0, 0],
56
+ "P": [0, 0, 124, 102, 102, 102, 124, 96, 96, 96, 0, 0, 0],
57
+ "Q": [0, 0, 60, 102, 102, 102, 102, 118, 108, 54, 0, 0, 0],
58
+ "R": [0, 0, 124, 102, 102, 124, 120, 108, 102, 102, 0, 0, 0],
59
+ "S": [0, 0, 60, 102, 96, 56, 12, 6, 102, 60, 0, 0, 0],
60
+ "T": [0, 0, 126, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0],
61
+ "U": [0, 0, 102, 102, 102, 102, 102, 102, 102, 60, 0, 0, 0],
62
+ "V": [0, 0, 102, 102, 102, 102, 102, 60, 24, 24, 0, 0, 0],
63
+ "W": [0, 0, 66, 66, 66, 90, 90, 126, 102, 66, 0, 0, 0],
64
+ "X": [0, 0, 102, 102, 60, 24, 60, 102, 102, 102, 0, 0, 0],
65
+ "Y": [0, 0, 102, 102, 102, 60, 24, 24, 24, 24, 0, 0, 0],
66
+ "Z": [0, 0, 126, 6, 12, 24, 48, 96, 96, 126, 0, 0, 0],
67
+ // ─── Lowercase a–z ───────────────────────────────────────────────────────
68
+ // Baseline row = index 9 (row 10). Descenders use indices 10-11.
69
+ "a": [0, 0, 0, 0, 60, 6, 62, 102, 102, 62, 0, 0, 0],
70
+ "b": [0, 0, 96, 96, 124, 102, 102, 102, 102, 124, 0, 0, 0],
71
+ "c": [0, 0, 0, 0, 60, 102, 96, 96, 102, 60, 0, 0, 0],
72
+ "d": [0, 0, 6, 6, 62, 102, 102, 102, 102, 62, 0, 0, 0],
73
+ "e": [0, 0, 0, 0, 60, 102, 126, 96, 102, 60, 0, 0, 0],
74
+ "f": [0, 0, 14, 24, 24, 126, 24, 24, 24, 24, 0, 0, 0],
75
+ "g": [0, 0, 0, 0, 62, 102, 102, 102, 62, 6, 6, 60, 0],
76
+ "h": [0, 0, 96, 96, 124, 102, 102, 102, 102, 102, 0, 0, 0],
77
+ "i": [0, 0, 24, 0, 56, 24, 24, 24, 24, 60, 0, 0, 0],
78
+ "j": [0, 0, 6, 0, 14, 6, 6, 6, 6, 6, 70, 60, 0],
79
+ "k": [0, 0, 96, 96, 102, 108, 120, 124, 108, 102, 0, 0, 0],
80
+ "l": [0, 0, 56, 24, 24, 24, 24, 24, 24, 14, 0, 0, 0],
81
+ "m": [0, 0, 0, 0, 108, 126, 126, 106, 98, 98, 0, 0, 0],
82
+ "n": [0, 0, 0, 0, 124, 102, 102, 102, 102, 102, 0, 0, 0],
83
+ "o": [0, 0, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0, 0],
84
+ "p": [0, 0, 0, 0, 124, 102, 102, 102, 124, 96, 96, 96, 0],
85
+ "q": [0, 0, 0, 0, 62, 102, 102, 102, 62, 6, 6, 6, 0],
86
+ "r": [0, 0, 0, 0, 108, 118, 96, 96, 96, 96, 0, 0, 0],
87
+ "s": [0, 0, 0, 0, 60, 102, 56, 12, 102, 60, 0, 0, 0],
88
+ "t": [0, 0, 24, 24, 126, 24, 24, 24, 24, 14, 0, 0, 0],
89
+ "u": [0, 0, 0, 0, 102, 102, 102, 102, 102, 62, 0, 0, 0],
90
+ "v": [0, 0, 0, 0, 102, 102, 102, 60, 60, 24, 0, 0, 0],
91
+ "w": [0, 0, 0, 0, 66, 66, 90, 90, 126, 36, 0, 0, 0],
92
+ "x": [0, 0, 0, 0, 102, 102, 60, 60, 102, 102, 0, 0, 0],
93
+ "y": [0, 0, 0, 0, 102, 102, 102, 62, 6, 6, 70, 60, 0],
94
+ "z": [0, 0, 0, 0, 126, 12, 24, 48, 96, 126, 0, 0, 0],
95
+ // ─── Punctuation ─────────────────────────────────────────────────────────
96
+ ".": [0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0],
97
+ ",": [0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 8, 16, 0],
98
+ ":": [0, 0, 0, 0, 24, 24, 0, 0, 24, 24, 0, 0, 0],
99
+ ";": [0, 0, 0, 0, 24, 24, 0, 0, 24, 24, 8, 16, 0],
100
+ "!": [0, 0, 24, 24, 24, 24, 24, 24, 0, 24, 0, 0, 0],
101
+ "?": [0, 0, 60, 102, 6, 12, 24, 24, 0, 24, 0, 0, 0],
102
+ "-": [0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0],
103
+ "+": [0, 0, 0, 0, 24, 24, 126, 24, 24, 0, 0, 0, 0],
104
+ "=": [0, 0, 0, 0, 0, 126, 0, 126, 0, 0, 0, 0, 0],
105
+ "(": [0, 0, 12, 24, 48, 48, 48, 48, 24, 12, 0, 0, 0],
106
+ ")": [0, 0, 48, 24, 12, 12, 12, 12, 24, 48, 0, 0, 0],
107
+ "/": [0, 0, 2, 6, 12, 24, 48, 96, 64, 0, 0, 0, 0],
108
+ "\\": [0, 0, 64, 96, 48, 24, 12, 6, 2, 0, 0, 0, 0],
109
+ "'": [0, 24, 24, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0],
110
+ '"': [0, 102, 102, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0],
111
+ "_": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0],
112
+ "@": [0, 0, 60, 102, 110, 106, 110, 96, 98, 60, 0, 0, 0],
113
+ "#": [0, 0, 36, 36, 126, 36, 36, 126, 36, 36, 0, 0, 0],
114
+ "&": [0, 0, 56, 108, 108, 56, 118, 206, 204, 118, 0, 0, 0],
115
+ "%": [0, 0, 98, 102, 12, 24, 48, 102, 70, 0, 0, 0, 0],
116
+ "*": [0, 0, 0, 102, 60, 255, 60, 102, 0, 0, 0, 0, 0],
117
+ "<": [0, 0, 0, 6, 28, 112, 112, 28, 6, 0, 0, 0, 0],
118
+ ">": [0, 0, 0, 96, 56, 14, 14, 56, 96, 0, 0, 0, 0],
119
+ "[": [0, 0, 60, 48, 48, 48, 48, 48, 48, 60, 0, 0, 0],
120
+ "]": [0, 0, 60, 12, 12, 12, 12, 12, 12, 60, 0, 0, 0],
121
+ "{": [0, 0, 14, 24, 24, 48, 24, 24, 24, 14, 0, 0, 0],
122
+ "}": [0, 0, 112, 24, 24, 12, 24, 24, 24, 112, 0, 0, 0],
123
+ "|": [0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0],
124
+ "~": [0, 0, 0, 0, 0, 114, 156, 0, 0, 0, 0, 0, 0],
125
+ "^": [0, 24, 60, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0],
126
+ "`": [0, 24, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0],
127
+ // ─── German characters ────────────────────────────────────────────────────
128
+ // Umlauts: dots sit at rows 0-1, letter body follows below
129
+ "\xE4": [0, 36, 0, 0, 60, 6, 62, 102, 102, 62, 0, 0, 0],
130
+ "\xF6": [0, 36, 0, 0, 60, 102, 102, 102, 102, 60, 0, 0, 0],
131
+ "\xFC": [0, 36, 0, 0, 102, 102, 102, 102, 102, 62, 0, 0, 0],
132
+ "\xC4": [36, 0, 24, 60, 102, 102, 126, 102, 102, 102, 0, 0, 0],
133
+ "\xD6": [36, 0, 60, 102, 102, 102, 102, 102, 102, 60, 0, 0, 0],
134
+ "\xDC": [36, 0, 102, 102, 102, 102, 102, 102, 102, 60, 0, 0, 0],
135
+ // ß: sharp-s / eszett
136
+ "\xDF": [0, 0, 60, 102, 102, 124, 102, 102, 102, 124, 96, 96, 0],
137
+ // ─── Currency / special symbols ──────────────────────────────────────────
138
+ // € (Euro): slightly narrower than full width, classic double-bar C shape
139
+ "\u20AC": [0, 0, 30, 48, 124, 48, 124, 48, 48, 30, 0, 0, 0]
140
+ };
141
+ // Annotate the CommonJS export names for ESM import in node:
142
+ 0 && (module.exports = {
143
+ FONT_8X13
144
+ });
145
+ //# sourceMappingURL=font-8x13.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/font-8x13.ts"],"sourcesContent":["// 8x13 Bitmap Font\r\n// Based on the classic X11/IBM VGA 8x13 bitmap font style.\r\n// Each character is 8 pixels wide and 13 pixels tall.\r\n// Each glyph is an array of 13 bytes; each byte represents one row (MSB = leftmost pixel).\r\n// Baseline is at row 10 (index 9). Rows 11-12 (indices 10-12) are used for descenders.\r\n\r\nexport const FONT_8X13: Record<string, number[]> = {\r\n // ─── Space ───────────────────────────────────────────────────────────────\r\n \" \": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n\r\n // ─── Digits ──────────────────────────────────────────────────────────────\r\n \"0\": [0x00, 0x00, 0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"1\": [0x00, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00],\r\n \"2\": [0x00, 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, 0x00, 0x00],\r\n \"3\": [0x00, 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"4\": [0x00, 0x00, 0x0C, 0x1C, 0x2C, 0x4C, 0x7E, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00],\r\n \"5\": [0x00, 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"6\": [0x00, 0x00, 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"7\": [0x00, 0x00, 0x7E, 0x06, 0x0C, 0x18, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00],\r\n \"8\": [0x00, 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"9\": [0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00, 0x00, 0x00],\r\n\r\n // ─── Uppercase A–Z ───────────────────────────────────────────────────────\r\n \"A\": [0x00, 0x00, 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"B\": [0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00],\r\n \"C\": [0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"D\": [0x00, 0x00, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, 0x00, 0x00],\r\n \"E\": [0x00, 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x7E, 0x00, 0x00, 0x00],\r\n \"F\": [0x00, 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00],\r\n \"G\": [0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x6E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"H\": [0x00, 0x00, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"I\": [0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00],\r\n \"J\": [0x00, 0x00, 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"K\": [0x00, 0x00, 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"L\": [0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, 0x00, 0x00],\r\n \"M\": [0x00, 0x00, 0x42, 0x66, 0x7E, 0x7E, 0x5A, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00],\r\n \"N\": [0x00, 0x00, 0x62, 0x72, 0x7A, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"O\": [0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"P\": [0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00],\r\n \"Q\": [0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x76, 0x6C, 0x36, 0x00, 0x00, 0x00],\r\n \"R\": [0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"S\": [0x00, 0x00, 0x3C, 0x66, 0x60, 0x38, 0x0C, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"T\": [0x00, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \"U\": [0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"V\": [0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \"W\": [0x00, 0x00, 0x42, 0x42, 0x42, 0x5A, 0x5A, 0x7E, 0x66, 0x42, 0x00, 0x00, 0x00],\r\n \"X\": [0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"Y\": [0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \"Z\": [0x00, 0x00, 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x7E, 0x00, 0x00, 0x00],\r\n\r\n // ─── Lowercase a–z ───────────────────────────────────────────────────────\r\n // Baseline row = index 9 (row 10). Descenders use indices 10-11.\r\n \"a\": [0x00, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"b\": [0x00, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00],\r\n \"c\": [0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"d\": [0x00, 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"e\": [0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"f\": [0x00, 0x00, 0x0E, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \"g\": [0x00, 0x00, 0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x3C, 0x00],\r\n \"h\": [0x00, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"i\": [0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00],\r\n \"j\": [0x00, 0x00, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x3C, 0x00],\r\n \"k\": [0x00, 0x00, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x7C, 0x6C, 0x66, 0x00, 0x00, 0x00],\r\n \"l\": [0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00],\r\n \"m\": [0x00, 0x00, 0x00, 0x00, 0x6C, 0x7E, 0x7E, 0x6A, 0x62, 0x62, 0x00, 0x00, 0x00],\r\n \"n\": [0x00, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"o\": [0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"p\": [0x00, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00],\r\n \"q\": [0x00, 0x00, 0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00],\r\n \"r\": [0x00, 0x00, 0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00],\r\n \"s\": [0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x38, 0x0C, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"t\": [0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00],\r\n \"u\": [0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"v\": [0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00],\r\n \"w\": [0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x5A, 0x5A, 0x7E, 0x24, 0x00, 0x00, 0x00],\r\n \"x\": [0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"y\": [0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x46, 0x3C, 0x00],\r\n \"z\": [0x00, 0x00, 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, 0x00, 0x00],\r\n\r\n // ─── Punctuation ─────────────────────────────────────────────────────────\r\n \".\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \",\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00],\r\n \":\": [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \";\": [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00],\r\n \"!\": [0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00],\r\n \"?\": [0x00, 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00],\r\n \"-\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"+\": [0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00],\r\n \"=\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"(\": [0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00],\r\n \")\": [0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00],\r\n \"/\": [0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00],\r\n \"\\\\\": [0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00],\r\n \"'\": [0x00, 0x18, 0x18, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"\\\"\": [0x00, 0x66, 0x66, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"_\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00],\r\n \"@\": [0x00, 0x00, 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x62, 0x3C, 0x00, 0x00, 0x00],\r\n \"#\": [0x00, 0x00, 0x24, 0x24, 0x7E, 0x24, 0x24, 0x7E, 0x24, 0x24, 0x00, 0x00, 0x00],\r\n \"&\": [0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xCE, 0xCC, 0x76, 0x00, 0x00, 0x00],\r\n \"%\": [0x00, 0x00, 0x62, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x46, 0x00, 0x00, 0x00, 0x00],\r\n \"*\": [0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"<\": [0x00, 0x00, 0x00, 0x06, 0x1C, 0x70, 0x70, 0x1C, 0x06, 0x00, 0x00, 0x00, 0x00],\r\n \">\": [0x00, 0x00, 0x00, 0x60, 0x38, 0x0E, 0x0E, 0x38, 0x60, 0x00, 0x00, 0x00, 0x00],\r\n \"[\": [0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00],\r\n \"]\": [0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00],\r\n \"{\": [0x00, 0x00, 0x0E, 0x18, 0x18, 0x30, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00],\r\n \"}\": [0x00, 0x00, 0x70, 0x18, 0x18, 0x0C, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00],\r\n \"|\": [0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00],\r\n \"~\": [0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"^\": [0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n \"`\": [0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\r\n\r\n // ─── German characters ────────────────────────────────────────────────────\r\n // Umlauts: dots sit at rows 0-1, letter body follows below\r\n \"ä\": [0x00, 0x24, 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"ö\": [0x00, 0x24, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"ü\": [0x00, 0x24, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00],\r\n \"Ä\": [0x24, 0x00, 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00],\r\n \"Ö\": [0x24, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n \"Ü\": [0x24, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00],\r\n // ß: sharp-s / eszett\r\n \"ß\": [0x00, 0x00, 0x3C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x00],\r\n\r\n // ─── Currency / special symbols ──────────────────────────────────────────\r\n // € (Euro): slightly narrower than full width, classic double-bar C shape\r\n \"€\": [0x00, 0x00, 0x1E, 0x30, 0x7C, 0x30, 0x7C, 0x30, 0x30, 0x1E, 0x00, 0x00, 0x00],\r\n};\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,IAAM,YAAsC;AAAA;AAAA,EAEjD,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA;AAAA,EAGnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,GAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,GAAM,IAAM,GAAM,GAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,IAAM,IAAM,KAAM,GAAM,GAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,IAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,IAAM,GAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA;AAAA,EAGnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,IAAM,IAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,IAAM,IAAM,KAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,IAAM,IAAM,KAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,IAAM,GAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,IAAM,IAAM,IAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA;AAAA;AAAA,EAInF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,GAAM,IAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,IAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,KAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,IAAM,IAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,IAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,KAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA;AAAA,EAGnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,GAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,GAAM,GAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,GAAM,GAAM,IAAM,IAAM,GAAM,IAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,GAAM,IAAM,IAAM,IAAM,GAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,KAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,KAAM,IAAM,IAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,KAAM,GAAM,KAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,MAAO,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACpF,KAAM,CAAC,GAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,KAAM,KAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,KAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,IAAM,IAAM,KAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,IAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,KAAM,IAAM,IAAM,IAAM,KAAM,IAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,KAAM,IAAM,KAAM,IAAM,KAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,IAAM,KAAM,KAAM,IAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,GAAM,GAAM,GAAM,GAAM,KAAM,KAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,IAAM,IAAM,KAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA,EACnF,KAAM,CAAC,GAAM,IAAM,IAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,CAAI;AAAA;AAAA;AAAA,EAInF,QAAM,CAAC,GAAM,IAAM,GAAM,GAAM,IAAM,GAAM,IAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,QAAM,CAAC,GAAM,IAAM,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,QAAM,CAAC,GAAM,IAAM,GAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,QAAM,CAAC,IAAM,GAAM,IAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,GAAM,GAAM,CAAI;AAAA,EACnF,QAAM,CAAC,IAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA,EACnF,QAAM,CAAC,IAAM,GAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,GAAM,GAAM,CAAI;AAAA;AAAA,EAEnF,QAAM,CAAC,GAAM,GAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAM,IAAM,CAAI;AAAA;AAAA;AAAA,EAInF,UAAM,CAAC,GAAM,GAAM,IAAM,IAAM,KAAM,IAAM,KAAM,IAAM,IAAM,IAAM,GAAM,GAAM,CAAI;AACrF;","names":[]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * AES-256-CBC decryption for Signotec signature point data.
3
+ *
4
+ * The Sigma pad encrypts all signature coordinates using AES-256-CBC.
5
+ * The pad uses the static default key (KAESDEFKEY) without key exchange.
6
+ *
7
+ * Decrypted 16-byte block format (verified from real device capture):
8
+ * Offset 0: uint32 LE - timestamp (sequential counter)
9
+ * Offset 4: uint16 LE - X coordinate (sensor units, ~0-4096)
10
+ * Offset 6: uint16 LE - Y coordinate (sensor units, ~0-4096)
11
+ * Offset 8: uint16 LE - pressure (0xFFFF = pen up)
12
+ * Offset 10: uint16 LE - extra data (pad-specific flags)
13
+ * Offset 12: uint32 LE - padding/extra
14
+ *
15
+ * CBC IV starts as all zeros and chains with each block's ciphertext.
16
+ */
17
+ interface DecryptedPoint {
18
+ x: number;
19
+ y: number;
20
+ pressure: number;
21
+ timestamp: number;
22
+ penUp: boolean;
23
+ }
24
+ /**
25
+ * Manages AES-256-CBC decryption state for a signature session.
26
+ * Each session starts with IV = all zeros and chains through all blocks.
27
+ */
28
+ declare class SignatureDecryptor {
29
+ private key;
30
+ private iv;
31
+ constructor(key?: Buffer);
32
+ /**
33
+ * Create a decryptor using the static default key.
34
+ * This works for Sigma USB pads (verified).
35
+ */
36
+ static withDefaultKey(): SignatureDecryptor;
37
+ /**
38
+ * Reset the CBC IV to all zeros (for retry/new signature session).
39
+ */
40
+ resetIv(): void;
41
+ /**
42
+ * Decrypt a single 16-byte AES block from a 0x41 HID event.
43
+ * The ciphertext is at bytes 4-19 of the HID report.
44
+ *
45
+ * Implements AES-256-CBC manually:
46
+ * 1. ECB decrypt the block
47
+ * 2. XOR with previous IV
48
+ * 3. Update IV to current ciphertext
49
+ */
50
+ decryptBlock(ciphertext: Buffer): DecryptedPoint | null;
51
+ /**
52
+ * Decrypt a point from a raw 0x41 HID event buffer.
53
+ * Extracts the 16-byte ciphertext from bytes 4-19.
54
+ */
55
+ decryptEvent(eventData: Buffer): DecryptedPoint | null;
56
+ }
57
+
58
+ export { type DecryptedPoint, SignatureDecryptor };
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/hid-crypto.ts
31
+ var hid_crypto_exports = {};
32
+ __export(hid_crypto_exports, {
33
+ SignatureDecryptor: () => SignatureDecryptor
34
+ });
35
+ module.exports = __toCommonJS(hid_crypto_exports);
36
+ var import_crypto = __toESM(require("crypto"));
37
+ var KAESDEFKEY = Buffer.from([
38
+ 38,
39
+ 212,
40
+ 165,
41
+ 168,
42
+ 144,
43
+ 1,
44
+ 171,
45
+ 19,
46
+ 127,
47
+ 113,
48
+ 49,
49
+ 81,
50
+ 217,
51
+ 47,
52
+ 207,
53
+ 31,
54
+ 17,
55
+ 135,
56
+ 134,
57
+ 22,
58
+ 78,
59
+ 129,
60
+ 183,
61
+ 148,
62
+ 45,
63
+ 142,
64
+ 223,
65
+ 210,
66
+ 218,
67
+ 6,
68
+ 36,
69
+ 245
70
+ ]);
71
+ var PEN_UP_PRESSURE = 65535;
72
+ var SignatureDecryptor = class _SignatureDecryptor {
73
+ constructor(key) {
74
+ this.key = Buffer.from(key || KAESDEFKEY);
75
+ this.iv = Buffer.alloc(16, 0);
76
+ }
77
+ /**
78
+ * Create a decryptor using the static default key.
79
+ * This works for Sigma USB pads (verified).
80
+ */
81
+ static withDefaultKey() {
82
+ return new _SignatureDecryptor();
83
+ }
84
+ /**
85
+ * Reset the CBC IV to all zeros (for retry/new signature session).
86
+ */
87
+ resetIv() {
88
+ this.iv = Buffer.alloc(16, 0);
89
+ }
90
+ /**
91
+ * Decrypt a single 16-byte AES block from a 0x41 HID event.
92
+ * The ciphertext is at bytes 4-19 of the HID report.
93
+ *
94
+ * Implements AES-256-CBC manually:
95
+ * 1. ECB decrypt the block
96
+ * 2. XOR with previous IV
97
+ * 3. Update IV to current ciphertext
98
+ */
99
+ decryptBlock(ciphertext) {
100
+ if (ciphertext.length < 16) return null;
101
+ try {
102
+ const block = ciphertext.slice(0, 16);
103
+ const decipher = import_crypto.default.createDecipheriv("aes-256-ecb", this.key, null);
104
+ decipher.setAutoPadding(false);
105
+ const decrypted = Buffer.concat([decipher.update(block), decipher.final()]);
106
+ for (let i = 0; i < 16; i++) {
107
+ decrypted[i] ^= this.iv[i];
108
+ }
109
+ block.copy(this.iv, 0, 0, 16);
110
+ const timestamp = decrypted.readUInt32LE(0);
111
+ const x = decrypted.readUInt16LE(4);
112
+ const y = decrypted.readUInt16LE(6);
113
+ const pressure = decrypted.readUInt16LE(8);
114
+ return {
115
+ timestamp,
116
+ x,
117
+ y,
118
+ pressure,
119
+ penUp: pressure === PEN_UP_PRESSURE
120
+ };
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * Decrypt a point from a raw 0x41 HID event buffer.
127
+ * Extracts the 16-byte ciphertext from bytes 4-19.
128
+ */
129
+ decryptEvent(eventData) {
130
+ if (eventData.length < 20) return null;
131
+ return this.decryptBlock(eventData.slice(4, 20));
132
+ }
133
+ };
134
+ // Annotate the CommonJS export names for ESM import in node:
135
+ 0 && (module.exports = {
136
+ SignatureDecryptor
137
+ });
138
+ //# sourceMappingURL=hid-crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hid-crypto.ts"],"sourcesContent":["/**\r\n * AES-256-CBC decryption for Signotec signature point data.\r\n *\r\n * The Sigma pad encrypts all signature coordinates using AES-256-CBC.\r\n * The pad uses the static default key (KAESDEFKEY) without key exchange.\r\n *\r\n * Decrypted 16-byte block format (verified from real device capture):\r\n * Offset 0: uint32 LE - timestamp (sequential counter)\r\n * Offset 4: uint16 LE - X coordinate (sensor units, ~0-4096)\r\n * Offset 6: uint16 LE - Y coordinate (sensor units, ~0-4096)\r\n * Offset 8: uint16 LE - pressure (0xFFFF = pen up)\r\n * Offset 10: uint16 LE - extra data (pad-specific flags)\r\n * Offset 12: uint32 LE - padding/extra\r\n *\r\n * CBC IV starts as all zeros and chains with each block's ciphertext.\r\n */\r\n\r\nimport crypto from \"crypto\";\r\n\r\n// Static AES-256 key from the Signotec library (kaesdefkey, 32 bytes)\r\n// Verified to work directly on Sigma USB pads without key exchange\r\nconst KAESDEFKEY = Buffer.from([\r\n 0x26, 0xd4, 0xa5, 0xa8, 0x90, 0x01, 0xab, 0x13,\r\n 0x7f, 0x71, 0x31, 0x51, 0xd9, 0x2f, 0xcf, 0x1f,\r\n 0x11, 0x87, 0x86, 0x16, 0x4e, 0x81, 0xb7, 0x94,\r\n 0x2d, 0x8e, 0xdf, 0xd2, 0xda, 0x06, 0x24, 0xf5,\r\n]);\r\n\r\n// Pen-up pressure sentinel value\r\nconst PEN_UP_PRESSURE = 0xFFFF;\r\n\r\nexport interface DecryptedPoint {\r\n x: number;\r\n y: number;\r\n pressure: number;\r\n timestamp: number;\r\n penUp: boolean;\r\n}\r\n\r\n/**\r\n * Manages AES-256-CBC decryption state for a signature session.\r\n * Each session starts with IV = all zeros and chains through all blocks.\r\n */\r\nexport class SignatureDecryptor {\r\n private key: Buffer;\r\n private iv: Buffer;\r\n\r\n constructor(key?: Buffer) {\r\n this.key = Buffer.from(key || KAESDEFKEY);\r\n this.iv = Buffer.alloc(16, 0);\r\n }\r\n\r\n /**\r\n * Create a decryptor using the static default key.\r\n * This works for Sigma USB pads (verified).\r\n */\r\n static withDefaultKey(): SignatureDecryptor {\r\n return new SignatureDecryptor();\r\n }\r\n\r\n /**\r\n * Reset the CBC IV to all zeros (for retry/new signature session).\r\n */\r\n resetIv(): void {\r\n this.iv = Buffer.alloc(16, 0);\r\n }\r\n\r\n /**\r\n * Decrypt a single 16-byte AES block from a 0x41 HID event.\r\n * The ciphertext is at bytes 4-19 of the HID report.\r\n *\r\n * Implements AES-256-CBC manually:\r\n * 1. ECB decrypt the block\r\n * 2. XOR with previous IV\r\n * 3. Update IV to current ciphertext\r\n */\r\n decryptBlock(ciphertext: Buffer): DecryptedPoint | null {\r\n if (ciphertext.length < 16) return null;\r\n\r\n try {\r\n const block = ciphertext.slice(0, 16);\r\n\r\n // AES-256-ECB decrypt (single block, no padding)\r\n const decipher = crypto.createDecipheriv(\"aes-256-ecb\", this.key, null);\r\n decipher.setAutoPadding(false);\r\n const decrypted = Buffer.concat([decipher.update(block), decipher.final()]);\r\n\r\n // CBC: XOR with IV\r\n for (let i = 0; i < 16; i++) {\r\n decrypted[i] ^= this.iv[i];\r\n }\r\n\r\n // Update IV for next block (standard CBC chaining)\r\n block.copy(this.iv, 0, 0, 16);\r\n\r\n // Parse the decrypted data\r\n const timestamp = decrypted.readUInt32LE(0);\r\n const x = decrypted.readUInt16LE(4);\r\n const y = decrypted.readUInt16LE(6);\r\n const pressure = decrypted.readUInt16LE(8);\r\n\r\n return {\r\n timestamp,\r\n x,\r\n y,\r\n pressure,\r\n penUp: pressure === PEN_UP_PRESSURE,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Decrypt a point from a raw 0x41 HID event buffer.\r\n * Extracts the 16-byte ciphertext from bytes 4-19.\r\n */\r\n decryptEvent(eventData: Buffer): DecryptedPoint | null {\r\n if (eventData.length < 20) return null;\r\n return this.decryptBlock(eventData.slice(4, 20));\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,oBAAmB;AAInB,IAAM,aAAa,OAAO,KAAK;AAAA,EAC7B;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1C;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1C;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1C;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAC5C,CAAC;AAGD,IAAM,kBAAkB;AAcjB,IAAM,qBAAN,MAAM,oBAAmB;AAAA,EAI9B,YAAY,KAAc;AACxB,SAAK,MAAM,OAAO,KAAK,OAAO,UAAU;AACxC,SAAK,KAAK,OAAO,MAAM,IAAI,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,iBAAqC;AAC1C,WAAO,IAAI,oBAAmB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,KAAK,OAAO,MAAM,IAAI,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,YAA2C;AACtD,QAAI,WAAW,SAAS,GAAI,QAAO;AAEnC,QAAI;AACF,YAAM,QAAQ,WAAW,MAAM,GAAG,EAAE;AAGpC,YAAM,WAAW,cAAAA,QAAO,iBAAiB,eAAe,KAAK,KAAK,IAAI;AACtE,eAAS,eAAe,KAAK;AAC7B,YAAM,YAAY,OAAO,OAAO,CAAC,SAAS,OAAO,KAAK,GAAG,SAAS,MAAM,CAAC,CAAC;AAG1E,eAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,kBAAU,CAAC,KAAK,KAAK,GAAG,CAAC;AAAA,MAC3B;AAGA,YAAM,KAAK,KAAK,IAAI,GAAG,GAAG,EAAE;AAG5B,YAAM,YAAY,UAAU,aAAa,CAAC;AAC1C,YAAM,IAAI,UAAU,aAAa,CAAC;AAClC,YAAM,IAAI,UAAU,aAAa,CAAC;AAClC,YAAM,WAAW,UAAU,aAAa,CAAC;AAEzC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,aAAa;AAAA,MACtB;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,WAA0C;AACrD,QAAI,UAAU,SAAS,GAAI,QAAO;AAClC,WAAO,KAAK,aAAa,UAAU,MAAM,GAAG,EAAE,CAAC;AAAA,EACjD;AACF;","names":["crypto"]}
@@ -0,0 +1,78 @@
1
+ import { HidProtocol } from './hid-protocol.js';
2
+ import './types.js';
3
+
4
+ /**
5
+ * Display rendering for Signotec pads via HID.
6
+ * Renders text and images into monochrome bitmaps, then sends them to the pad.
7
+ *
8
+ * The Signotec pad does NOT accept text commands directly.
9
+ * Text is rendered client-side into bitmaps, then transferred as image data.
10
+ */
11
+
12
+ /** Returns the line height (char height + gap) for a fontSize. */
13
+ declare function fontLineHeight(fontSize: number): number;
14
+ /** Returns the character width (including 1px gap) for a fontSize. */
15
+ declare function fontCharWidth(fontSize: number): number;
16
+ /**
17
+ * Render text into a 1bpp monochrome bitmap suitable for the pad display.
18
+ * Uses a built-in bitmap font (no canvas dependency).
19
+ */
20
+ declare class DisplayRenderer {
21
+ private width;
22
+ private height;
23
+ private framebuffer;
24
+ constructor(width: number, height: number);
25
+ get buffer(): Buffer;
26
+ clear(): void;
27
+ /**
28
+ * Set a pixel (0=black, 1=white) in the framebuffer.
29
+ */
30
+ setPixel(x: number, y: number, black: boolean): void;
31
+ /**
32
+ * Draw a filled rectangle.
33
+ */
34
+ fillRect(x: number, y: number, w: number, h: number, black: boolean): void;
35
+ /**
36
+ * Draw a horizontal line.
37
+ */
38
+ hLine(x: number, y: number, w: number): void;
39
+ /**
40
+ * Draw text using the 8x13 bitmap font.
41
+ * fontSize: 1=normal(8x13), 2=large(16x26), 3=headline(24x39)
42
+ * bold: draws text twice with 1px right shift for thicker strokes
43
+ */
44
+ drawText(x: number, y: number, text: string, fontSize?: number, bold?: boolean): number;
45
+ /** Draw inverted text (white on black) for button labels. */
46
+ drawTextInverted(x: number, y: number, text: string, fontSize?: number, bold?: boolean): number;
47
+ private _renderText;
48
+ /**
49
+ * Draw text fitted within a rectangle. Wraps words and scales to fit.
50
+ */
51
+ drawTextInRect(left: number, top: number, width: number, height: number, text: string, fontSize?: number): void;
52
+ /**
53
+ * Load a BMP file and draw it at the specified position.
54
+ * Supports 1-bit, 8-bit, and 24-bit BMPs.
55
+ */
56
+ drawBmpFile(x: number, y: number, filePath: string): boolean;
57
+ /**
58
+ * Load a PNG file and draw it at the specified position.
59
+ * Uses a minimal PNG decoder (no external dependencies).
60
+ */
61
+ drawPngFile(x: number, y: number, filePath: string): boolean;
62
+ /**
63
+ * Draw image data. Detects format from header.
64
+ */
65
+ drawImageData(x: number, y: number, data: Buffer, hint?: string): boolean;
66
+ private drawBmpData;
67
+ private drawPngData;
68
+ /**
69
+ * Send the entire framebuffer to the pad.
70
+ */
71
+ sendToDevice(protocol: HidProtocol): Promise<boolean>;
72
+ /**
73
+ * Send a region of the framebuffer to the pad.
74
+ */
75
+ sendRegionToDevice(protocol: HidProtocol, x: number, y: number, w: number, h: number): Promise<boolean>;
76
+ }
77
+
78
+ export { DisplayRenderer, fontCharWidth, fontLineHeight };