100 lines
2.8 KiB
Python
100 lines
2.8 KiB
Python
"""Genera un icono provisional para jlauncher (PNG 1024x1024).
|
|
|
|
Dibuja un «squircle» con degradado y un triángulo de «play» (es un lanzador de juegos).
|
|
Se ejecuta sin pantalla con la plataforma offscreen de Qt:
|
|
|
|
QT_QPA_PLATFORM=offscreen .venv/bin/python assets/make_icon.py
|
|
|
|
Salida: assets/icon.png. El .icns lo construye build.sh con iconutil.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
from PySide6.QtCore import QPointF, QRectF, Qt # noqa: E402
|
|
from PySide6.QtGui import ( # noqa: E402
|
|
QBrush,
|
|
QColor,
|
|
QGuiApplication,
|
|
QImage,
|
|
QLinearGradient,
|
|
QPainter,
|
|
QPainterPath,
|
|
)
|
|
|
|
SIZE = 1024
|
|
|
|
|
|
def render() -> QImage:
|
|
img = QImage(SIZE, SIZE, QImage.Format_ARGB32)
|
|
img.fill(Qt.transparent)
|
|
|
|
p = QPainter(img)
|
|
p.setRenderHint(QPainter.Antialiasing, True)
|
|
|
|
# «Squircle»: rectángulo con esquinas redondeadas estilo macOS (~22% del lado).
|
|
margin = SIZE * 0.06
|
|
rect = QRectF(margin, margin, SIZE - 2 * margin, SIZE - 2 * margin)
|
|
radius = rect.width() * 0.2237
|
|
body = QPainterPath()
|
|
body.addRoundedRect(rect, radius, radius)
|
|
|
|
grad = QLinearGradient(rect.topLeft(), rect.bottomRight())
|
|
grad.setColorAt(0.0, QColor("#4b3bd6"))
|
|
grad.setColorAt(1.0, QColor("#7b2ff7"))
|
|
p.fillPath(body, QBrush(grad))
|
|
|
|
# Barras verticales tenues: guiño a «jail».
|
|
p.save()
|
|
p.setClipPath(body)
|
|
p.setPen(Qt.NoPen)
|
|
p.setBrush(QColor(255, 255, 255, 26))
|
|
bars = 5
|
|
bar_w = rect.width() * 0.052
|
|
gap = (rect.width() - bars * bar_w) / (bars + 1)
|
|
x = rect.left() + gap
|
|
for _ in range(bars):
|
|
p.drawRoundedRect(QRectF(x, rect.top(), bar_w, rect.height()), bar_w / 2, bar_w / 2)
|
|
x += bar_w + gap
|
|
p.restore()
|
|
|
|
# Triángulo de «play» centrado, blanco con esquinas redondeadas.
|
|
cx, cy = rect.center().x(), rect.center().y()
|
|
r = rect.width() * 0.26
|
|
tri = QPainterPath()
|
|
tri.moveTo(QPointF(cx - r * 0.55, cy - r * 0.95))
|
|
tri.lineTo(QPointF(cx - r * 0.55, cy + r * 0.95))
|
|
tri.lineTo(QPointF(cx + r * 1.0, cy))
|
|
tri.closeSubpath()
|
|
|
|
pen_brush = QColor("#ffffff")
|
|
stroker_pen = p.pen()
|
|
stroker_pen.setColor(pen_brush)
|
|
stroker_pen.setWidthF(r * 0.28)
|
|
stroker_pen.setJoinStyle(Qt.RoundJoin)
|
|
stroker_pen.setCapStyle(Qt.RoundCap)
|
|
p.strokePath(tri, stroker_pen)
|
|
p.fillPath(tri, pen_brush)
|
|
|
|
p.end()
|
|
return img
|
|
|
|
|
|
def main() -> int:
|
|
QGuiApplication([])
|
|
out = Path(__file__).resolve().parent / "icon.png"
|
|
img = render()
|
|
if not img.save(str(out), "PNG"):
|
|
print(f"[icon] no se pudo guardar {out}")
|
|
return 1
|
|
print(f"[icon] generado {out} ({SIZE}x{SIZE})")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|