different take on hex string generator

with this approach the hex string generation can be optimized via
per-object or per-thread buffer (by passing it to qHexString()), that
is yet to be tested tho

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-03-28 09:47:55 +02:00
parent 0aa306b3f6
commit 32d252d3cf
10 changed files with 72 additions and 76 deletions

View file

@ -223,17 +223,21 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
QString key = QLatin1String("qt_")
+ HexString<quint64>(pm.cacheKey())
+ HexString<uint>(pe ? pe->mode : QIcon::Normal)
+ HexString<quint64>(QApplication::palette().cacheKey())
+ HexString<uint>(actualSize.width())
+ HexString<uint>(actualSize.height());
const QString key = qHexString(
"qt_icon_%lld_%d_%lld_%d_%d",
pm.cacheKey(),
static_cast<int>(pe ? pe->mode : QIcon::Normal),
QApplication::palette().cacheKey(),
actualSize.width(),
actualSize.height()
);
const QString key2 = key + QLatin1Char('_') + QChar(static_cast<uint>(mode));
if (mode == QIcon::Active) {
if (QPixmapCache::find(key + HexString<uint>(mode), pm))
if (QPixmapCache::find(key2, pm))
return pm; // horray
if (QPixmapCache::find(key + HexString<uint>(QIcon::Normal), pm)) {
const QString key3 = key + QLatin1Char('_') + QChar(static_cast<uint>(QIcon::Normal));
if (QPixmapCache::find(key + key3, pm)) {
QStyleOption opt(0);
opt.palette = QApplication::palette();
QPixmap active = QApplication::style()->generatedIconPixmap(QIcon::Active, pm, &opt);
@ -242,7 +246,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
}
}
if (!QPixmapCache::find(key + HexString<uint>(mode), pm)) {
if (!QPixmapCache::find(key2, pm)) {
if (pm.size() != actualSize)
pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (pe && pe->mode != mode && mode != QIcon::Normal) {
@ -252,7 +256,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
if (!generated.isNull())
pm = generated;
}
QPixmapCache::insert(key + HexString<uint>(mode), pm);
QPixmapCache::insert(key2, pm);
}
return pm;
}

View file

@ -429,11 +429,13 @@ QPixmap QIconLoaderEngineEntry::pixmap(const QSize &size, QIcon::Mode mode, QIco
}
int actualSize = qMin(size.width(), size.height());
QString key = QLatin1String("$qt_theme_")
+ HexString<qint64>(m_basePixmap.cacheKey())
+ HexString<int>(mode)
+ HexString<qint64>(qApp->palette().cacheKey())
+ HexString<int>(actualSize);
const QString key = qHexString(
"qt_theme_%lld_%d_%lld_%d",
m_basePixmap.cacheKey(),
static_cast<int>(mode),
qApp->palette().cacheKey(),
actualSize
);
QPixmap cachedPixmap;
if (QPixmapCache::find(key, &cachedPixmap)) {

View file

@ -561,11 +561,12 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
return false;
QFileInfo info(fileName);
QString key = QLatin1String("qt_pixmap")
+ info.absoluteFilePath()
+ HexString<uint>(info.lastModified().toTime_t())
+ HexString<quint64>(info.size())
+ HexString<uint>(data ? data->pixelType() : QPixmapData::PixmapType);
const QString key = qHexString(
"qt_pixmap_%lld_%lld_%d_",
info.lastModified().toTime_t(),
info.size(),
static_cast<int>(data ? data->pixelType() : QPixmapData::PixmapType)
) + info.absoluteFilePath();
// Note: If no extension is provided, we try to match the
// file against known plugin extensions

View file

@ -50,6 +50,7 @@
#include "qlocale.h"
#include "qdialog.h"
#include "qmath.h"
#include "qguicommon_p.h"
#include <limits.h>
#include <float.h>
@ -959,22 +960,6 @@ QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVar
return qvariant_cast<QPixmap>(variant);
}
// hacky but faster version of "QString::sprintf("%d-%d", i, enabled)"
static QString qPixmapSerial(quint64 i, bool enabled)
{
ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', ushort('0' + enabled) };
ushort *ptr = &arr[16];
while (i > 0) {
// hey - it's our internal representation, so use the ascii character after '9'
// instead of 'a' for hex
*(--ptr) = '0' + i % 16;
i >>= 4;
}
return QString((const QChar *)ptr, int(&arr[sizeof(arr) / sizeof(ushort)] - ptr));
}
/*!
\internal
Returns the selected version of the given \a pixmap using the given \a palette.
@ -983,7 +968,11 @@ static QString qPixmapSerial(quint64 i, bool enabled)
*/
QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
{
QString key = qPixmapSerial(pixmap.cacheKey(), enabled);
const QString key = qHexString(
"qt_itemdelegate_%lld_%d",
pixmap.cacheKey(),
static_cast<int>(enabled)
);
QPixmap *pm = QPixmapCache::find(key);
if (!pm) {
QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);

View file

@ -4956,9 +4956,10 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
{
const qreal radiusBase = qMax(qreal(1), maxRadius);
QString key = QLatin1String("WaveUnderline-")
+ pen.color().name()
+ HexString<qreal>(radiusBase);
const QString key = qHexString(
"qt_waveunderline_%f_",
static_cast<float>(radiusBase)
) + pen.color().name();
QPixmap pixmap;
if (QPixmapCache::find(key, pixmap))

View file

@ -6,6 +6,7 @@
#include "qtabwidget.h"
#include "qmap.h"
#include "qdrawhelper_p.h"
#include "qcorecommon_p.h"
QT_BEGIN_NAMESPACE
@ -41,6 +42,9 @@ static const QRgb qt_blackrgba = qRgba(0, 0, 0, 255);
// same as QColor(Qt::color1).rgb() and QColor(Qt::black).rgb()
static const QRgb qt_blackrgb = qRgb(0, 0, 0);
static const qreal inv_dist_to_plane = 1. / 1024.;
// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
inline static const QVector<QRgb>& monoColorTable()
{
@ -131,10 +135,16 @@ inline static QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWid
}
#endif // QT_NO_TABWIDGET
static const qreal inv_dist_to_plane = 1. / 1024.;
// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
// converts an integer values to an unique string token
inline static QString qHexString(const char *format, ...)
{
va_list ap;
va_start(ap, format);
QSTACKARRAY(char, hexbuf, 1024);
::vsnprintf(hexbuf, sizeof(hexbuf), format, ap);
va_end(ap);
return QString::fromLatin1(hexbuf);
}
QT_END_NAMESPACE

View file

@ -1223,7 +1223,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QPixmap cache;
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("qt_headersection"), option, option->rect.size());
pixmapName += QString::number(- int(header->position));
pixmapName += QString::number(- int(header->orientation));
QRect r = option->rect;
@ -2010,7 +2010,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QPixmap cache;
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("qt_spinbox"), spinBox, spinBox->rect.size());
if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(spinBox->rect.size());
cache.fill(Qt::transparent);
@ -2759,7 +2759,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// The AddLine (down/right) button
if (scrollBar->subControls & SC_ScrollBarAddLine) {
QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16));
QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("qt_scrollbar_addline"), option, QSize(16, 16));
QRect pixmapRect = scrollBarAddLine;
if (isEnabled) {
QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1);
@ -2837,7 +2837,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
bool isEnabled = (comboBox->state & State_Enabled);
bool focus = isEnabled && (comboBox->state & State_HasFocus);
QPixmap cache;
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("qt_combobox"), option, comboBox->rect.size());
if (sunken)
pixmapName += QLatin1String("-sunken");
if (comboBox->editable)
@ -3077,7 +3077,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
highlightAlpha.setAlpha(80);
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size());
QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("qt_slider_groove"), option, groove.size());
QRect pixmapRect(0, 0, groove.width(), groove.height());
// draw background groove
@ -3155,7 +3155,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// draw handle
if ((option->subControls & SC_SliderHandle) ) {
QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("qt_slider_handle"), option, handle.size());
if (!QPixmapCache::find(handlePixmapName, cache)) {
cache = QPixmap(handle.size());
cache.fill(Qt::transparent);

View file

@ -26,6 +26,7 @@
#include "qmath.h"
#include "qpen.h"
#include "qstylehelper_p.h"
#include "qguicommon_p.h"
QT_BEGIN_NAMESPACE
@ -34,18 +35,21 @@ namespace QStyleHelper {
QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
{
const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
QString tmp = key + HexString<uint>(option->state)
+ HexString<uint>(option->direction)
+ HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u)
+ HexString<quint64>(option->palette.cacheKey())
+ HexString<uint>(size.width())
+ HexString<uint>(size.height());
QString tmp = key + qHexString(
"_%d_%d_%d_%lld_%d_%d",
static_cast<int>(option->state),
static_cast<int>(option->direction),
static_cast<int>(complexOption ? int(complexOption->activeSubControls) : 0u),
option->palette.cacheKey(),
size.width(),
size.height()
);
#ifndef QT_NO_SPINBOX
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
tmp = tmp + HexString<uint>(spinBox->buttonSymbols)
+ HexString<uint>(spinBox->stepEnabled)
+ QLatin1Char(spinBox->frame ? '1' : '0');
tmp += QLatin1Char('_') + QChar(static_cast<uint>(spinBox->buttonSymbols));
tmp += QLatin1Char('_') + QChar(static_cast<uint>(spinBox->stepEnabled));
tmp += QLatin1Char('_') + QChar(static_cast<uint>(spinBox->frame ? '1' : '0'));
}
#endif // QT_NO_SPINBOX
return tmp;

View file

@ -55,21 +55,6 @@ namespace QStyleHelper
#endif //QT_NO_DIAL
}
// internal helper. Converts an integer value to an unique string token
template <typename T>
struct HexString
{
inline HexString(const T t)
: val(t)
{}
inline operator const QChar() const {
const char *c = reinterpret_cast<const char *>(&val);
return QChar(qChecksum(c, sizeof(T)));
}
const T val;
};
QT_END_NAMESPACE
#endif // QSTYLEHELPER_P_H

View file

@ -694,9 +694,9 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
QRect r = opt->rect;
int size = qMin(r.height(), r.width());
QPixmap pixmap;
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("$qt_ia-")
QString pixmapName = QStyleHelper::uniqueName(QLatin1String("qt_arrow")
+ QString::fromLatin1(metaObject()->className()), opt, QSize(size, size))
+ HexString<uint>(pe);
+ QLatin1Char('_') + QChar(static_cast<uint>(pe));
if (!QPixmapCache::find(pixmapName, pixmap)) {
int border = size/5;
int sqsize = 2*(size/2);