119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Background (centered layout) + theme.txt + preview.png"""
|
|
import argparse
|
|
import os
|
|
from psd_tools import PSDImage
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('psd', help='layered PSD with the menu background')
|
|
parser.add_argument('out', help='output directory')
|
|
parser.add_argument('--bar', default=None,
|
|
help='selected-row image (default: <out>/sel_bar.png)')
|
|
parser.add_argument('--font', default='Montserrat-SemiBold.ttf',
|
|
help='TTF used for the preview text')
|
|
args = parser.parse_args()
|
|
|
|
SRC = args.psd
|
|
T = args.out
|
|
os.makedirs(T, exist_ok=True)
|
|
|
|
KEEP_HEADERS = {'главное меню', 'paravis flash', '© paravis.ru'}
|
|
DROP_PIXELS = {'shape and color'} # frame of the right "additional menu"
|
|
|
|
psd = PSDImage.open(SRC)
|
|
|
|
|
|
def walk(layer):
|
|
for ch in layer:
|
|
nm = (ch.name or '').strip().lower()
|
|
if ch.kind == 'group':
|
|
walk(ch)
|
|
elif ch.kind == 'type':
|
|
if nm not in KEEP_HEADERS:
|
|
ch.visible = False
|
|
elif ch.kind == 'pixel':
|
|
if nm in DROP_PIXELS:
|
|
ch.visible = False
|
|
|
|
|
|
for layer in psd:
|
|
nm = (layer.name or '')
|
|
if nm.startswith('ТЕКСТ_БЕЗ_ОБВОДКИ'):
|
|
layer.visible = False
|
|
elif nm.startswith('ВЫДЕЛЕНЫЕ'):
|
|
layer.visible = False
|
|
else:
|
|
walk(layer)
|
|
|
|
bg = psd.composite().convert('RGB')
|
|
bg.save(os.path.join(T, 'background.png'))
|
|
print('background:', bg.size)
|
|
|
|
# ---------------------------------------------------------------- geometry
|
|
LEFT, TOP, WIDTH = 202, 100, 620
|
|
ITEM_H, SPACING = 46, 4
|
|
ROWS = [
|
|
('Super Grub2 (поиск и запуск ОС)', '(1)'),
|
|
('Поиск и запуск Windows 7-11', '(2)'),
|
|
('Установка Windows 7, 10, 11 x64', '(3)'),
|
|
('Ventoy (ISO-образы)', '(4)'),
|
|
('Kaspersky Rescue Disk 18', '(5)'),
|
|
None,
|
|
('Windows 10, 11 PE Sergei Strelec', '(6)'),
|
|
('Утилиты для диагностики', '(7)'),
|
|
('Восстановление Windows MSDaRT', '(8)'),
|
|
('Запуск / Установка Linux', '(9)'),
|
|
None,
|
|
('Перезагрузка', '(R)'),
|
|
('Выключение', '(S)'),
|
|
]
|
|
HEIGHT = len(ROWS) * (ITEM_H + SPACING)
|
|
|
|
theme = f'''# Paravis Flash - GRUB2 theme (main menu)
|
|
desktop-image: "background.png"
|
|
desktop-color: "#e9e9e9"
|
|
title-text: ""
|
|
terminal-font: "Unifont Regular 16"
|
|
|
|
+ boot_menu {{
|
|
left = {LEFT}
|
|
top = {TOP}
|
|
width = {WIDTH}
|
|
height = {HEIGHT}
|
|
item_font = "Montserrat SemiBold 17"
|
|
item_color = "#2b3a55"
|
|
selected_item_color = "#ffffff"
|
|
item_height = {ITEM_H}
|
|
item_spacing = {SPACING}
|
|
item_padding = 26
|
|
item_icon_space = 0
|
|
icon_width = 0
|
|
icon_height = 0
|
|
selected_item_pixmap_style = "sel_*.png"
|
|
scrollbar = false
|
|
}}
|
|
'''
|
|
open(os.path.join(T, 'theme.txt'), 'w', encoding='utf-8').write(theme)
|
|
print('theme.txt written')
|
|
|
|
# ---------------------------------------------------------------- preview
|
|
bar_path = args.bar or os.path.join(T, 'sel_bar.png')
|
|
bar = Image.open(bar_path).convert('RGBA').resize((WIDTH, ITEM_H))
|
|
font = ImageFont.truetype(args.font, 17)
|
|
img = bg.copy().convert('RGBA')
|
|
d = ImageDraw.Draw(img)
|
|
col = max(len(r[0]) for r in ROWS if r)
|
|
for i, row in enumerate(ROWS):
|
|
y = TOP + i * (ITEM_H + SPACING)
|
|
if row is None:
|
|
continue
|
|
label, num = row
|
|
if i == 0:
|
|
img.alpha_composite(bar, (LEFT, y))
|
|
color = (255, 255, 255) if i == 0 else (43, 58, 85)
|
|
d.text((LEFT + 26, y + ITEM_H / 2), label, font=font, fill=color, anchor='lm')
|
|
d.text((LEFT + WIDTH - 22, y + ITEM_H / 2), num, font=font, fill=color, anchor='rm')
|
|
img.convert('RGB').save(os.path.join(T, 'preview.png'))
|
|
print('preview.png written')
|