#!/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()