#!/usr/bin/env python3 # Logo/favicon Gitea: THETA MAIUSCOLA = cerchio (anello) con una "H" al centro. # La H non tocca l'anello (clearance sicura). Niente coda. # Emette sia gli SVG (logo/favicon) che i PNG (logo/favicon/apple-touch-icon) # partendo dalla STESSA geometria, così SVG e PNG combaciano. import os from PIL import Image, ImageDraw OUT = "custom/public/assets/img" # --- geometria normalizzata (frazioni del lato quadrato) --- INSET = 0.04 # bordo del riquadro arrotondato RAD = 0.22 # raggio angoli del riquadro CX, CY = 0.5, 0.5 # centro (simmetrico, nessuna coda) RO = 0.41 # raggio esterno anello RING = 0.05 # spessore anello -> raggio interno RI = RO - RING # H centrale HH = 0.26 # mezza altezza della H (stelo da CY-HH a CY+HH) SPAC = 0.145 # distanza orizzontale dal centro agli steli STEM = 0.05 # spessore steli CROSS = 0.042 # spessore barra orizzontale C1, C2 = (124, 58, 237), (14, 165, 233) # viola -> azzurro RI = RO - RING def lerp(a, b, t): return int(a + (b - a) * t) def grad_color(t): return (lerp(C1[0], C2[0], t), lerp(C1[1], C2[1], t), lerp(C1[2], C2[2], t)) def theta_geo(size): cx, cy = CX * size, CY * size ro, ri = RO * size, RI * size stem = STEM * size cross = CROSS * size # steli: centro x = cx ± SPAC left_x0 = (CX - SPAC - STEM / 2) * size left_x1 = (CX - SPAC + STEM / 2) * size right_x0 = (CX + SPAC - STEM / 2) * size right_x1 = (CX + SPAC + STEM / 2) * size st_y0, st_y1 = (CY - HH) * size, (CY + HH) * size # barra: attraversa tutta la larghezza della H, centrata su CY cb_y0, cb_y1 = CY * size - cross / 2, CY * size + cross / 2 return dict(cx=cx, cy=cy, ro=ro, ri=ri, left_x0=left_x0, left_x1=left_x1, right_x0=right_x0, right_x1=right_x1, st_y0=st_y0, st_y1=st_y1, cb_x0=left_x0, cb_x1=right_x1, cb_y0=cb_y0, cb_y1=cb_y1, stem=stem, cross=cross) def circle_path(r, cx, cy, size): lx, rx = cx - r, cx + r return (f"M {lx:.2f} {cy:.2f} A {r:.2f} {r:.2f} 0 1 0 {rx:.2f} {cy:.2f} " f"A {r:.2f} {r:.2f} 0 1 0 {lx:.2f} {cy:.2f} Z") def svg_theta(size): g = theta_geo(size) inset, rad = INSET * size, RAD * size w = size def e(x): return f"{x:.2f}" outer = circle_path(g["ro"], g["cx"], g["cy"], size) inner = circle_path(g["ri"], g["cx"], g["cy"], size) lines = [] lines.append(f'') lines.append(' ' '') lines.append(f' ') # anello (theta maiuscola = cerchio) lines.append(f' ') # H centrale (steli + barra) lines.append(f' ') lines.append(f' ') lines.append(f' ') lines.append('') return "\n".join(lines) + "\n" def draw_theta_png(size, apple=False): g = theta_geo(size) img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) inset, rad = INSET * size, RAD * size # sfondo: riquadro arrotondato con gradiente verticale sq = Image.new("L", (size, size), 0) ImageDraw.Draw(sq).rounded_rectangle( [inset, inset, size - inset, size - inset], radius=rad, fill=255) grad = Image.new("RGBA", (size, size), (0, 0, 0, 0)) gd = ImageDraw.Draw(grad) for i in range(size * 2): t = i / (size * 2 - 1) gd.line([(i, 0), (i, size)], fill=grad_color(t)) grad.putalpha(sq) img.alpha_composite(grad) # theta+H come maschera bianca mask = Image.new("L", (size, size), 0) md = ImageDraw.Draw(mask) md.ellipse([g["cx"] - g["ro"], g["cy"] - g["ro"], g["cx"] + g["ro"], g["cy"] + g["ro"]], fill=255) md.ellipse([g["cx"] - g["ri"], g["cy"] - g["ri"], g["cx"] + g["ri"], g["cy"] + g["ri"]], fill=0) md.rectangle([g["left_x0"], g["st_y0"], g["left_x1"], g["st_y1"]], fill=255) md.rectangle([g["right_x0"], g["st_y0"], g["right_x1"], g["st_y1"]], fill=255) md.rectangle([g["cb_x0"], g["cb_y0"], g["cb_x1"], g["cb_y1"]], fill=255) white = Image.new("RGBA", (size, size), (255, 255, 255, 255)) white.putalpha(mask) img.alpha_composite(white) if apple: base = Image.new("RGBA", img.size, (255, 255, 255, 255)) base.alpha_composite(img) return base.convert("RGB") return img def make_assets(): os.makedirs(OUT, exist_ok=True) open(f"{OUT}/logo.svg", "w").write(svg_theta(64)) open(f"{OUT}/favicon.svg", "w").write(svg_theta(64)) draw_theta_png(220).save(f"{OUT}/logo.png") draw_theta_png(64).save(f"{OUT}/favicon.png") draw_theta_png(180, apple=True).save(f"{OUT}/apple-touch-icon.png") print("theta (capital: circle + H) assets written to", OUT) if __name__ == "__main__": make_assets()