- Bootloader: GRUB fallback text colors → yellow/brown (amber tone) - CLI charts: all GPU metric series use single amber color (xterm-256 #214) - Wallpaper: logo width scaled to 400 px dynamically, shadow scales with font size - Support bundle: renamed to YYYY-MM-DD (BEE-SP vX.X) SRV_MODEL SRV_SN ToD.tar.gz using dmidecode for server model (spaces→underscores) and serial number - Remove display resolution feature (UI card, API routes, handlers, tests) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
118 lines
4.7 KiB
Bash
Executable File
118 lines
4.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# 9001-wallpaper.hook.chroot — generate /usr/share/bee/wallpaper.png inside chroot
|
|
set -e
|
|
echo "=== generating bee wallpaper ==="
|
|
mkdir -p /usr/share/bee
|
|
|
|
python3 - <<'PYEOF'
|
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
|
import os
|
|
|
|
W, H = 1920, 1080
|
|
|
|
ASCII_ART = [
|
|
" ███████╗ █████╗ ███████╗██╗ ██╗ ██████╗ ███████╗███████╗",
|
|
" ██╔════╝██╔══██╗██╔════╝╚██╗ ██╔╝ ██╔══██╗██╔════╝██╔════╝",
|
|
" █████╗ ███████║███████╗ ╚████╔╝ █████╗██████╔╝█████╗ █████╗",
|
|
" ██╔══╝ ██╔══██║╚════██║ ╚██╔╝ ╚════╝██╔══██╗██╔══╝ ██╔══╝",
|
|
" ███████╗██║ ██║███████║ ██║ ██████╔╝███████╗███████╗",
|
|
" ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝",
|
|
]
|
|
SUBTITLE = " Hardware Audit LiveCD"
|
|
|
|
FG = (0xF6, 0xD0, 0x47)
|
|
FG_DIM = (0xD4, 0xA9, 0x1C)
|
|
SHADOW = (0x5E, 0x47, 0x05)
|
|
SUB = (0x96, 0x7A, 0x17)
|
|
BG = (0x05, 0x05, 0x05)
|
|
|
|
MONO_FONT_CANDIDATES = [
|
|
'/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf',
|
|
'/usr/share/fonts/truetype/liberation2/LiberationMono-Bold.ttf',
|
|
'/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf',
|
|
'/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf',
|
|
]
|
|
SUB_FONT_CANDIDATES = [
|
|
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf',
|
|
'/usr/share/fonts/truetype/liberation2/LiberationSans-Bold.ttf',
|
|
'/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf',
|
|
'/usr/share/fonts/truetype/freefont/FreeSansBold.ttf',
|
|
]
|
|
|
|
|
|
def load_font(candidates, size):
|
|
for path in candidates:
|
|
if os.path.exists(path):
|
|
return ImageFont.truetype(path, size)
|
|
return ImageFont.load_default()
|
|
|
|
|
|
def mono_metrics(font):
|
|
probe = Image.new('L', (W, H), 0)
|
|
draw = ImageDraw.Draw(probe)
|
|
char_w = int(round(draw.textlength("M", font=font)))
|
|
bb = draw.textbbox((0, 0), "Mg", font=font)
|
|
char_h = bb[3] - bb[1]
|
|
return char_w, char_h
|
|
|
|
|
|
def render_ascii_mask(font, lines, char_w, char_h, line_gap):
|
|
width = max(len(line) for line in lines) * char_w
|
|
height = len(lines) * char_h + line_gap * (len(lines) - 1)
|
|
mask = Image.new('L', (width, height), 0)
|
|
draw = ImageDraw.Draw(mask)
|
|
for row, line in enumerate(lines):
|
|
y = row * (char_h + line_gap)
|
|
for col, ch in enumerate(line):
|
|
if ch == ' ':
|
|
continue
|
|
x = col * char_w
|
|
draw.text((x, y), ch, font=font, fill=255)
|
|
return mask
|
|
|
|
|
|
img = Image.new('RGB', (W, H), BG)
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
# Soft amber glow under the logo without depending on font rendering.
|
|
glow = Image.new('RGBA', (W, H), (0, 0, 0, 0))
|
|
glow_draw = ImageDraw.Draw(glow)
|
|
glow_draw.ellipse((360, 250, 1560, 840), fill=(180, 120, 10, 56))
|
|
glow_draw.ellipse((520, 340, 1400, 760), fill=(255, 190, 40, 36))
|
|
glow = glow.filter(ImageFilter.GaussianBlur(60))
|
|
img = Image.alpha_composite(img.convert('RGBA'), glow)
|
|
|
|
TARGET_LOGO_W = 400
|
|
max_chars = max(len(line) for line in ASCII_ART)
|
|
_probe_font = load_font(MONO_FONT_CANDIDATES, 64)
|
|
_probe_cw, _ = mono_metrics(_probe_font)
|
|
font_size_logo = max(6, int(64 * TARGET_LOGO_W / (_probe_cw * max_chars)))
|
|
font_logo = load_font(MONO_FONT_CANDIDATES, font_size_logo)
|
|
char_w, char_h = mono_metrics(font_logo)
|
|
logo_mask = render_ascii_mask(font_logo, ASCII_ART, char_w, char_h, 2)
|
|
logo_w, logo_h = logo_mask.size
|
|
logo_x = (W - logo_w) // 2
|
|
logo_y = 380
|
|
|
|
sh_off = max(1, font_size_logo // 6)
|
|
shadow_mask = logo_mask.filter(ImageFilter.GaussianBlur(1))
|
|
img.paste(SHADOW, (logo_x + sh_off * 2, logo_y + sh_off * 2), shadow_mask)
|
|
img.paste(FG_DIM, (logo_x + sh_off, logo_y + sh_off), logo_mask)
|
|
img.paste(FG, (logo_x, logo_y), logo_mask)
|
|
|
|
font_sub = load_font(SUB_FONT_CANDIDATES, 30)
|
|
sub_bb = draw.textbbox((0, 0), SUBTITLE, font=font_sub)
|
|
sub_x = (W - (sub_bb[2] - sub_bb[0])) // 2
|
|
sub_y = logo_y + logo_h + 48
|
|
draw = ImageDraw.Draw(img)
|
|
draw.text((sub_x + 2, sub_y + 2), SUBTITLE, font=font_sub, fill=(35, 28, 6))
|
|
draw.text((sub_x, sub_y), SUBTITLE, font=font_sub, fill=SUB)
|
|
|
|
img = img.convert('RGB')
|
|
|
|
img.save('/usr/share/bee/wallpaper.png', optimize=True)
|
|
print('wallpaper written: /usr/share/bee/wallpaper.png')
|
|
PYEOF
|
|
|
|
echo "=== wallpaper done ==="
|