From 32d252d3cffded6c723ec7ecdc44d530501f58a1 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Thu, 28 Mar 2024 09:47:55 +0200 Subject: [PATCH] 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 --- src/gui/image/qicon.cpp | 24 ++++++++++++++---------- src/gui/image/qiconloader.cpp | 12 +++++++----- src/gui/image/qpixmap.cpp | 11 ++++++----- src/gui/itemviews/qitemdelegate.cpp | 23 ++++++----------------- src/gui/painting/qpainter.cpp | 7 ++++--- src/gui/qguicommon_p.h | 18 ++++++++++++++---- src/gui/styles/qcleanlooksstyle.cpp | 12 ++++++------ src/gui/styles/qstylehelper.cpp | 22 +++++++++++++--------- src/gui/styles/qstylehelper_p.h | 15 --------------- src/gui/styles/qwindowsstyle.cpp | 4 ++-- 10 files changed, 72 insertions(+), 76 deletions(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index c8ce61cb7..5b695faa5 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -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(pm.cacheKey()) - + HexString(pe ? pe->mode : QIcon::Normal) - + HexString(QApplication::palette().cacheKey()) - + HexString(actualSize.width()) - + HexString(actualSize.height()); + const QString key = qHexString( + "qt_icon_%lld_%d_%lld_%d_%d", + pm.cacheKey(), + static_cast(pe ? pe->mode : QIcon::Normal), + QApplication::palette().cacheKey(), + actualSize.width(), + actualSize.height() + ); + const QString key2 = key + QLatin1Char('_') + QChar(static_cast(mode)); if (mode == QIcon::Active) { - if (QPixmapCache::find(key + HexString(mode), pm)) + if (QPixmapCache::find(key2, pm)) return pm; // horray - if (QPixmapCache::find(key + HexString(QIcon::Normal), pm)) { + const QString key3 = key + QLatin1Char('_') + QChar(static_cast(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(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(mode), pm); + QPixmapCache::insert(key2, pm); } return pm; } diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 8291284a4..2208dabac 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -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(m_basePixmap.cacheKey()) - + HexString(mode) - + HexString(qApp->palette().cacheKey()) - + HexString(actualSize); + const QString key = qHexString( + "qt_theme_%lld_%d_%lld_%d", + m_basePixmap.cacheKey(), + static_cast(mode), + qApp->palette().cacheKey(), + actualSize + ); QPixmap cachedPixmap; if (QPixmapCache::find(key, &cachedPixmap)) { diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index eee8ac4b4..474c5e97a 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -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(info.lastModified().toTime_t()) - + HexString(info.size()) - + HexString(data ? data->pixelType() : QPixmapData::PixmapType); + const QString key = qHexString( + "qt_pixmap_%lld_%lld_%d_", + info.lastModified().toTime_t(), + info.size(), + static_cast(data ? data->pixelType() : QPixmapData::PixmapType) + ) + info.absoluteFilePath(); // Note: If no extension is provided, we try to match the // file against known plugin extensions diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 0ae6ee7eb..cc06bbe24 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -50,6 +50,7 @@ #include "qlocale.h" #include "qdialog.h" #include "qmath.h" +#include "qguicommon_p.h" #include #include @@ -959,22 +960,6 @@ QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVar return qvariant_cast(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(enabled) + ); QPixmap *pm = QPixmapCache::find(key); if (!pm) { QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 0850f91ef..3aca692de 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -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(radiusBase); + const QString key = qHexString( + "qt_waveunderline_%f_", + static_cast(radiusBase) + ) + pen.color().name(); QPixmap pixmap; if (QPixmapCache::find(key, pixmap)) diff --git a/src/gui/qguicommon_p.h b/src/gui/qguicommon_p.h index a521e235c..1c20966a6 100644 --- a/src/gui/qguicommon_p.h +++ b/src/gui/qguicommon_p.h @@ -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& 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 diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 265bf62e8..4ed93ab17 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -1223,7 +1223,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o // Draws the header in tables. if (const QStyleOptionHeader *header = qstyleoption_cast(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(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); diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp index 64e84f0dd..f2b56dcfd 100644 --- a/src/gui/styles/qstylehelper.cpp +++ b/src/gui/styles/qstylehelper.cpp @@ -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(option); - QString tmp = key + HexString(option->state) - + HexString(option->direction) - + HexString(complexOption ? uint(complexOption->activeSubControls) : 0u) - + HexString(option->palette.cacheKey()) - + HexString(size.width()) - + HexString(size.height()); + QString tmp = key + qHexString( + "_%d_%d_%d_%lld_%d_%d", + static_cast(option->state), + static_cast(option->direction), + static_cast(complexOption ? int(complexOption->activeSubControls) : 0u), + option->palette.cacheKey(), + size.width(), + size.height() + ); #ifndef QT_NO_SPINBOX if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast(option)) { - tmp = tmp + HexString(spinBox->buttonSymbols) - + HexString(spinBox->stepEnabled) - + QLatin1Char(spinBox->frame ? '1' : '0'); + tmp += QLatin1Char('_') + QChar(static_cast(spinBox->buttonSymbols)); + tmp += QLatin1Char('_') + QChar(static_cast(spinBox->stepEnabled)); + tmp += QLatin1Char('_') + QChar(static_cast(spinBox->frame ? '1' : '0')); } #endif // QT_NO_SPINBOX return tmp; diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h index 00b785a44..87ab93e05 100644 --- a/src/gui/styles/qstylehelper_p.h +++ b/src/gui/styles/qstylehelper_p.h @@ -55,21 +55,6 @@ namespace QStyleHelper #endif //QT_NO_DIAL } -// internal helper. Converts an integer value to an unique string token -template - struct HexString -{ - inline HexString(const T t) - : val(t) - {} - - inline operator const QChar() const { - const char *c = reinterpret_cast(&val); - return QChar(qChecksum(c, sizeof(T))); - } - const T val; -}; - QT_END_NAMESPACE #endif // QSTYLEHELPER_P_H diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 8e1f78dad..f45806cfa 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -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(pe); + + QLatin1Char('_') + QChar(static_cast(pe)); if (!QPixmapCache::find(pixmapName, pixmap)) { int border = size/5; int sqsize = 2*(size/2);