diff --git a/cockatrice/src/interface/pixel_map_generator.cpp b/cockatrice/src/interface/pixel_map_generator.cpp index 5bfba1c8a..9b8c4bcdc 100644 --- a/cockatrice/src/interface/pixel_map_generator.cpp +++ b/cockatrice/src/interface/pixel_map_generator.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -418,6 +419,57 @@ QPixmap DropdownIconPixmapGenerator::generatePixmap(int height, bool expanded) QMap DropdownIconPixmapGenerator::pmCache; +namespace +{ +/// Longest side mana symbols are rendered at before being scaled to their final size. +constexpr int MASTER_ICON_SIZE = 128; + +QString manaSymbolCacheKey(const QString &symbol, const QSize &size) +{ + return symbol + QLatin1Char('|') + QString::number(size.width()) + QLatin1Char('x') + + QString::number(size.height()); +} +} // namespace + +const QPixmap &ManaSymbolPixmapGenerator::masterIcon(const QString &symbol) +{ + auto it = masterCache.constFind(symbol); + if (it != masterCache.constEnd()) { + return it.value(); + } + + QImageReader reader("theme:icons/mana/" + symbol); + QSize sourceSize = reader.size(); + if (!sourceSize.isEmpty()) { + sourceSize.scale(QSize(MASTER_ICON_SIZE, MASTER_ICON_SIZE), Qt::KeepAspectRatio); + reader.setScaledSize(sourceSize); + } + const QPixmap rendered = QPixmap::fromImageReader(&reader); + + return masterCache.insert(symbol, rendered).value(); +} + +QPixmap ManaSymbolPixmapGenerator::generatePixmap(const QString &symbol, const QSize &size) +{ + const QString key = manaSymbolCacheKey(symbol, size); + auto it = scaledCache.constFind(key); + if (it != scaledCache.constEnd()) { + return it.value(); + } + + const QPixmap &icon = masterIcon(symbol); + if (icon.isNull()) { + return {}; + } + + QPixmap scaled = icon.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + scaledCache.insert(key, scaled); + return scaled; +} + +QHash ManaSymbolPixmapGenerator::masterCache; +QHash ManaSymbolPixmapGenerator::scaledCache; + QPixmap loadColorAdjustedPixmap(const QString &name) { if (qApp->palette().windowText().color().lightness() > 200) { diff --git a/cockatrice/src/interface/pixel_map_generator.h b/cockatrice/src/interface/pixel_map_generator.h index 22f44d8db..17720166a 100644 --- a/cockatrice/src/interface/pixel_map_generator.h +++ b/cockatrice/src/interface/pixel_map_generator.h @@ -7,6 +7,7 @@ #ifndef PIXMAPGENERATOR_H #define PIXMAPGENERATOR_H +#include #include #include #include @@ -125,6 +126,34 @@ public: } }; +class ManaSymbolPixmapGenerator +{ +private: + static QHash masterCache; + static QHash scaledCache; + + /** + * @brief Renders \a symbol once at a fixed moderate size, so repeated scalings never + * re-rasterize the source file (SVG sources can be very expensive to rasterize). + */ + static const QPixmap &masterIcon(const QString &symbol); + +public: + /** + * @brief Returns a smooth-scaled rendering of the given mana symbol icon. + * + * Results are shared between all callers via a process-wide cache keyed by symbol + * and size, so scaling work is done once per distinct combination instead of once + * per widget creation or resize. + */ + static QPixmap generatePixmap(const QString &symbol, const QSize &size); + static void clear() + { + masterCache.clear(); + scaledCache.clear(); + } +}; + QPixmap loadColorAdjustedPixmap(const QString &name); #endif diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp index 973f532be..18011909f 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp @@ -1,57 +1,15 @@ #include "mana_symbol_widget.h" #include "../../../../client/settings/cache_settings.h" +#include "../../../pixel_map_generator.h" -#include -#include #include #include -namespace -{ -/// Longest side mana symbols are rendered at before being scaled to their final size. -constexpr int MASTER_ICON_SIZE = 128; - -QHash &scaledIconCache() -{ - static QHash cache; - return cache; -} - -/** - * @brief Renders \a symbol once at a fixed moderate size, so repeated scalings never - * re-rasterize the source file (SVG sources can be very expensive to rasterize). - */ -const QPixmap &masterIcon(const QString &symbol) -{ - static QHash cache; - auto it = cache.constFind(symbol); - if (it != cache.constEnd()) { - return it.value(); - } - - QImageReader reader("theme:icons/mana/" + symbol); - QSize sourceSize = reader.size(); - if (!sourceSize.isEmpty()) { - sourceSize.scale(QSize(MASTER_ICON_SIZE, MASTER_ICON_SIZE), Qt::KeepAspectRatio); - reader.setScaledSize(sourceSize); - } - const QPixmap rendered = QPixmap::fromImageReader(&reader); - - return cache.insert(symbol, rendered).value(); -} - -QString cacheKey(const QString &symbol, const QSize &size) -{ - return symbol + QLatin1Char('|') + QString::number(size.width()) + QLatin1Char('x') + - QString::number(size.height()); -} -} // namespace - ManaSymbolWidget::ManaSymbolWidget(QWidget *parent, QString _symbol, bool _isActive, bool _mayBeToggled) : QLabel(parent), symbol(std::move(_symbol)), isActive(_isActive), mayBeToggled(_mayBeToggled) { - setPixmap(getCachedScaledIcon(symbol, QSize(50, 50))); + setPixmap(ManaSymbolPixmapGenerator::generatePixmap(symbol, QSize(50, 50))); setMaximumWidth(50); // Initialize opacity effect @@ -64,24 +22,6 @@ ManaSymbolWidget::ManaSymbolWidget(QWidget *parent, QString _symbol, bool _isAct &ManaSymbolWidget::updateOpacity); } -QPixmap ManaSymbolWidget::getCachedScaledIcon(const QString &symbol, const QSize &size) -{ - const QString key = cacheKey(symbol, size); - auto it = scaledIconCache().constFind(key); - if (it != scaledIconCache().constEnd()) { - return it.value(); - } - - const QPixmap &icon = masterIcon(symbol); - if (icon.isNull()) { - return {}; - } - - QPixmap scaled = icon.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); - scaledIconCache().insert(key, scaled); - return scaled; -} - void ManaSymbolWidget::toggleSymbol() { setColorActive(!isActive); @@ -132,5 +72,5 @@ void ManaSymbolWidget::resizeEvent(QResizeEvent *event) return; } - setPixmap(getCachedScaledIcon(symbol, newSize)); + setPixmap(ManaSymbolPixmapGenerator::generatePixmap(symbol, newSize)); } diff --git a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h index dae13f7b9..705873dff 100644 --- a/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h +++ b/cockatrice/src/interface/widgets/cards/additional_info/mana_symbol_widget.h @@ -33,15 +33,6 @@ public: return symbol[0]; } - /** - * @brief Returns a smooth-scaled rendering of the given mana symbol icon. - * - * Results are shared between all instances via a process-wide cache keyed by symbol - * and size, so scaling work is done once per distinct combination instead of once per - * widget creation or resize. - */ - static QPixmap getCachedScaledIcon(const QString &symbol, const QSize &size); - public slots: void resizeEvent(QResizeEvent *event) override; void mousePressEvent(QMouseEvent *event) override; diff --git a/cockatrice/src/interface/widgets/utility/card_completer_delegate.cpp b/cockatrice/src/interface/widgets/utility/card_completer_delegate.cpp index 6cf096cd4..29bf2263e 100644 --- a/cockatrice/src/interface/widgets/utility/card_completer_delegate.cpp +++ b/cockatrice/src/interface/widgets/utility/card_completer_delegate.cpp @@ -1,5 +1,6 @@ #include "card_completer_delegate.h" +#include "../../pixel_map_generator.h" #include "../cards/additional_info/mana_cost_widget.h" #include @@ -84,7 +85,6 @@ QColor CardCompleterDelegate::accentForColors(const QString &colors) CardCompleterDelegate::CardCompleterDelegate(QObject *parent) : QStyledItemDelegate(parent) { - symbolCache.setMaxCost(64); setCodeCache.setMaxCost(64); } @@ -108,36 +108,16 @@ QSize CardCompleterDelegate::sizeHint(const QStyleOptionViewItem &option, const // Mana symbol painting // --------------------------------------------------------------------------- -const QPixmap *CardCompleterDelegate::cachedSymbolPixmap(const QString &symbol, int size) const -{ - const QString key = symbol + QString::number(size); - - if (symbolCache.contains(key)) { - return symbolCache[key]; - } - - QPixmap src(QString("theme:icons/mana/%1").arg(symbol)); - - if (!src.isNull()) { - auto *pm = new QPixmap(src.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - - symbolCache.insert(key, pm); - return pm; - } - - return nullptr; -} - // --------------------------------------------------------------------------- void CardCompleterDelegate::drawManaSymbol(QPainter *p, QPoint centre, const QString &symbol, int radius) const { const QRect pip(centre.x() - radius, centre.y() - radius, radius * 2, radius * 2); - const QPixmap *px = cachedSymbolPixmap(symbol, radius * 2); + const QPixmap px = ManaSymbolPixmapGenerator::generatePixmap(symbol, QSize(radius * 2, radius * 2)); - if (px && !px->isNull()) { - p->drawPixmap(pip, *px); + if (!px.isNull()) { + p->drawPixmap(pip, px); return; } diff --git a/cockatrice/src/interface/widgets/utility/card_completer_delegate.h b/cockatrice/src/interface/widgets/utility/card_completer_delegate.h index 18661a21b..78667f56b 100644 --- a/cockatrice/src/interface/widgets/utility/card_completer_delegate.h +++ b/cockatrice/src/interface/widgets/utility/card_completer_delegate.h @@ -31,9 +31,6 @@ public: QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; private: - // Mana symbol pixmaps, loaded once and cached - mutable QCache symbolCache; - // Set short codes, resolved once per card name and cached mutable QCache setCodeCache; @@ -47,9 +44,6 @@ private: // adventure costs ("1W // W") are drawn as separate groups. Returns the left-most x used int drawManaCost(QPainter *p, const QRect &row, const QString &manaCost, int radius) const; - // Load (or return cached) a mana icon pixmap; falls back to painted circle - const QPixmap *cachedSymbolPixmap(const QString &symbol, int size) const; - // Resolve the preferred printing's set short code for a card QString setCodeForCard(const QSharedPointer &card) const; diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 814da9808..84d5d175f 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -390,6 +390,7 @@ int main(int argc, char *argv[]) PingPixmapGenerator::clear(); CountryPixmapGenerator::clear(); UserLevelPixmapGenerator::clear(); + ManaSymbolPixmapGenerator::clear(); return ret; }