Boot manager: Niveus window, keys and wells, Instrument Sans, pointer, other systems, working power entries
The F8 menu is redrawn in the Niveus language: a window with three lights, bevelled keys with a lit edge, wells for panels, anti-aliased corners and a soft shadow, set in Instrument Sans rasterised into include/gfx/nvfont.h (tools/python/mknvfont.py, make nvfont). Scale doubles on screens 1400 px tall or more. Lists taller than the screen scroll. The keyboard still drives everything, and a mouse, touchpad or tablet does too: both UEFI pointer protocols are polled, hover moves the highlight, a click activates. The cursor stays hidden until the pointer has really done something, since the firmware installs a pointer protocol with or without a mouse. The 'keep this resolution?' countdown is one ten-second budget however many times the pointer moves. Loaders found at well-known paths on any volume (Windows, Ubuntu, Debian, Fedora, Arch, openSUSE, systemd-boot, rEFInd, other BOOTX64.EFI) are listed and chain-loaded with LoadImage/StartImage. 'Reboot to firmware' used to halt; it now sets OsIndications and restarts, and Restart and Shut Down call ResetSystem. Checked under QEMU+OVMF: menu, resolution list (incl. 2560x1600 at double scale), system information, shut down, firmware setup, chain-loading a copy of the loader from a second disk, and a full boot of the ISO to the login prompt. Pointer hover and click were checked only with synthetic events: in this setup a USB mouse or tablet delivered no event to the loader (one USB I/O handle appeared but no pointer protocol came from it), and why was not established. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
parent
020aa6113c
commit
dee3affa3b
11 changed files with 9304 additions and 208 deletions
80
tools/python/mknvfont.py
Normal file
80
tools/python/mknvfont.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Rasterise Niveus's interface face into a header the boot manager can draw.
|
||||
|
||||
The loader cannot carry a TrueType rasteriser, and the answer to that has been
|
||||
the same since include/gfx/font.h: do the work at build time and commit the
|
||||
result. This takes Instrument Sans (SIL OFL, see docs/Website/niveus/fonts/)
|
||||
at three sizes and writes 8-bit coverage bitmaps, one per printable ASCII
|
||||
character, with the metrics needed to lay them out proportionally.
|
||||
|
||||
python3 tools/python/mknvfont.py docs/Website/niveus/fonts/static include/gfx/nvfont.h
|
||||
|
||||
Needs Pillow; nothing else, and nothing at all at build time of the OS.
|
||||
"""
|
||||
import sys, os
|
||||
from PIL import ImageFont
|
||||
|
||||
# Each size twice: x1 for ordinary screens and x2 for the ones where a 15 px
|
||||
# face would be a speck. Rendering at the real size beats doubling pixels.
|
||||
SIZES = []
|
||||
for _scale in (1, 2):
|
||||
SIZES += [
|
||||
("body%d" % _scale, "InstrumentSans-Medium.ttf", 15 * _scale),
|
||||
("small%d" % _scale, "InstrumentSans-Regular.ttf", 12 * _scale),
|
||||
("title%d" % _scale, "InstrumentSans-SemiBold.ttf", 24 * _scale),
|
||||
]
|
||||
FIRST, LAST = 32, 126
|
||||
|
||||
|
||||
def render(path, px):
|
||||
f = ImageFont.truetype(path, px)
|
||||
asc, desc = f.getmetrics()
|
||||
glyphs, blob = [], bytearray()
|
||||
for code in range(FIRST, LAST + 1):
|
||||
ch = chr(code)
|
||||
adv = int(round(f.getlength(ch) * 64)) # 26.6 fixed point: whole-pixel advances make text look cramped
|
||||
mask, (ox, oy) = f.getmask2(ch, mode="L", anchor="ls")
|
||||
w, h = mask.size
|
||||
data = bytes(mask) if (w and h) else b""
|
||||
glyphs.append((len(blob), w, h, ox, oy, adv))
|
||||
blob += data
|
||||
return asc, desc, glyphs, blob
|
||||
|
||||
|
||||
def main():
|
||||
src, out = sys.argv[1], sys.argv[2]
|
||||
lines = [
|
||||
"#pragma once",
|
||||
"",
|
||||
"// GENERATED by tools/python/mknvfont.py -- do not edit. Run `make nvfont`.",
|
||||
"// source: docs/Website/niveus/fonts/static (Instrument Sans, SIL OFL 1.1)",
|
||||
"//",
|
||||
"// 8-bit coverage bitmaps for printable ASCII, proportionally spaced, used by",
|
||||
"// the boot manager (boot/common/ui.c). Not included by the kernel.",
|
||||
"",
|
||||
"struct nvglyph { unsigned short off; unsigned char w, h; signed char ox, oy; unsigned short adv; /* 1/64 px */ };",
|
||||
"struct nvfont { unsigned char ascent, descent; const struct nvglyph *g; const unsigned char *bits; };",
|
||||
"#define NVFONT_FIRST %d" % FIRST,
|
||||
"#define NVFONT_LAST %d" % LAST,
|
||||
"",
|
||||
]
|
||||
for name, fn, px in SIZES:
|
||||
asc, desc, glyphs, blob = render(os.path.join(src, fn), px)
|
||||
lines.append("static const struct nvglyph nvg_%s[] = {" % name)
|
||||
for (o, w, h, ox, oy, adv) in glyphs:
|
||||
lines.append(" {%d,%d,%d,%d,%d,%d}," % (o, w, h, ox, oy, adv))
|
||||
lines.append("};")
|
||||
lines.append("static const unsigned char nvb_%s[] = {" % name)
|
||||
for i in range(0, len(blob), 24):
|
||||
lines.append(" " + ",".join(str(b) for b in blob[i:i + 24]) + ",")
|
||||
if not blob:
|
||||
lines.append(" 0")
|
||||
lines.append("};")
|
||||
lines.append("static const struct nvfont nvfont_%s = { %d, %d, nvg_%s, nvb_%s };" %
|
||||
(name, asc, desc, name, name))
|
||||
lines.append("")
|
||||
open(out, "w").write("\n".join(lines) + "\n")
|
||||
print("wrote", out)
|
||||
|
||||
|
||||
main()
|
||||
Loading…
Reference in a new issue