nx_pwg_rle.nx source
↩ module page · 217 lines · 9546 B
1// nx_pwg_rle.nx -- the PackBits-like run-length codec shared by PWG-Raster AND URF (Apple Raster).
2// This is the pixel-data encoding of "driverless" printing -- the bytes a real IPP printer rasterizes.
3//
4// Verified against the AUTHORITATIVE CUPS/PWG raster spec (sovereign-fetched, cited:
5// knowledge/fetched/cups_raster_spec.raw, lines 483-501):
6// - Each LINE begins with a 1-byte line-repeat count = (repeats - 1): 0x00 = appears once, 0xFF = 256x.
7// - Within a line, whole pixels ("colors") are PackBits-encoded:
8// control 0x00..0x7F -> REPEATED run: (ctrl+1) copies of the ONE following pixel (count 1..128)
9// control 0x80..0xFF -> LITERAL run: (257-ctrl) following pixels verbatim (count 2..128)
10// - one pixel = bpp bytes (sgray_8 -> 1 byte; sRGB -> 3 bytes).
11// Cross-checked on the spec's worked example line
12// 00 FE FFFF00 0000FF FFFF00 02 FFFFFF 00 00FF00 00 FFFFFF
13// = yellow,blue,yellow, white,white,white, green, white (proves the decoder matches the spec).
14//
15// NEVER-BRICK (#26): pure byte arithmetic; NO syscalls, no hardware access. Sovereign (no imports).
16// no_silent_failure: the decoder bounds-checks every read/write and returns -1 on truncation/overrun.
17// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL
18
19// pixels at logical index i and j of `line` (each bpp bytes) equal?
20func nx_rle_px_eq(line: *u8, i: i64, j: i64, bpp: i64) -> i64 {
21 var k: i64 = 0
22 var eq: i64 = 1
23 while k < bpp {
24 if (line[i * bpp + k] as i64) != (line[j * bpp + k] as i64) { eq = 0; k = bpp }
25 else { k = k + 1 }
26 }
27 return eq
28}
29
30// whole-scanline ya == yb equal? (width pixels, bpp bytes each)
31func nx_rle_line_eq(bitmap: *u8, width: i64, bpp: i64, ya: i64, yb: i64) -> i64 {
32 let pa: i64 = ya * width * bpp
33 let pb: i64 = yb * width * bpp
34 var k: i64 = 0
35 let nbytes: i64 = width * bpp
36 var eq: i64 = 1
37 while k < nbytes {
38 if (bitmap[pa + k] as i64) != (bitmap[pb + k] as i64) { eq = 0; k = nbytes }
39 else { k = k + 1 }
40 }
41 return eq
42}
43
44// Encode ONE scanline (no line-repeat byte). Returns advanced out offset.
45func nx_rle_encode_line(line: *u8, width: i64, bpp: i64, out: *u8, off0: i64) -> i64 {
46 var off: i64 = off0
47 var i: i64 = 0
48 while i < width {
49 // longest run of identical pixels at i (cap 128)
50 var run: i64 = 1
51 var cont: i64 = 1
52 while cont == 1 {
53 if (i + run) >= width { cont = 0 }
54 else {
55 if run >= 128 { cont = 0 }
56 else {
57 if nx_rle_px_eq(line, i, i + run, bpp) == 1 { run = run + 1 }
58 else { cont = 0 }
59 }
60 }
61 }
62 if run >= 2 {
63 out[off] = (run - 1) as u8
64 off = off + 1
65 var k: i64 = 0
66 while k < bpp { out[off] = line[i * bpp + k]; off = off + 1; k = k + 1 }
67 i = i + run
68 } else {
69 // literal: gather pixels until a run>=2 begins or 128 collected
70 let lit_start: i64 = i
71 var litcount: i64 = 0
72 var lc: i64 = 1
73 while lc == 1 {
74 if i >= width { lc = 0 }
75 else {
76 if litcount >= 128 { lc = 0 }
77 else {
78 var same: i64 = 0
79 if (i + 1) < width { if nx_rle_px_eq(line, i, i + 1, bpp) == 1 { same = 1 } }
80 if same == 1 { lc = 0 }
81 else { litcount = litcount + 1; i = i + 1 }
82 }
83 }
84 }
85 if litcount == 1 {
86 out[off] = 0 as u8 // a lone pixel -> repeat-of-1 (literal min is 2)
87 off = off + 1
88 var k2: i64 = 0
89 while k2 < bpp { out[off] = line[lit_start * bpp + k2]; off = off + 1; k2 = k2 + 1 }
90 } else {
91 out[off] = (257 - litcount) as u8 // literal control 0x81..0xFF
92 off = off + 1
93 var p: i64 = 0
94 while p < litcount {
95 var k3: i64 = 0
96 while k3 < bpp { out[off] = line[(lit_start + p) * bpp + k3]; off = off + 1; k3 = k3 + 1 }
97 p = p + 1
98 }
99 }
100 }
101 }
102 return off
103}
104
105// Encode a full page (height scanlines), collapsing consecutive identical lines via the line-repeat byte.
106// Returns total encoded byte length written at out[0..].
107func nx_rle_encode_page(bitmap: *u8, width: i64, height: i64, bpp: i64, out: *u8) -> i64 {
108 var off: i64 = 0
109 var y: i64 = 0
110 while y < height {
111 var rep: i64 = 1
112 var c: i64 = 1
113 while c == 1 {
114 if (y + rep) >= height { c = 0 }
115 else {
116 if rep >= 256 { c = 0 }
117 else {
118 if nx_rle_line_eq(bitmap, width, bpp, y, y + rep) == 1 { rep = rep + 1 }
119 else { c = 0 }
120 }
121 }
122 }
123 out[off] = (rep - 1) as u8
124 off = off + 1
125 let lp: *u8 = ((bitmap as i64) + y * width * bpp) as *u8
126 off = nx_rle_encode_line(lp, width, bpp, out, off)
127 y = y + rep
128 }
129 return off
130}
131
132// Decode `height` lines of `width` pixels (bpp bytes each) from src[0..n) into out (capacity out_cap pixels).
133// Returns pixels decoded (= width*height) or -1 on any truncation/overrun (no_silent_failure).
134func nx_rle_decode(src: *u8, n: i64, width: i64, height: i64, bpp: i64, out: *u8, out_cap: i64) -> i64 {
135 var in_off: i64 = 0
136 var out_px: i64 = 0
137 var lines_done: i64 = 0
138 var err: i64 = 0
139 var keep: i64 = 1
140 while keep == 1 {
141 if lines_done >= height { keep = 0 }
142 else {
143 if in_off >= n { err = 1; keep = 0 }
144 else {
145 let LR: i64 = src[in_off] as i64
146 in_off = in_off + 1
147 let line_px0: i64 = out_px
148 var px: i64 = 0
149 var lk: i64 = 1
150 while lk == 1 {
151 if px >= width { lk = 0 }
152 else {
153 if in_off >= n { err = 1; lk = 0; keep = 0 }
154 else {
155 let ctrl: i64 = src[in_off] as i64
156 in_off = in_off + 1
157 if ctrl <= 127 {
158 let cnt: i64 = ctrl + 1
159 if (in_off + bpp) > n { err = 1; lk = 0; keep = 0 }
160 else {
161 var r: i64 = 0
162 while r < cnt {
163 if out_px >= out_cap { err = 1; r = cnt; lk = 0; keep = 0 }
164 else {
165 if px >= width { err = 1; r = cnt; lk = 0; keep = 0 }
166 else {
167 var k: i64 = 0
168 while k < bpp { out[out_px * bpp + k] = src[in_off + k]; k = k + 1 }
169 out_px = out_px + 1; px = px + 1; r = r + 1
170 }
171 }
172 }
173 in_off = in_off + bpp
174 }
175 } else {
176 let cnt2: i64 = 257 - ctrl
177 if (in_off + cnt2 * bpp) > n { err = 1; lk = 0; keep = 0 }
178 else {
179 var r2: i64 = 0
180 while r2 < cnt2 {
181 if out_px >= out_cap { err = 1; r2 = cnt2; lk = 0; keep = 0 }
182 else {
183 if px >= width { err = 1; r2 = cnt2; lk = 0; keep = 0 }
184 else {
185 var k2: i64 = 0
186 while k2 < bpp { out[out_px * bpp + k2] = src[in_off + k2]; k2 = k2 + 1 }
187 in_off = in_off + bpp; out_px = out_px + 1; px = px + 1; r2 = r2 + 1
188 }
189 }
190 }
191 }
192 }
193 }
194 }
195 }
196 if err == 0 {
197 if px != width { err = 1; keep = 0 }
198 else {
199 var rr: i64 = 0
200 while rr < LR {
201 if (out_px + width) > out_cap { err = 1; rr = LR; keep = 0 }
202 else {
203 var c2: i64 = 0
204 let nb: i64 = width * bpp
205 while c2 < nb { out[out_px * bpp + c2] = out[line_px0 * bpp + c2]; c2 = c2 + 1 }
206 out_px = out_px + width; rr = rr + 1
207 }
208 }
209 lines_done = lines_done + (LR + 1)
210 }
211 }
212 }
213 }
214 }
215 if err == 1 { return 0 - 1 }
216 return out_px
217}