fix: bug scan — API hardening, safer disk picker, updater rollback, friendlier installer #19
1 changed files with 16 additions and 7 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# ruff: noqa: E501 — inline SVG markup reads better unwrapped
|
||||||
"""Generate the logo-poll showcase assets for /logo/ from one geometry source.
|
"""Generate the logo-poll showcase assets for /logo/ from one geometry source.
|
||||||
|
|
||||||
python3 website/tools/logo-assets.py
|
python3 website/tools/logo-assets.py
|
||||||
|
|
@ -10,6 +11,7 @@ the output — the site build itself needs nothing beyond Hugo.
|
||||||
Mark M: lowercase f knocked out of a gate, 64-unit grid (even-odd fill).
|
Mark M: lowercase f knocked out of a gate, 64-unit grid (even-odd fill).
|
||||||
Mark R: window, wheel and F, 104x114 grid, stroke 8 (from Robert's sketch).
|
Mark R: window, wheel and F, 104x114 grid, stroke 8 (from Robert's sketch).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
|
@ -119,7 +121,9 @@ def raster(svgtxt, w, h):
|
||||||
|
|
||||||
def mark_png(k, tier, height, color=None):
|
def mark_png(k, tier, height, color=None):
|
||||||
_, _, w, h = MARKS[k]["vb"]
|
_, _, w, h = MARKS[k]["vb"]
|
||||||
return raster(svg(k, tier, color or MARKS[k]["color"], standalone=True), round(height * w / h), height)
|
return raster(
|
||||||
|
svg(k, tier, color or MARKS[k]["color"], standalone=True), round(height * w / h), height
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- wordmark
|
# ---------------------------------------------------------------- wordmark
|
||||||
|
|
@ -141,7 +145,9 @@ def wordmark(text, size, x0=0.0, baseline=0.0, tracking=-0.028):
|
||||||
g.draw(pen)
|
g.draw(pen)
|
||||||
d = pen.getCommands()
|
d = pen.getCommands()
|
||||||
if d:
|
if d:
|
||||||
parts.append(f'<path transform="translate({x:.2f} {baseline:.2f}) scale({s:.5f} {-s:.5f})" d="{d}"/>')
|
parts.append(
|
||||||
|
f'<path transform="translate({x:.2f} {baseline:.2f}) scale({s:.5f} {-s:.5f})" d="{d}"/>'
|
||||||
|
)
|
||||||
x += g.width * s + tracking * size
|
x += g.width * s + tracking * size
|
||||||
return "".join(parts), x - x0 - tracking * size
|
return "".join(parts), x - x0 - tracking * size
|
||||||
|
|
||||||
|
|
@ -241,21 +247,24 @@ def vote_card(path):
|
||||||
m = mark_png(k, "flat", 330)
|
m = mark_png(k, "flat", 330)
|
||||||
im.alpha_composite(m, (cx - m.width // 2, 110 - (m.height - 330) // 2))
|
im.alpha_composite(m, (cx - m.width // 2, 110 - (m.height - 330) // 2))
|
||||||
size = 46
|
size = 46
|
||||||
d = ImageDraw.Draw(im)
|
|
||||||
for text, cx, col in (("M", W // 4, "#6b6b6f"), ("R", 3 * W // 4, "#8a8a90")):
|
for text, cx, col in (("M", W // 4, "#6b6b6f"), ("R", 3 * W // 4, "#8a8a90")):
|
||||||
paths, tw = wordmark(text, size)
|
paths, tw = wordmark(text, size)
|
||||||
# letters via the same outlines: rasterise a tiny SVG for crisp text
|
# letters via the same outlines: rasterise a tiny SVG for crisp text
|
||||||
svgtxt = (f'<svg {XMLNS} viewBox="0 -{size} {tw:.0f} {size * 1.3:.0f}">'
|
svgtxt = (
|
||||||
f'<g fill="{col}">{paths}</g></svg>')
|
f'<svg {XMLNS} viewBox="0 -{size} {tw:.0f} {size * 1.3:.0f}">'
|
||||||
|
f'<g fill="{col}">{paths}</g></svg>'
|
||||||
|
)
|
||||||
t = raster(svgtxt, round(tw), round(size * 1.3))
|
t = raster(svgtxt, round(tw), round(size * 1.3))
|
||||||
im.alpha_composite(t, (cx - t.width // 2, 500))
|
im.alpha_composite(t, (cx - t.width // 2, 500))
|
||||||
# url line, centred on the seam
|
# url line, centred on the seam
|
||||||
paths, tw = wordmark("furtka.org/logo", 40)
|
paths, tw = wordmark("furtka.org/logo", 40)
|
||||||
svgtxt = (f'<svg {XMLNS} viewBox="0 -40 {tw:.0f} 52"><g fill="#c03a28">{paths}</g></svg>')
|
svgtxt = f'<svg {XMLNS} viewBox="0 -40 {tw:.0f} 52"><g fill="#c03a28">{paths}</g></svg>'
|
||||||
t = raster(svgtxt, round(tw), 52)
|
t = raster(svgtxt, round(tw), 52)
|
||||||
pad = 18
|
pad = 18
|
||||||
box = Image.new("RGBA", (t.width + 2 * pad, t.height + 2 * pad), "#f7f6f3")
|
box = Image.new("RGBA", (t.width + 2 * pad, t.height + 2 * pad), "#f7f6f3")
|
||||||
ImageDraw.Draw(box).rounded_rectangle([0, 0, box.width - 1, box.height - 1], 14, outline="#e4e3dc")
|
ImageDraw.Draw(box).rounded_rectangle(
|
||||||
|
[0, 0, box.width - 1, box.height - 1], 14, outline="#e4e3dc"
|
||||||
|
)
|
||||||
box.alpha_composite(t, (pad, pad))
|
box.alpha_composite(t, (pad, pad))
|
||||||
im.alpha_composite(box, (W // 2 - box.width // 2, 40))
|
im.alpha_composite(box, (W // 2 - box.width // 2, 40))
|
||||||
im.convert("RGB").save(path, optimize=True)
|
im.convert("RGB").save(path, optimize=True)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue