ps1: IGDB-first covers, elided PIC0 text, drop PS3 badge

- Cover art: try IGDB first for PS1 so the cover is clean box art without
  the PlayStation banner that libretro/ScreenScraper thumbnails bake in
  (redundant with the ICON0 case frame).
- PIC0: elide long titles with an ellipsis and word-wrap the description to
  3 lines with a trailing ellipsis instead of clipping/overflowing.
- PIC0: remove the PS3 badge; PSP only for now (PS3/PS4 packaging is future
  work).
This commit is contained in:
2026-09-07 19:29:19 -04:00
parent f6dccbec24
commit 43263aa644
+51 -19
View File
@@ -952,28 +952,31 @@ def _make_pic0(title, description, esrb, QImage, QPainter, QPainterPath, QColor,
_draw_ps_glyphs(p, W - 34, 12, 22, QColor(200, 200, 205), QRectF, QPointF,
QPolygonF, QPen, Qt)
# Title (bold, upper-left).
# Title (bold, upper-left), elided so long titles end with an ellipsis
# instead of clipping mid-character.
f_title = QFont("DejaVu Sans")
f_title.setPixelSize(19)
f_title.setBold(True)
p.setFont(f_title)
p.setPen(QColor(255, 255, 255))
p.drawText(QRectF(18, 16, W - 64, 28), Qt.AlignLeft | Qt.AlignVCenter,
title or "")
title_width = W - 70
fm_title = QFontMetrics(f_title)
title_text = fm_title.elidedText(title or "", Qt.ElideRight, title_width)
p.drawText(QRectF(18, 16, title_width, 28), Qt.AlignLeft | Qt.AlignVCenter,
title_text)
# Description (wrapped, below title).
# Description (wrapped to at most 3 lines, last line elided).
if description:
f_desc = QFont("DejaVu Sans")
f_desc.setPixelSize(12)
p.setFont(f_desc)
p.setPen(QColor(215, 215, 215))
text = description.strip()
fm = QFontMetrics(f_desc)
# Rough 3-line budget (~40 chars/line at 12px across 272px).
if fm.horizontalAdvance(text) > 3 * (W - 36):
text = text[:130].rstrip() + "\u2026"
p.drawText(QRectF(18, 46, W - 36, 74),
Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, text)
lines = _wrap_elided(fm, description.strip(), W - 36, 3, Qt)
y = 46
for line in lines:
p.drawText(QRectF(18, y, W - 36, 16), Qt.AlignLeft | Qt.AlignVCenter, line)
y += 16
# ESRB badge (bottom-left) + caption.
if esrb:
@@ -981,9 +984,8 @@ def _make_pic0(title, description, esrb, QImage, QPainter, QPainterPath, QColor,
if badge:
_draw_esrb(p, badge, 18, 140, QRectF, QColor, QFont, QFontMetrics, QPen, Qt)
# Platform badges (bottom-right).
_draw_platform_badge(p, "PS3", W - 14 - 64, 146, QColor(94, 146, 210),
QRectF, QColor, QFont, QFontMetrics, Qt)
# Platform badge (bottom-right). Only PSP for now; PS3/PS4 packaging is a
# separate future feature.
_draw_platform_badge(p, "PSP", W - 14 - 30, 146, QColor(212, 175, 55),
QRectF, QColor, QFont, QFontMetrics, Qt)
@@ -991,6 +993,28 @@ def _make_pic0(title, description, esrb, QImage, QPainter, QPainterPath, QColor,
return _save(img)
def _wrap_elided(fm, text, width, max_lines, Qt):
"""Word-wrap ``text`` to ``width`` px, eliding the final line when it runs
past ``max_lines``. Returns a list of up to ``max_lines`` strings."""
words = text.split()
lines = []
cur = ""
for i, w in enumerate(words):
cand = (cur + " " + w).strip() if cur else w
if fm.horizontalAdvance(cand) <= width:
cur = cand
continue
if len(lines) == max_lines - 1:
rest = " ".join([cur] + words[i:]) if cur else " ".join(words[i:])
lines.append(fm.elidedText(rest, Qt.ElideRight, width))
return lines
lines.append(cur)
cur = w
if cur:
lines.append(cur)
return lines[:max_lines]
def _draw_ps_glyphs(p, x, y, size, color, QRectF, QPointF, QPolygonF, QPen, Qt):
"""Draw the four PlayStation face-button glyphs in a 2x2 grid."""
cell = size / 2.0
@@ -1133,9 +1157,17 @@ def fetch_cover(name, release_id, system, timeout=10, quick=False):
if data is not None:
log.info("cover %r <- manual", name)
elif system != "videos":
# 2. Games/PS1: libretro (full box art) first, then the shipped
# OpenVGDB bundle (PSP only, offline), then ScreenScraper (non-quick),
# then Wikipedia (keyless, non-quick), then IGDB last.
# 2. PS1: IGDB first — its covers are clean box art without the
# PlayStation banner that libretro/ScreenScraper thumbnails bake in
# (redundant with our ICON0 frame). Games: libretro first, then the
# shipped OpenVGDB bundle (offline), then ScreenScraper (non-quick),
# then Wikipedia (keyless), then IGDB last.
data = None
if system == "ps1" and not quick and time.time() < deadline:
data = _fetch_igdb_cover(name, t, system=system)
if data is not None:
log.info("cover %r <- igdb", name)
if data is None:
data = _fetch_libretro(name, t, system=system, indexed_only=quick)
if data is not None:
log.info("cover %r <- libretro", name)
@@ -1153,12 +1185,12 @@ def fetch_cover(name, release_id, system, timeout=10, quick=False):
data = _fetch_wikipedia_cover(name, t)
if data is not None:
log.info("cover %r <- wikipedia", name)
if data is None and time.time() < deadline:
if data is None and system != "ps1" and time.time() < deadline:
data = _fetch_igdb_cover(name, t, system=system)
if data is not None:
if system == "games":
# IGDB only has cropped 3:4 PSP key art; composite it
# into the full PSP cover template (header + artwork).
# IGDB only has cropped 3:4 PSP key art; composite
# it into the full PSP cover template.
data = compose_game_cover(data)
log.info("cover %r <- igdb", name)