README card: each 0 in the Halloween numbers is the logo's 3D pumpkin (readme_stats.py --halloween)

This commit is contained in:
Gathin23 committed 2026-10-29 18:47:07 +05:30
1 parent 5e50fe0eda
commit 42fe7b09d6
5 files changed
+49 -9

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

+7 -6
View File
@@ -4,9 +4,10 @@ the file the front page displays.
Run tools/readme_stats.py and tools/readme_featured.py first, then:
python3 tools/readme_card.py Fredoka.ttf docs/card.jpg
python3 tools/readme_card.py --halloween Fredoka.ttf docs/card-halloween.jpg # the October variant
The Halloween variant keeps the layout and the generated numbers: it recolours docs/stats.png's mint
numbers and the headings to pumpkin orange, adds a thin dripping stripe and a few bats, and shows
docs/new-home-halloween.jpg as AFTER. docs/card.jpg is not touched, so the README goes back with one line.
The Halloween variant keeps the layout and the generated numbers: it shows docs/stats-halloween.png
(python3 tools/readme_stats.py --halloween Fredoka.ttf docs/stats-halloween.png: the same numbers in pumpkin
orange, each 0 a pumpkin), recolours the headings to orange, adds a thin dripping stripe and a few bats, and
shows docs/new-home-halloween.jpg as AFTER. docs/card.jpg is not touched, so the README goes back with one line.
Fredoka is the variable TTF from Google Fonts, and its file is not in this repo: pass the path of the
copy you downloaded. The four pictures it stacks are this checkout's own - docs/stock-home.jpg,
docs/new-home.jpg and the two its siblings draw - so run it from the repository root.
@@ -81,7 +82,8 @@ INPUTS = (
("docs/stats.png", "tools/readme_stats.py draws it"),
("docs/featured.png", "tools/readme_featured.py draws it"),
)
HALLOWEEN_INPUTS = (("docs/new-home-halloween.jpg", None),)
HALLOWEEN_INPUTS = (("docs/new-home-halloween.jpg", None),
("docs/stats-halloween.png", "tools/readme_stats.py --halloween draws it"))
def inputs_problem():
@@ -217,9 +219,8 @@ def decorate(card):
card.alpha_composite(deco) if hasattr(card, "alpha_composite") and card.mode == "RGBA" else card.paste(deco, (0, 0), deco)
stats, featured = load("docs/stats.png"), load("docs/featured.png")
stats, featured = load("docs/stats-halloween.png" if HALLOWEEN else "docs/stats.png"), load("docs/featured.png")
if HALLOWEEN:
tint(stats, (0, 0, W, 130)) # the generated numbers, mint to orange
heading(featured, (650, 50, 950, 85)) # "FEATURED IN"
tint(featured, (1090, 315, 1135, 352)) # the arrow after "314 articles"
parts = [stats, featured, tv]
+42 -3
View File
@@ -1,13 +1,16 @@
"""Renders the stat strip (docs/stats.png), the top part of the README card.
Update STATS, then: python3 tools/readme_stats.py Fredoka.ttf docs/stats.png
and rebuild the card with tools/readme_card.py. Fredoka is the variable TTF from Google Fonts, and its
and rebuild the card with tools/readme_card.py.
python3 tools/readme_stats.py --halloween Fredoka.ttf docs/stats-halloween.png draws the October strip for
tools/readme_card.py --halloween: the same STATS in pumpkin orange, each digit 0 the 3D pumpkin of the
spooky logo (docs/pumpkin-3d.png). Fredoka is the variable TTF from Google Fonts, and its
file is not in this repo: download it and pass the path of the copy you saved.
"""
import os
import sys
USAGE = ("usage: readme_stats.py <font.ttf> <out.png>\n"
USAGE = ("usage: readme_stats.py [--halloween] <font.ttf> <out.png>\n"
" Fredoka, the variable TTF from Google Fonts, is not in this repo: download it and pass the\n"
" path of the file you saved.")
@@ -19,6 +22,7 @@ def font_and_out(argv):
the first thing that fails here, and Pillow's `OSError: cannot open resource` names neither the file
it wanted nor where to get it.
"""
argv = [a for a in argv if a != "--halloween"]
if len(argv) != 3:
sys.exit(USAGE)
font, out = argv[1], argv[2]
@@ -50,6 +54,7 @@ def out_problem(path):
return None
HALLOWEEN = "--halloween" in sys.argv
FONT, OUT = font_and_out(sys.argv)
# The picture is the other argument the reader types, and Pillow only refuses it after the whole thing
@@ -85,11 +90,45 @@ def f(size, wt):
return x
f(12, 400) # the font is the argument the reader brings, so a wrong one is named before any drawing
num, lab = f(92, 600), f(30, 500)
NUM_FILL = "#ff9a3c" if HALLOWEEN else "#cfffcf"
PUMPKIN = None
if HALLOWEEN:
if not os.path.isfile("docs/pumpkin-3d.png"):
sys.exit("cannot read docs/pumpkin-3d.png: the Halloween strip draws each 0 as that picture, so run "
"this from the repository root. Nothing was written.")
PUMPKIN = Image.open("docs/pumpkin-3d.png").convert("RGBA")
PUMPKIN = PUMPKIN.crop(PUMPKIN.getbbox())
def number(d, cx, n):
"""`n` with each 0 drawn as the pumpkin: as tall as the digits, standing on their baseline."""
top, bottom = d.textbbox((0, 40), "3", font=num)[1::2]
h = bottom - top
pk = PUMPKIN.resize((round(PUMPKIN.width * h / PUMPKIN.height), h), Image.LANCZOS)
gap = 10
parts = n.split("0")
seq = []
for i, text in enumerate(parts):
if text:
seq.append(("t", text, d.textlength(text, font=num)))
if i < len(parts) - 1:
seq.append(("p", None, pk.width + gap))
x = cx - sum(w for _, _, w in seq) / 2
for kind, text, w in seq:
if kind == "t":
d.text((x, 40), text, font=num, fill=NUM_FILL)
else:
img.paste(pk, (round(x + gap / 2), bottom - h), pk)
x += w
PAD = 70
col = (W - 2 * PAD) / len(STATS)
for i, (n, l) in enumerate(STATS):
cx = PAD + col * i + col / 2
w = d.textlength(n, font=num); d.text((cx - w / 2, 40), n, font=num, fill="#cfffcf")
if HALLOWEEN and "0" in n:
number(d, cx, n)
else:
w = d.textlength(n, font=num); d.text((cx - w / 2, 40), n, font=num, fill=NUM_FILL)
sp = 5; w = sum(d.textlength(c, font=lab) for c in l) + sp * (len(l) - 1); x = cx - w / 2
for c in l: d.text((x, 160), c, font=lab, fill="#aab3bd"); x += d.textlength(c, font=lab) + sp
if i: d.line([(PAD + col * i, 56), (PAD + col * i, H - 56)], fill="#2c313a", width=3)