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);
|
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);
|
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
|
* 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
|
* 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
|
* 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
|
* does no file I/O at all. The render cache is keyed by resolved path and pixel
|
||||||
* color, pixel size and DPR, so a palette change produces new keys instead of
|
* size plus a variant: the palette color for sentinel SVGs, the icon mode for
|
||||||
* reusing art built under the previous palette.
|
* 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
|
class ThemeSvgIconEngine final : public QObject, public QIconEngine
|
||||||
{
|
{
|
||||||
|
|
@ -231,24 +233,26 @@ private:
|
||||||
QPixmap render(const QSize &pixelSize, qreal devicePixelRatio, QIcon::Mode mode) const
|
QPixmap render(const QSize &pixelSize, qreal devicePixelRatio, QIcon::Mode mode) const
|
||||||
{
|
{
|
||||||
ensureResolved();
|
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);
|
// Same cache for both paths: sentinel art varies by palette color, art
|
||||||
const QString key = cacheKey(resolvedPath, color, pixelSize, devicePixelRatio);
|
// 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);
|
const auto cached = cache.constFind(key);
|
||||||
if (cached != cache.constEnd()) {
|
if (cached != cache.constEnd()) {
|
||||||
return cached.value();
|
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()) {
|
if (!pixmap.isNull()) {
|
||||||
// Set the ratio before caching: assigning it to a cached pixmap
|
// Set the ratio before caching: assigning it to a cached pixmap
|
||||||
// afterwards detaches (deep-copies) it on every paint.
|
// 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)
|
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(", ");
|
return result.join(", ");
|
||||||
}
|
}
|
||||||
case Qt::DecorationRole: {
|
case Qt::DecorationRole: {
|
||||||
// The themed icon follows the palette, so the lock also
|
// One engine per model: it is palette- and theme-aware and
|
||||||
// switches to HighlightedText on a selected row, and the
|
// invalidates itself, so a repaint must not build a new one.
|
||||||
// item view paints it at the device pixel ratio.
|
return gameentry.with_password() ? lockIcon : QVariant();
|
||||||
return gameentry.with_password() ? loadThemedIcon(QStringLiteral("icons/lock")) : QVariant();
|
|
||||||
case Qt::TextAlignmentRole:
|
case Qt::TextAlignmentRole:
|
||||||
return Qt::AlignLeft;
|
return Qt::AlignLeft;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "game_type_map.h"
|
#include "game_type_map.h"
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
#include <QIcon>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
|
@ -32,6 +33,7 @@ private:
|
||||||
QList<ServerInfo_Game> gameList; /**< List of games currently displayed. */
|
QList<ServerInfo_Game> gameList; /**< List of games currently displayed. */
|
||||||
QMap<int, QString> rooms; /**< Map of room IDs to room names. */
|
QMap<int, QString> rooms; /**< Map of room IDs to room names. */
|
||||||
QMap<int, GameTypeMap> gameTypes; /**< Map of room IDs to available game types. */
|
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. */
|
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.
|
/// its char overload cannot match a word.
|
||||||
qsizetype findSentinel(const QByteArray &bytes, qsizetype from)
|
qsizetype findSentinel(const QByteArray &bytes, qsizetype from)
|
||||||
{
|
{
|
||||||
for (qsizetype i = from; i + SENTINEL.size() <= bytes.size(); ++i) {
|
// QByteArrayView::sliced() is a view, so the scan does not allocate a copy
|
||||||
if (bytes.sliced(i, SENTINEL.size()).compare(SENTINEL, Qt::CaseInsensitive) == 0) {
|
// 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;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue