code wiki / (root) / nx_doc_layout.nx

nx_doc_layout.nx source

↩ module page · 101 lines · 4568 B

1// nx_doc_layout.nx -- document layout: text -> 8-bit GRAYSCALE page bitmap (front half of "print real 2// documents"). Distinct from nx_text_render (that targets the OS 1bpp framebuffer). Blits scaled 8x8 glyphs 3// from nx_font8x8's font8x8_table() with margins, monospace advance, right-margin wrap, and newline. 4// Output flows into nx_urf -> Print-Job -> printer. PURE (writes a caller bitmap) -> never-brick. Sovereign. 5// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL 6 7import "nx_font8x8.nx" 8 9// pointer to the 8-byte glyph for ch in the font8x8 table (0x20..0x7F; others -> space). 10func nx_doc_glyph(table: *u8, ch: i64) -> *u8 { 11 if ch < 32 { return table } 12 if ch > 127 { return table } 13 return ((table as i64) + (ch - 32) * 8) as *u8 14} 15 16// blit one 8x8 glyph scaled by `scale` into bm at top-left (gx,gy). set bits -> black (0x00). bounds-checked. 17func nx_doc_blit(bm: *u8, W: i64, H: i64, gx: i64, gy: i64, glyph: *u8, scale: i64) -> i64 { 18 var r: i64 = 0 19 while r < 8 { 20 let rowbits: i64 = glyph[r] as i64 21 var c: i64 = 0 22 while c < 8 { 23 if ((rowbits >> c) & 1) == 1 { 24 var dy: i64 = 0 25 while dy < scale { 26 let py: i64 = gy + r * scale + dy 27 if py >= 0 { if py < H { 28 var dx: i64 = 0 29 while dx < scale { 30 let px: i64 = gx + c * scale + dx 31 if px >= 0 { if px < W { bm[py * W + px] = 0 as u8 } } 32 dx = dx + 1 33 } 34 } } 35 dy = dy + 1 36 } 37 } 38 c = c + 1 39 } 40 r = r + 1 41 } 42 return 0 43} 44 45// Render NUL-terminated `text` into bm (caller pre-fills white 0xFF). Monospace, WORD-WRAP at the right 46// margin (whole words move to the next line; words wider than a line fall back to char-wrap), '\n' = new 47// line. Stops cleanly when the page fills, returning characters consumed so a caller can paginate (the next 48// page continues from text+consumed). This is the front half of multi-page document printing. 49func nx_doc_render(bm: *u8, W: i64, H: i64, table: *u8, text: *u8, scale: i64, 50 mleft: i64, mtop: i64, mright: i64, mbottom: i64, line_gap: i64) -> i64 { 51 let adv: i64 = 8 * scale 52 let lh: i64 = 8 * scale + line_gap 53 var x: i64 = mleft 54 var y: i64 = mtop 55 var i: i64 = 0 56 var stop: i64 = 0 57 while stop == 0 { 58 let ch: i64 = text[i] as i64 59 if ch == 0 { stop = 1 } 60 else { 61 if ch == 10 { // explicit newline 62 x = mleft 63 y = y + lh 64 i = i + 1 65 if (y + 8 * scale) > (H - mbottom) { stop = 1 } 66 } else { 67 if ch == 32 { // space: advance (collapse at line start) 68 if x > mleft { x = x + adv } 69 i = i + 1 70 } else { 71 // measure the word (run of non-space, non-newline) 72 var wl: i64 = 0 73 var k: i64 = i 74 var cont: i64 = 1 75 while cont == 1 { 76 let cc: i64 = text[k] as i64 77 if cc == 0 { cont = 0 } 78 else { if cc == 32 { cont = 0 } else { if cc == 10 { cont = 0 } else { wl = wl + 1; k = k + 1 } } } 79 } 80 // wrap the whole word to the next line if it won't fit and we're mid-line 81 if x > mleft { if (x + wl * adv) > (W - mright) { x = mleft; y = y + lh } } 82 if (y + 8 * scale) > (H - mbottom) { stop = 1 } // word moves to next page 83 else { 84 var w: i64 = 0 85 while w < wl { 86 if (x + adv) > (W - mright) { if x > mleft { x = mleft; y = y + lh } } // char-wrap (over-long word) 87 if (y + 8 * scale) > (H - mbottom) { stop = 1; w = wl } 88 else { 89 nx_doc_blit(bm, W, H, x, y, nx_doc_glyph(table, text[i] as i64), scale) 90 x = x + adv 91 i = i + 1 92 w = w + 1 93 } 94 } 95 } 96 } 97 } 98 } 99 } 100 return i 101}