mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 09:33:25 -08:00
Compare commits
7 commits
c9685076b9
...
b6b6f1ea5d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6b6f1ea5d | ||
|
|
51e42a50ca | ||
|
|
31fb173881 | ||
|
|
c2ecd58e99 | ||
|
|
7e71d424f1 | ||
|
|
95e5cda296 | ||
|
|
42a0352477 |
4 changed files with 33 additions and 24 deletions
|
|
@ -85,9 +85,9 @@ bool hasSentinel(const QByteArray &svg)
|
|||
return !svg.isEmpty() && QString::fromUtf8(svg).contains(QStringLiteral("currentColor"), Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QString cacheKey(const QString &path, const QByteArray &color, const QSize &size, qreal devicePixelRatio)
|
||||
QString cacheKey(const QString &path, const QByteArray &variant, const QSize &size, qreal devicePixelRatio)
|
||||
{
|
||||
return path + QLatin1Char('|') + QString::fromLatin1(color) + QLatin1Char('|') + QString::number(size.width()) +
|
||||
return path + QLatin1Char('|') + QString::fromLatin1(variant) + QLatin1Char('|') + QString::number(size.width()) +
|
||||
QLatin1Char('x') + QString::number(size.height()) + QLatin1Char('@') + QString::number(devicePixelRatio);
|
||||
}
|
||||
|
||||
|
|
@ -97,9 +97,11 @@ QString cacheKey(const QString &path, const QByteArray &color, const QSize &size
|
|||
* Qt's SVG renderer has no ambient color, so the sentinel is substituted from
|
||||
* the current palette on every pixmap request. Asset resolution, the file bytes
|
||||
* and the intrinsic size are cached until the theme changes: a repaint then
|
||||
* does no file I/O at all. The render cache is keyed by resolved path, palette
|
||||
* color, pixel size and DPR, so a palette change produces new keys instead of
|
||||
* reusing art built under the previous palette.
|
||||
* does no file I/O at all. The render cache is keyed by resolved path and pixel
|
||||
* size plus a variant: the palette color for sentinel SVGs, the icon mode for
|
||||
* assets that carry their own colors. A palette change therefore produces new
|
||||
* keys instead of reusing art built under the previous palette, and the
|
||||
* non-sentinel path (raster overrides, plain SVGs) is cached like any other.
|
||||
*/
|
||||
class ThemeSvgIconEngine final : public QObject, public QIconEngine
|
||||
{
|
||||
|
|
@ -231,24 +233,26 @@ private:
|
|||
QPixmap render(const QSize &pixelSize, qreal devicePixelRatio, QIcon::Mode mode) const
|
||||
{
|
||||
ensureResolved();
|
||||
if (!resolvedHasSentinel) {
|
||||
// Authored art carries its own colors: use Qt's normal loader so
|
||||
// raster overrides and non-SVG assets keep working.
|
||||
QPixmap pixmap = fromAsset(pixelSize, mode);
|
||||
if (!pixmap.isNull()) {
|
||||
pixmap.setDevicePixelRatio(devicePixelRatio);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
const QByteArray color = sentinelColor(mode, role);
|
||||
const QString key = cacheKey(resolvedPath, color, pixelSize, devicePixelRatio);
|
||||
// Same cache for both paths: sentinel art varies by palette color, art
|
||||
// with its own colors varies by mode (Disabled is generated). A color
|
||||
// variant is never a bare digit, so the two key spaces cannot collide.
|
||||
const QByteArray variant =
|
||||
resolvedHasSentinel ? sentinelColor(mode, role) : QByteArray::number(static_cast<int>(mode));
|
||||
const QString key = cacheKey(resolvedPath, variant, pixelSize, devicePixelRatio);
|
||||
const auto cached = cache.constFind(key);
|
||||
if (cached != cache.constEnd()) {
|
||||
return cached.value();
|
||||
}
|
||||
|
||||
QPixmap pixmap = renderSvg(resolveSvgColorSentinel(resolvedSvg, color), pixelSize, devicePixelRatio);
|
||||
QPixmap pixmap;
|
||||
if (resolvedHasSentinel) {
|
||||
pixmap = renderSvg(resolveSvgColorSentinel(resolvedSvg, variant), pixelSize, devicePixelRatio);
|
||||
} else {
|
||||
// Authored art carries its own colors: use Qt's normal loader so
|
||||
// raster overrides and non-SVG assets keep working.
|
||||
pixmap = fromAsset(pixelSize, mode);
|
||||
}
|
||||
if (!pixmap.isNull()) {
|
||||
// Set the ratio before caching: assigning it to a cached pixmap
|
||||
// afterwards detaches (deep-copies) it on every paint.
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ const QString GamesModel::getGameCreatedString(const int secs)
|
|||
}
|
||||
|
||||
GamesModel::GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent)
|
||||
: QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes)
|
||||
: QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes),
|
||||
lockIcon(loadThemedIcon(QStringLiteral("icons/lock")))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -189,10 +190,9 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const
|
|||
return result.join(", ");
|
||||
}
|
||||
case Qt::DecorationRole: {
|
||||
// The themed icon follows the palette, so the lock also
|
||||
// switches to HighlightedText on a selected row, and the
|
||||
// item view paints it at the device pixel ratio.
|
||||
return gameentry.with_password() ? loadThemedIcon(QStringLiteral("icons/lock")) : QVariant();
|
||||
// One engine per model: it is palette- and theme-aware and
|
||||
// invalidates itself, so a repaint must not build a new one.
|
||||
return gameentry.with_password() ? lockIcon : QVariant();
|
||||
case Qt::TextAlignmentRole:
|
||||
return Qt::AlignLeft;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "game_type_map.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QModelIndex>
|
||||
|
|
@ -32,6 +33,7 @@ private:
|
|||
QList<ServerInfo_Game> gameList; /**< List of games currently displayed. */
|
||||
QMap<int, QString> rooms; /**< Map of room IDs to room names. */
|
||||
QMap<int, GameTypeMap> gameTypes; /**< Map of room IDs to available game types. */
|
||||
QIcon lockIcon; /**< Themed lock for password-protected games. */
|
||||
|
||||
static const int NUM_COLS = 8; /**< Number of columns in the table. */
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,11 @@ constexpr QByteArrayView SENTINEL = "currentColor";
|
|||
/// its char overload cannot match a word.
|
||||
qsizetype findSentinel(const QByteArray &bytes, qsizetype from)
|
||||
{
|
||||
for (qsizetype i = from; i + SENTINEL.size() <= bytes.size(); ++i) {
|
||||
if (bytes.sliced(i, SENTINEL.size()).compare(SENTINEL, Qt::CaseInsensitive) == 0) {
|
||||
// QByteArrayView::sliced() is a view, so the scan does not allocate a copy
|
||||
// at every byte position (QByteArray::sliced() would).
|
||||
const QByteArrayView view(bytes);
|
||||
for (qsizetype i = from; i + SENTINEL.size() <= view.size(); ++i) {
|
||||
if (view.sliced(i, SENTINEL.size()).compare(SENTINEL, Qt::CaseInsensitive) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue