FABRIC.md item 4.4t: confine REPL text rendering to the CANVAS box
vt100's TTF-mode text grid now operates within the per-arch 640x480 box (computed in 4.4o, pixel-verified in 4.4p) instead of the full framebuffer: box-origin offset in px_of()/py_of(), box-derived cols/rows (53x20) set before the 4.4q scrollback allocation depends on them, mode-aware erase_display()/reverse-index fill, and a new box-scoped fb_scroll_rect() alongside the existing whole-framebuffer fb_scroll_rows() (bitmap/boot mode unaffected either way). Also clears the full framebuffer once at the bitmap-to-TTF switch so leftover boot debris doesn't sit frozen outside the box now that erase_display(2) is box-scoped afterward. Three-arch QEMU boot + pixel-scanned screendumps confirm zero non-background pixels land outside the box on amd64, aarch64, and riscv64. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1f3ec3554e
commit
c92be2768f
@@ -305,3 +305,56 @@ void fb_scroll_rows(uint32_t char_rows, uint32_t bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fb_scroll_rect — box-confined scroll (FABRIC.md item 4.4t).
|
||||
*
|
||||
* Same non-volatile bulk-copy rationale as fb_scroll_rows() above, but
|
||||
* bounded to a caller-supplied rectangle instead of the whole framebuffer --
|
||||
* needed once REPL text is confined to the 4.4o CANVAS box, since a
|
||||
* whole-framebuffer scroll would drag pixels from outside the box (e.g. a
|
||||
* future 4.4r border) into the text area. Takes pixel_rows directly rather
|
||||
* than char_rows * a hardcoded cell height, since TTF mode's cell height
|
||||
* (24px) differs from bitmap mode's (16px * scale).
|
||||
*/
|
||||
void fb_scroll_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h,
|
||||
uint32_t pixel_rows, uint32_t bg)
|
||||
{
|
||||
uint32_t src_y, dst_y, px;
|
||||
uint32_t packed_bg;
|
||||
uint32_t *fb = (uint32_t *)(uintptr_t)g_fb.base;
|
||||
uint32_t x_end, y_end;
|
||||
|
||||
if (!g_fb.ready || pixel_rows == 0 || w == 0 || h == 0) return;
|
||||
|
||||
x_end = x + w;
|
||||
y_end = y + h;
|
||||
if (x_end > g_fb.width) x_end = g_fb.width;
|
||||
if (y_end > g_fb.height) y_end = g_fb.height;
|
||||
if (x >= x_end || y >= y_end) return;
|
||||
|
||||
if (pixel_rows >= (y_end - y)) {
|
||||
fb_fill_rect(x, y, x_end - x, y_end - y, bg);
|
||||
return;
|
||||
}
|
||||
|
||||
packed_bg = pack_pixel(bg);
|
||||
|
||||
/* Copy pixel rows upward, bounded to [x, x_end) */
|
||||
for (dst_y = y; dst_y + pixel_rows < y_end; dst_y++) {
|
||||
src_y = dst_y + pixel_rows;
|
||||
uint32_t *src = fb + src_y * g_fb.stride + x;
|
||||
uint32_t *dst = fb + dst_y * g_fb.stride + x;
|
||||
for (px = 0; px < (x_end - x); px++) {
|
||||
dst[px] = src[px];
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the newly exposed rows at the bottom of the rect */
|
||||
for (dst_y = y_end - pixel_rows; dst_y < y_end; dst_y++) {
|
||||
uint32_t *row = fb + dst_y * g_fb.stride + x;
|
||||
for (px = 0; px < (x_end - x); px++) {
|
||||
row[px] = packed_bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user