font: the console draws outlines now, and a byte could not have held Ą
"Ą Ę Ś Ł Ż" drew as "?????" and the obvious diagnosis -- the font has no glyphs for them -- was wrong twice over. `struct vtcell.ch` was **one byte** holding a CP437 index, and the console mapped UTF-8 down to it on the way in. U+0104 does not fit in a byte. No font could have fixed that; the cell had to get wider first. So: `ch` is a uint32 codepoint, the mapping on the way in is gone, and the cell draws through kernel/dev/ttf.c against JetBrains Mono linked into the image. Cell size comes from the font's measured advance instead of a hardcoded 8x16. The grid costs 864 KB of BSS instead of 432 KB, which is the honest price of holding a codepoint per cell for six terminals at 240x75. The rasteriser needed three fixes before it could be trusted with this. **21 KB of locals on a 4 KB kernel stack.** `ttf_render` held an outline (512 points as three arrays) and a raster (1024 edges) as automatics. KSTACKSIZE is 4096. They walked off the bottom of the stack into whatever was underneath, which surfaced as user processes faulting on addresses they never touched and then a panic inside freevm() on an overwritten page directory. Nothing pointed anywhere near a font. **And then again, recursively.** load_outline() held a 4736-byte outline as a local *and recursed* for composite glyphs. Composite glyphs are exactly Ą, Ę, Ś, Ł, Ż -- so the second crash arrived the moment the first fix let Unicode reach the screen, looking like a fresh bug. Now a static outline per recursion level with a depth cap of 4 (the font's deepest real nesting is 2), and the leaf parse split into load_simple() so its 512-byte flag array is not multiplied by the depth. Worst chain measured from the object file: ~2.3 KB. Neither showed in tools/ttftest, which has an 8 MB stack. That is the standing hazard of one source file built for host and kernel: the host is most forgiving about exactly the resource the kernel is strictest about. **Component transforms were being skipped**, on the stated theory that a wrong transform is worse than none. It is not. `‘` in this font is the comma glyph with a scale of -1 -- a 180-degree rotation -- and the offset that ships with it only lands correctly after the rotation. Without it the mark went twelve pixels into a ten-pixel cell and was clipped away entirely, so the character read as missing from the font rather than as misplaced. F2Dot14 2x2 now, with SCALED_COMPONENT_OFFSET honoured. The glyph cache was ASCII-only, so every accented letter re-rasterised on every repaint: a screenful of Polish did hundreds of bezier flattenings per scroll where the same screenful of English did none. 95 reserved ASCII slots plus 224 shared slots keyed by codepoint, 64 KB pool. Verified 13680 cached renders byte-identical to direct ones across collisions and a pool flush. tools/ttftest speaks UTF-8 now. Iterating bytes meant it could only ever ask for ASCII, and ASCII is entirely simple glyphs -- it could not reach the code path that mattered. Also: resolvconf's success line moves behind /proc/bootmode, same rule as vgpud. A quiet boot opened with "resolvconf: nameserver 10.0.2.3" where the one line was supposed to be "Welcome to SchOS!". Failures stay loud. Verified on screen, not just on the host: Ą Ę Ś Ł Ż ć ń ó ź, Ω λ π Œ Ð Æ ß, ∞ ‘x’ → ≤ all render, panic=0 across four boots. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
ca28978995
commit
5618164754
11 changed files with 568 additions and 132 deletions
|
|
@ -75,7 +75,16 @@ int gfx_rows(void);
|
|||
|
||||
// For the text layer in kernel/dev/vt.c: one cell with its own colours, and
|
||||
// a screen scroll that leaves the cursor alone.
|
||||
void gfx_draw_cell(int col, int row, uchar glyph, uint32 fg, uint32 bg);
|
||||
// One terminal cell. `cp` is a Unicode codepoint, not a byte -- see the note on
|
||||
// struct vtcell in vt.h for why that distinction is the whole feature.
|
||||
void gfx_draw_cell(int col, int row, uint32 cp, uint32 fg, uint32 bg);
|
||||
|
||||
// Bring the console typeface up, once, early. Falls back to the built-in
|
||||
// bitmap and says nothing if the font will not open -- see the note in gfx.c
|
||||
// on why it cannot print for itself.
|
||||
void gfx_font_init(void);
|
||||
int gfx_font_ready(void);
|
||||
void gfx_cell_size(int *w, int *h);
|
||||
// A filled rectangle in pixels, with the per-pixel checks hoisted out.
|
||||
void gfx_fill(int x, int y, int w, int h, uint32 color);
|
||||
void gfx_scroll_up(uint32 bg);
|
||||
|
|
|
|||
16
include/vt.h
16
include/vt.h
|
|
@ -43,11 +43,23 @@
|
|||
// same cell holding two 32-bit colours would be twelve, and the grids are
|
||||
// static.
|
||||
struct vtcell {
|
||||
uint8 ch;
|
||||
// A Unicode codepoint, not a byte.
|
||||
//
|
||||
// This was a uint8, which is to say the grid could hold 256 distinct glyphs
|
||||
// and every terminal was a CP437 terminal. A codepoint outside that was not
|
||||
// stored wrongly, it was *converted* -- `glyph_for()` mapped what it could
|
||||
// and turned the rest into `?`. Ą, Ę, Ś, Ω, Œ, Ə, ∞ and every other
|
||||
// character anybody actually types were question marks before they reached
|
||||
// the font, so no font could have fixed it.
|
||||
//
|
||||
// Four bytes a cell instead of one. A 1920x1080 screen at 9x18 is 12,720
|
||||
// cells, so the grid costs 100 KB instead of 50 KB per terminal.
|
||||
uint32 ch;
|
||||
uint8 fg;
|
||||
uint8 bg;
|
||||
uint8 attr; // reserved: bold/underline/reverse, which do not change
|
||||
}; // the glyph and so can be added without touching a grid
|
||||
uint8 pad; // the glyph and so can be added without touching a grid
|
||||
};
|
||||
|
||||
#define VT_FG_DEFAULT 16 // SCH_FG from include/theme.h
|
||||
#define VT_BG_DEFAULT 17 // SCH_BG
|
||||
|
|
|
|||
Loading…
Reference in a new issue