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:
+51
-19
@@ -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,
|
_draw_ps_glyphs(p, W - 34, 12, 22, QColor(200, 200, 205), QRectF, QPointF,
|
||||||
QPolygonF, QPen, Qt)
|
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 = QFont("DejaVu Sans")
|
||||||
f_title.setPixelSize(19)
|
f_title.setPixelSize(19)
|
||||||
f_title.setBold(True)
|
f_title.setBold(True)
|
||||||
p.setFont(f_title)
|
p.setFont(f_title)
|
||||||
p.setPen(QColor(255, 255, 255))
|
p.setPen(QColor(255, 255, 255))
|
||||||
p.drawText(QRectF(18, 16, W - 64, 28), Qt.AlignLeft | Qt.AlignVCenter,
|
title_width = W - 70
|
||||||
title or "")
|
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:
|
if description:
|
||||||
f_desc = QFont("DejaVu Sans")
|
f_desc = QFont("DejaVu Sans")
|
||||||
f_desc.setPixelSize(12)
|
f_desc.setPixelSize(12)
|
||||||
p.setFont(f_desc)
|
p.setFont(f_desc)
|
||||||
p.setPen(QColor(215, 215, 215))
|
p.setPen(QColor(215, 215, 215))
|
||||||
text = description.strip()
|
|
||||||
fm = QFontMetrics(f_desc)
|
fm = QFontMetrics(f_desc)
|
||||||
# Rough 3-line budget (~40 chars/line at 12px across 272px).
|
lines = _wrap_elided(fm, description.strip(), W - 36, 3, Qt)
|
||||||
if fm.horizontalAdvance(text) > 3 * (W - 36):
|
y = 46
|
||||||
text = text[:130].rstrip() + "\u2026"
|
for line in lines:
|
||||||
p.drawText(QRectF(18, 46, W - 36, 74),
|
p.drawText(QRectF(18, y, W - 36, 16), Qt.AlignLeft | Qt.AlignVCenter, line)
|
||||||
Qt.AlignLeft | Qt.AlignTop | Qt.TextWordWrap, text)
|
y += 16
|
||||||
|
|
||||||
# ESRB badge (bottom-left) + caption.
|
# ESRB badge (bottom-left) + caption.
|
||||||
if esrb:
|
if esrb:
|
||||||
@@ -981,9 +984,8 @@ def _make_pic0(title, description, esrb, QImage, QPainter, QPainterPath, QColor,
|
|||||||
if badge:
|
if badge:
|
||||||
_draw_esrb(p, badge, 18, 140, QRectF, QColor, QFont, QFontMetrics, QPen, Qt)
|
_draw_esrb(p, badge, 18, 140, QRectF, QColor, QFont, QFontMetrics, QPen, Qt)
|
||||||
|
|
||||||
# Platform badges (bottom-right).
|
# Platform badge (bottom-right). Only PSP for now; PS3/PS4 packaging is a
|
||||||
_draw_platform_badge(p, "PS3", W - 14 - 64, 146, QColor(94, 146, 210),
|
# separate future feature.
|
||||||
QRectF, QColor, QFont, QFontMetrics, Qt)
|
|
||||||
_draw_platform_badge(p, "PSP", W - 14 - 30, 146, QColor(212, 175, 55),
|
_draw_platform_badge(p, "PSP", W - 14 - 30, 146, QColor(212, 175, 55),
|
||||||
QRectF, QColor, QFont, QFontMetrics, Qt)
|
QRectF, QColor, QFont, QFontMetrics, Qt)
|
||||||
|
|
||||||
@@ -991,6 +993,28 @@ def _make_pic0(title, description, esrb, QImage, QPainter, QPainterPath, QColor,
|
|||||||
return _save(img)
|
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):
|
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."""
|
"""Draw the four PlayStation face-button glyphs in a 2x2 grid."""
|
||||||
cell = size / 2.0
|
cell = size / 2.0
|
||||||
@@ -1133,9 +1157,17 @@ def fetch_cover(name, release_id, system, timeout=10, quick=False):
|
|||||||
if data is not None:
|
if data is not None:
|
||||||
log.info("cover %r <- manual", name)
|
log.info("cover %r <- manual", name)
|
||||||
elif system != "videos":
|
elif system != "videos":
|
||||||
# 2. Games/PS1: libretro (full box art) first, then the shipped
|
# 2. PS1: IGDB first — its covers are clean box art without the
|
||||||
# OpenVGDB bundle (PSP only, offline), then ScreenScraper (non-quick),
|
# PlayStation banner that libretro/ScreenScraper thumbnails bake in
|
||||||
# then Wikipedia (keyless, non-quick), then IGDB last.
|
# (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)
|
data = _fetch_libretro(name, t, system=system, indexed_only=quick)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
log.info("cover %r <- libretro", name)
|
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)
|
data = _fetch_wikipedia_cover(name, t)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
log.info("cover %r <- wikipedia", name)
|
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)
|
data = _fetch_igdb_cover(name, t, system=system)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
if system == "games":
|
if system == "games":
|
||||||
# IGDB only has cropped 3:4 PSP key art; composite it
|
# IGDB only has cropped 3:4 PSP key art; composite
|
||||||
# into the full PSP cover template (header + artwork).
|
# it into the full PSP cover template.
|
||||||
data = compose_game_cover(data)
|
data = compose_game_cover(data)
|
||||||
log.info("cover %r <- igdb", name)
|
log.info("cover %r <- igdb", name)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user