Add color utilities.
This commit is contained in:
parent
3ac572edeb
commit
298d5e9848
@ -7,6 +7,8 @@
|
|||||||
#include <QtZlib/zlib.h>
|
#include <QtZlib/zlib.h>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
public:
|
public:
|
||||||
@ -22,6 +24,178 @@ public:
|
|||||||
testFile.close();
|
testFile.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
static quint8 ReverseBits(quint8 b) {
|
||||||
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
static QIcon CreateAssetIcon(const QString& name, QColor color = QColor()) {
|
||||||
|
constexpr int iconSize = 32;
|
||||||
|
constexpr int padding = 4;
|
||||||
|
|
||||||
|
QImage result(iconSize, iconSize, QImage::Format_ARGB32);
|
||||||
|
result.fill(Qt::transparent);
|
||||||
|
|
||||||
|
if (!color.isValid()) {
|
||||||
|
color = Utils::StringToColor(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainter painter(&result);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
QBrush brush(color);
|
||||||
|
brush.setStyle(Qt::SolidPattern);
|
||||||
|
painter.setBrush(color);
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.drawRoundedRect(0, 0, iconSize, iconSize, 4, 4);
|
||||||
|
|
||||||
|
// Set base font
|
||||||
|
QFont font("Heavitas");
|
||||||
|
font.setPixelSize(iconSize); // Start large
|
||||||
|
painter.setFont(font);
|
||||||
|
|
||||||
|
// Adjust font size to fit text width (only reduce, not increase)
|
||||||
|
QFontMetrics fm(font);
|
||||||
|
int textWidth = fm.horizontalAdvance(name);
|
||||||
|
while (textWidth > iconSize - 2 * padding && font.pixelSize() > 1) {
|
||||||
|
font.setPixelSize(font.pixelSize() - 1);
|
||||||
|
painter.setFont(font);
|
||||||
|
fm = QFontMetrics(font);
|
||||||
|
textWidth = fm.horizontalAdvance(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate vertical scaling factor
|
||||||
|
qreal scaleY = 1.2 * iconSize / fm.height();
|
||||||
|
|
||||||
|
// Apply transform: scale vertically, center align
|
||||||
|
painter.save();
|
||||||
|
painter.translate(iconSize / 2.0, iconSize / 2.0);
|
||||||
|
painter.scale(1.0, scaleY);
|
||||||
|
painter.translate(-iconSize / 2.0, -iconSize / 2.0);
|
||||||
|
|
||||||
|
QRect textRect(0, 0, iconSize, iconSize);
|
||||||
|
|
||||||
|
// Draw stroke
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
for (int dx = 0; dx <= 1; ++dx) {
|
||||||
|
for (int dy = 0; dy <= 1; ++dy) {
|
||||||
|
if (dx || dy)
|
||||||
|
painter.drawText(textRect.translated(dx, dy), Qt::AlignCenter, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw main text
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.drawText(textRect, Qt::AlignCenter, name);
|
||||||
|
painter.restore();
|
||||||
|
|
||||||
|
// Debug output
|
||||||
|
QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/");
|
||||||
|
result.save(QDir().absoluteFilePath(".") + "/icons/" + name + ".png");
|
||||||
|
|
||||||
|
return QIcon(QPixmap::fromImage(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QIcon CreateGameIcon(const int gameNum, QColor color = QColor()) {
|
||||||
|
constexpr int size = 32;
|
||||||
|
constexpr int padding = 4; // pixels of padding on all sides
|
||||||
|
const int contentSize = size - 2 * padding;
|
||||||
|
|
||||||
|
QImage result(size, size, QImage::Format_ARGB32);
|
||||||
|
result.fill(Qt::transparent);
|
||||||
|
|
||||||
|
if (!color.isValid()) {
|
||||||
|
color = Utils::StringToColor(QString("COD%1").arg(gameNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainter painter(&result);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
painter.setRenderHint(QPainter::TextAntialiasing, false);
|
||||||
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
painter.setBrush(color);
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.drawRoundedRect(0, 0, size, size, 4, 4);
|
||||||
|
|
||||||
|
// === Font Setup ===
|
||||||
|
QFont codFont("Heavitas");
|
||||||
|
codFont.setPixelSize(contentSize * 0.40);
|
||||||
|
|
||||||
|
QFont numFont("Heavitas");
|
||||||
|
numFont.setPixelSize(contentSize);
|
||||||
|
|
||||||
|
// === Layout Areas (inside padding) ===
|
||||||
|
const QRect contentRect(padding, padding, contentSize, contentSize);
|
||||||
|
const int col1 = contentRect.left();
|
||||||
|
const int col2 = contentRect.left() + contentRect.width() / 3;
|
||||||
|
|
||||||
|
const int thirdH = contentRect.height() / 3;
|
||||||
|
const QRect codRects[] = {
|
||||||
|
QRect(col1, 2 + contentRect.top(), contentRect.width() / 3, thirdH),
|
||||||
|
QRect(col1, contentRect.top() + thirdH, contentRect.width() / 3, thirdH),
|
||||||
|
QRect(col1, -2 + contentRect.top() + 2 * thirdH, contentRect.width() / 3, thirdH),
|
||||||
|
};
|
||||||
|
|
||||||
|
const QRect numRect(col2, contentRect.top(), contentRect.width() * 2 / 3, contentRect.height());
|
||||||
|
|
||||||
|
const QString codLetters[] = { "C", "O", "D" };
|
||||||
|
const QString numText = QString::number(gameNum);
|
||||||
|
|
||||||
|
// === Stroke pass ===
|
||||||
|
for (int dx = -1; dx <= 2; ++dx) {
|
||||||
|
for (int dy = -1; dy <= 2; ++dy) {
|
||||||
|
if (dx == 0 && dy == 0) continue;
|
||||||
|
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
painter.setFont(codFont);
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
painter.drawText(codRects[i].translated(dx, dy), Qt::AlignCenter, codLetters[i]);
|
||||||
|
|
||||||
|
painter.setFont(numFont);
|
||||||
|
painter.drawText(numRect.translated(dx, dy), Qt::AlignCenter, numText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Fill pass ===
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(codFont);
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
painter.drawText(codRects[i], Qt::AlignCenter, codLetters[i]);
|
||||||
|
|
||||||
|
painter.setFont(numFont);
|
||||||
|
painter.drawText(numRect, Qt::AlignCenter, numText);
|
||||||
|
|
||||||
|
// Save & return icon
|
||||||
|
QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/");
|
||||||
|
result.save(QDir().absoluteFilePath(".") + QString("/icons/COD%1.png").arg(gameNum));
|
||||||
|
|
||||||
|
return QIcon(QPixmap::fromImage(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static QColor StringToColor(const QString& str) {
|
||||||
|
// 1. Hash the string using Qt's built-in hash (MD5, SHA1, or any)
|
||||||
|
QByteArray hash = QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5);
|
||||||
|
|
||||||
|
// 2. Use first 3 bytes of hash for RGB
|
||||||
|
// This guarantees same string = same color every time
|
||||||
|
int r = static_cast<unsigned char>(hash[0]);
|
||||||
|
int g = static_cast<unsigned char>(hash[1]);
|
||||||
|
int b = static_cast<unsigned char>(hash[2]);
|
||||||
|
|
||||||
|
// 3. Optionally adjust brightness or saturation to avoid too dark/light colors
|
||||||
|
QColor color(r, g, b);
|
||||||
|
if (color.value() < 128) { // brighten if too dark
|
||||||
|
color = color.lighter(150);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
static bool ReadUntilString(QDataStream* stream, const QString& targetString) {
|
static bool ReadUntilString(QDataStream* stream, const QString& targetString) {
|
||||||
if (!stream || targetString.isEmpty()) {
|
if (!stream || targetString.isEmpty()) {
|
||||||
return false; // Invalid input
|
return false; // Invalid input
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user