eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1#!/usr/bin/env python3
2# Generate the install-window background for the Eleven DMG.
3# Renders at 2x (retina) then downsamples for the 1x rep, so both are crisp.
4import os
5from PIL import Image, ImageDraw, ImageFont
6
7OUT = os.path.dirname(os.path.abspath(__file__))
8S = 2 # supersample / retina factor
9W, H = 640 * S, 400 * S
10
11# Purple sampled from the app icon (AppIcon icon_1024, core of the violet
12# gradient) so the "Eleven" wordmark matches the logo exactly.
13PURPLE = (101, 64, 208) # #6540D0 — wordmark
14GREY = (150, 155, 168) # the count numbers — light grey, regular weight
15DOT_GREY = (200, 203, 214) # faint separators / arrow-lighter
16DARK = (28, 30, 42)
17MUTED = (122, 126, 140)
18GRAD_TOP = (252, 252, 255)
19GRAD_BOT = (235, 237, 249)
20
21
22def font(size, bold=False):
23 size = int(size * S)
24 # Prefer SF Pro (variable font — pick the Bold instance); fall back to Arial.
25 try:
26 f = ImageFont.truetype("/System/Library/Fonts/SFNS.ttf", size)
27 if bold:
28 try:
29 f.set_variation_by_name("Bold")
30 except Exception:
31 pass
32 return f
33 except Exception:
34 p = "/System/Library/Fonts/Supplemental/Arial Bold.ttf" if bold \
35 else "/System/Library/Fonts/Supplemental/Arial.ttf"
36 return ImageFont.truetype(p, size)
37
38
39# --- base gradient ---
40img = Image.new("RGB", (W, H), GRAD_TOP)
41d = ImageDraw.Draw(img)
42for y in range(H):
43 t = y / (H - 1)
44 d.line([(0, y), (W, y)], fill=tuple(
45 int(a + (b - a) * t) for a, b in zip(GRAD_TOP, GRAD_BOT)))
46d = ImageDraw.Draw(img)
47
48# --- the count: 1 · 2 · … · 10 → (light grey, regular, on the icon line) ---
49row_y = 208 * S
50num_font = font(14.5) # match the "Drag the app…" subtitle — one body size
51arrow_font = num_font # the → is the same size as the numbers (no size-mixing)
52inter = 2 * S # tight spacing between tokens
53arrow_gap = 7 * S # a little breathing room before the arrow
54
55parts = [] # (text, font, colour)
56for i in range(1, 11):
57 parts.append((str(i), num_font, GREY))
58 if i < 10:
59 parts.append(("·", num_font, DOT_GREY))
60widths = [d.textlength(t, font=f) for (t, f, _) in parts]
61arrow_w = d.textlength("→", font=arrow_font)
62total = sum(widths) + inter * (len(parts) - 1) + arrow_gap + arrow_w
63x = W / 2 - total / 2
64for (t, f, c), w in zip(parts, widths):
65 d.text((x, row_y), t, font=f, fill=c, anchor="lm")
66 x += w + inter
67x = x - inter + arrow_gap
68d.text((x, row_y), "→", font=arrow_font, fill=GREY, anchor="lm")
69
70# --- title ---
71title_r = font(27, bold=True)
72ty = 62 * S
73seg1, seg2 = "Install ", "Eleven"
74w1 = d.textlength(seg1, font=title_r)
75w2 = d.textlength(seg2, font=title_r)
76sx = (W - (w1 + w2)) / 2
77d.text((sx, ty), seg1, font=title_r, fill=DARK, anchor="lm")
78d.text((sx + w1, ty), seg2, font=title_r, fill=PURPLE, anchor="lm")
79
80# --- subtitle ---
81sub = font(14.5)
82d.text((W / 2, 98 * S), "Drag the app into your Applications folder",
83 font=sub, fill=MUTED, anchor="mm")
84
85img.save(os.path.join(OUT, "background@2x.png"))
86img.resize((W // S, H // S), Image.LANCZOS).save(os.path.join(OUT, "background.png"))
87print("wrote background.png (%dx%d) + background@2x.png (%dx%d)" %
88 (W // S, H // S, W, H))
89