[Banner] Keep horizontal user banner crops inside the artwork (#7742)

This commit is contained in:
Bryce! 2026-11-04 11:08:54 -05:00 • committed by GitHub
parent d944273335
commit e558c0dffa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 139 additions and 32 deletions

View file

@ -2,6 +2,8 @@
#include "libcockatrice/card/card_info.h"
#include <QRect>
#include <QSize>
#include <QTransform>
#include <libcockatrice/card/printing/exact_card.h>
#include <qnamespace.h>
@ -18,4 +20,23 @@ QPixmap rotateSidewaysLayoutArt(const QPixmap &art, const ExactCard &card)
transform.rotate(90);
return art.transformed(transform, Qt::SmoothTransformation);
}
} // namespace CardArtUtils
QPixmap cropCardArt(const QPixmap &art, const ExactCard &card)
{
if (art.isNull()) {
return {};
}
const QPixmap source = rotateSidewaysLayoutArt(art, card);
const bool landscape = card.getInfo().getUiAttributes().landscapeOrientation;
const QSize size = source.size();
const int marginX = size.width() * 0.07;
// Landscape name boxes extend below 5% of the upright image. Remove the
// whole box here, rather than relying on the banner's narrow viewport to
// hide it: the same saved offset is also used by the taller profile popup.
const int topMargin = size.height() * (landscape ? 0.15 : 0.11);
const int bottomMargin = size.height() * 0.45;
const QRect crop(marginX, topMargin, size.width() - 2 * marginX, size.height() - topMargin - bottomMargin);
return source.copy(crop.intersected(source.rect()));
}
} // namespace CardArtUtils

View file

@ -20,6 +20,13 @@ namespace CardArtUtils
* @return @p art rotated 90° clockwise for sideways-layout cards, else @p art.
*/
QPixmap rotateSidewaysLayoutArt(const QPixmap &art, const ExactCard &card);
/**
* Return the upright artwork used by banner previews, user rows and profile
* popups. The crop excludes conventional name and rules boxes before callers apply
* their saved pan and zoom, so a taller popup cannot expose the card frame.
*/
QPixmap cropCardArt(const QPixmap &art, const ExactCard &card);
} // namespace CardArtUtils
#endif // CARD_ART_UTILS_H
#endif // CARD_ART_UTILS_H

View file

@ -12,7 +12,6 @@
#include <QChar>
#include <QMetaObject>
#include <QPointer>
#include <QRect>
#include <QSize>
#include <QStringList>
#include <libcockatrice/card/database/card_database_manager.h>
@ -66,27 +65,6 @@ void UserCardArtProvider::requestCardArt(const QString &userName, const QString
processQueue();
}
QPixmap UserCardArtProvider::cropCardArt(const QPixmap &fullRes, const ExactCard &card)
{
QPixmap source = fullRes;
// Sideways-layout cards (plane, siege/battle, split) store their landscape
// artwork rotated 90° inside a portrait frame. Rotate it upright first so
// the crop below lands on the horizontal art, mirroring the way
// CardInfoPictureWidget displays these cards.
const bool landscape = card.getInfo().getUiAttributes().landscapeOrientation;
source = CardArtUtils::rotateSidewaysLayoutArt(source, card);
const QSize sz = source.size();
const int marginX = sz.width() * 0.07;
const int topMargin = landscape ? sz.height() * 0.05 : sz.height() * 0.11;
const int bottomMargin = landscape ? sz.height() * 0.42 : sz.height() * 0.45;
const QRect artRect(marginX, topMargin, sz.width() - 2 * marginX, sz.height() - topMargin - bottomMargin);
return source.copy(artRect.intersected(source.rect()));
}
void UserCardArtProvider::insertIntoCache(const QString &key, const QPixmap &pixmap)
{
if (pixmap.isNull()) {
@ -134,7 +112,7 @@ void UserCardArtProvider::processQueue()
// Synchronous hit (already loaded/on disk)
if (!fullRes.isNull()) {
insertIntoCache(key, cropCardArt(fullRes, card));
insertIntoCache(key, CardArtUtils::cropCardArt(fullRes, card));
pending.remove(key);
emit cardArtUpdated(userName);
@ -158,7 +136,7 @@ void UserCardArtProvider::processQueue()
CardPictureLoader::getPixmap(fullRes, card, QSize(745, 1040));
if (!fullRes.isNull()) {
self->insertIntoCache(key, self->cropCardArt(fullRes, card));
self->insertIntoCache(key, CardArtUtils::cropCardArt(fullRes, card));
}
self->pending.remove(key);
@ -172,4 +150,4 @@ void UserCardArtProvider::processQueue()
// Stop here. We'll continue when the async load finishes.
return;
}
}
}

View file

@ -10,8 +10,6 @@
#include <QString>
#include <qtmetamacros.h>
class ExactCard;
class UserCardArtProvider : public QObject
{
Q_OBJECT
@ -21,7 +19,6 @@ public:
void requestCardArt(const QString &userName, const QString &cardName, const QString &providerId);
const QMap<QString, QPixmap> &cache() const;
static QPixmap cropCardArt(const QPixmap &fullRes, const ExactCard &card);
signals:
void cardArtUpdated(const QString &userName);

View file

@ -2,6 +2,7 @@
#include "../../../card_picture_loader/card_picture_loader.h"
#include "../../cards/art_crop_attribution.h"
#include "../../cards/card_art_utils.h"
#include "../../utility/completer_utils.h"
#include "card_database_display_model.h"
#include "card_database_model.h"
@ -10,7 +11,6 @@
#include "libcockatrice/card/printing/exact_card.h"
#include "libcockatrice/card/printing/printing_info.h"
#include "libcockatrice/card/set/card_set.h"
#include "user_card_art_provider.h"
#include "user_list_painter.h"
#include <QBrush>
@ -580,7 +580,7 @@ void UserCardArtSettingsDialog::reloadPreview()
return;
}
currentPixmap = UserCardArtProvider::cropCardArt(fullRes, card);
currentPixmap = CardArtUtils::cropCardArt(fullRes, card);
preview->setPixmap(currentPixmap);
preview->setParams(currentParams);