xtc/tools/create_promotional_overview.py
2026-11-06 17:37:18 +01:00

77 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Compose the promotional overview from real gallery captures (requires Pillow)."""
from pathlib import Path
import subprocess
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parents[1]
GALLERY = ROOT / "screenshots"
WIDTH, HEIGHT = 2400, 1800
def font(size, bold=False):
family = "DejaVu Sans:style=Bold" if bold else "DejaVu Sans"
path = subprocess.check_output(
["fc-match", family, "-f", "%{file}"], text=True
).strip()
return ImageFont.truetype(path, size)
def main():
canvas = Image.new("RGB", (WIDTH, HEIGHT))
draw = ImageDraw.Draw(canvas)
# A quiet ink/teal gradient keeps the actual application views prominent.
for y in range(HEIGHT):
t = y / HEIGHT
draw.line((0, y, WIDTH, y), fill=(int(13 + 6*t), int(24 + 4*t), int(31 + 5*t)))
white, muted, teal = "#edf5f5", "#a4b7c1", "#74dbc1"
def text(x, y, value, size, color=white, bold=False):
draw.text((x, y), value, font=font(size, bold), fill=color)
def capture(name, box, x, y, w, h):
with Image.open(GALLERY / (name + ".png")) as source:
crop = source.convert("RGB").crop(box)
# Fit without distorting UI proportions; the remaining space is the card.
scale = min(w / crop.width, h / crop.height)
crop = crop.resize(
(round(crop.width * scale), round(crop.height * scale)),
Image.Resampling.LANCZOS,
)
canvas.paste(crop, (x + (w-crop.width)//2, y + (h-crop.height)//2))
text(80, 38, "xtc", 150, teal, True)
draw.line((370, 75, 370, 207), fill="#35525a", width=2)
text(420, 63, "A lightweight, modular DAW.", 65, bold=True)
text(424, 154, "Compose. Shape your sound. Connect your ideas.", 35, muted)
text(82, 252, "ARRANGE YOUR IDEAS", 23, teal, True)
text(2320 - draw.textlength("Audio + MIDI sequencing", font=font(23)), 252,
"Audio + MIDI sequencing", 23, muted)
draw.rounded_rectangle((76, 304, 2324, 1158), radius=15, fill="#080f15", outline="#36515b", width=2)
capture("sequencer-loop", (0, 20, 1400, 540), 82, 310, 2236, 842)
cards = [
(80, "01", "Write melodies", "Piano roll + note velocities",
"piano-roll-velocity", (24, 230, 930, 804)),
(836, "02", "Build your mix", "Track / bus routing + automation",
"mixer-playing", (24, 230, 1380, 804)),
(1592, "03", "Connect your effects", "Modular track insert chains",
"track-inserts-vst3", (24, 188, 1356, 425)),
]
for x, number, title, caption, source, box in cards:
text(x, 1205, number, 23, teal, True)
text(x+48, 1196, title, 34, bold=True)
text(x, 1253, caption, 24, muted)
draw.rounded_rectangle((x, 1309, x+728, 1634), radius=12, fill="#181d23", outline="#354852", width=2)
capture(source, box, x+10, 1319, 708, 305)
draw.line((80, 1690, 2320, 1690), fill="#354852", width=2)
text(80, 1720, "LINUX FIRST / OPEN SOURCE / MIT LICENSE", 23, teal, True)
text(1580, 1720, "In development · Actual application captures", 23, muted)
canvas.save(GALLERY / "overview.png", optimize=True)
if __name__ == "__main__":
main()