alpinux-wiki/scripts/build-assets.py

162 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Génère les assets binaires (logo PNG + favicons) depuis la source SVG.
Dépendances : Pillow, chromium
Usage :
python3 scripts/build-assets.py
Sorties :
docs/assets/alpinux-logo.png → logo 200×200 inclus dans le wiki (MkDocs)
/tmp/alpinux-static-assets/ → favicons + logo 512px à uploader sur static.alpinux.org/logo/
"""
import subprocess
import tempfile
import os
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
REPO = Path(__file__).resolve().parent.parent
SVG = REPO / "docs/assets/alpinux-logo.svg"
DOCS_OUT = REPO / "docs/assets"
CDN_OUT = Path("/tmp/alpinux-static-assets")
FONT_R = "/usr/share/fonts/truetype/msttcorefonts/arial.ttf"
FONT_B = "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf"
COLOR = (15, 78, 143) # #0f4e8f
def render_shapes(svg_path: Path, width: int, height: int) -> Image.Image:
"""Render SVG shapes via chromium headless (no text)."""
html = f"""<!DOCTYPE html><html>
<head><meta charset="utf-8">
<style>*{{margin:0;padding:0}}html,body{{width:{width}px;height:{height}px;overflow:hidden;background:transparent}}</style>
</head>
<body><img src="file://{svg_path}" width="{width}" height="{height}"></body>
</html>"""
with tempfile.NamedTemporaryFile(suffix=".html", mode="w", delete=False) as f:
f.write(html)
tmp_html = f.name
out_png = tmp_html.replace(".html", ".png")
subprocess.run([
"chromium", "--headless", "--disable-gpu", "--no-sandbox",
f"--screenshot={out_png}", f"--window-size={width},{height}",
f"file://{tmp_html}"
], capture_output=True)
img = Image.open(out_png).convert("RGBA")
os.unlink(tmp_html)
os.unlink(out_png)
return img
def add_text(canvas: Image.Image) -> Image.Image:
"""Composite Alpinux text with correct weights onto the canvas."""
draw = ImageDraw.Draw(canvas)
size = 30
f_reg = ImageFont.truetype(FONT_R, size)
f_bld = ImageFont.truetype(FONT_B, size)
parts = [("A", False), ("l", True), ("p", False), ("inux", True)]
widths = []
for char, bold in parts:
f = f_bld if bold else f_reg
bb = f.getbbox(char)
widths.append(bb[2] - bb[0])
total_w = sum(widths)
x = (canvas.width - total_w) // 2
y = 164 + (36 - size) // 2 + 1
for (char, bold), w in zip(parts, widths):
f = f_bld if bold else f_reg
bb = f.getbbox(char)
draw.text((x - bb[0], y - bb[1]), char, font=f, fill=COLOR)
x += w
return canvas
def build_logo_wiki(docs_out: Path):
"""Build 200×200 logo PNG → docs/assets/ (servi par MkDocs, non commité)."""
shapes = render_shapes(SVG, 200, 164)
canvas = Image.new("RGBA", (200, 200), (255, 255, 255, 255))
canvas.paste(shapes, (0, 0))
canvas = add_text(canvas)
path = docs_out / "alpinux-logo.png"
canvas.convert("RGB").save(path)
print(f" {path} (200×200) → wiki MkDocs")
def build_logo_cdn(cdn_out: Path):
"""Build 512×512 logo PNG → CDN (static.alpinux.org/logo/)."""
shapes512 = render_shapes(SVG, 512, 421)
canvas512 = Image.new("RGBA", (512, 512), (255, 255, 255, 255))
canvas512.paste(shapes512, (0, 0))
draw = ImageDraw.Draw(canvas512)
size = 77
f_reg = ImageFont.truetype(FONT_R, size)
f_bld = ImageFont.truetype(FONT_B, size)
parts = [("A", False), ("l", True), ("p", False), ("inux", True)]
widths = [f_bld.getbbox(c)[2]-f_bld.getbbox(c)[0] if b else f_reg.getbbox(c)[2]-f_reg.getbbox(c)[0] for c,b in parts]
total_w = sum(widths)
x = (512 - total_w) // 2
y = 421 + (91 - size) // 2 + 2
for (char, bold), w in zip(parts, widths):
f = f_bld if bold else f_reg
bb = f.getbbox(char)
draw.text((x - bb[0], y - bb[1]), char, font=f, fill=COLOR)
x += w
path512 = cdn_out / "alpinux-logo-512.png"
canvas512.convert("RGB").save(path512)
print(f" {path512} (512×512) → static.alpinux.org/logo/")
def build_favicons(cdn_out: Path):
"""Build favicon PNG set + .ico → CDN (static.alpinux.org/logo/)."""
icon_src = render_shapes(SVG, 200, 164).crop((0, 0, 164, 164))
sizes = {
"favicon-16.png": 16,
"favicon-32.png": 32,
"favicon.png": 48,
"favicon-96.png": 96,
"favicon-192.png": 192,
}
imgs = {}
for name, sz in sizes.items():
img = icon_src.resize((sz, sz), Image.LANCZOS)
bg = Image.new("RGBA", (sz, sz), (255, 255, 255, 255))
bg.paste(img, (0, 0))
p = cdn_out / name
bg.save(p)
imgs[sz] = bg
print(f" {p} ({sz}×{sz}) → static.alpinux.org/logo/")
ico = cdn_out / "favicon.ico"
imgs[16].save(ico, format="ICO", sizes=[(16,16),(32,32),(48,48)],
append_images=[imgs[32], imgs[48]])
print(f" {ico} (multi-size: 16+32+48) → static.alpinux.org/logo/")
def main():
DOCS_OUT.mkdir(parents=True, exist_ok=True)
CDN_OUT.mkdir(parents=True, exist_ok=True)
print("Génération des assets Alpinux...")
print()
print("── Logo wiki (docs/assets/) ──")
build_logo_wiki(DOCS_OUT)
print()
print("── CDN static.alpinux.org/logo/ ──")
build_logo_cdn(CDN_OUT)
build_favicons(CDN_OUT)
print()
print(f"Fichiers CDN dans : {CDN_OUT}")
print("À uploader sur : static.alpinux.org/logo/")
print()
print("Ensuite : mkdocs build")
if __name__ == "__main__":
main()