Skip to content

Commit

Permalink
refactor(Icon): add cache
Browse files Browse the repository at this point in the history
  • Loading branch information
FeiChongCalmCar committed Nov 9, 2022
1 parent cc56ada commit f8db333
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 16 deletions.
30 changes: 19 additions & 11 deletions include/KtUtils/IconHelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2037,27 +2037,30 @@ class KTUTILS_EXPORT IconHelper : public QObject {
/**
* \brief Generate QPixmap for given icon
* \note This function is SLOW, please hold the result and reuse it
* instead of call multiple times.
* instead of call multiple times, or turn on cached parameter.
* \param iconType Enum value for wanted icon.
* \param size Pixel size for generated image.
* \param color Fill color of the icon.
* \param cached Cache the generated pixmap, return it next time.
* \return Generated QPixmap for the icon with given size and color.
* \sa Icon, icon
*/
static QPixmap pixmap(Icon iconType, int size = 16,
const QColor& color = Qt::white);
const QColor& color = Qt::white, bool cached = true);

/**
* \brief Generate QIcon for given icon with available sizes: 16, 24, 32, 36,
* 48, 64, 72, 96, 128, 144, 192, 256.
* \note This function is EXTREMELY SLOW, please hold the result and reuse it
* instead of call multiple times.
* instead of call multiple times, or turn on cached parameter.
* \param iconType Enum value for wanted icon.
* \param color Fill color of the icon, QIcon::Disabled will for to gray.
* \param cached Cache the generated icon, return it next time.
* \return Generated QIcon for the icon with given size and color.
* \sa Icon, pixmap, icon
*/
static QIcon icon(Icon iconType, const QColor& color = Qt::white);
static QIcon icon(Icon iconType, const QColor& color = Qt::white,
bool cached = true);

// Enumeration for font files
enum Font { Brand, Regular, Solid };
Expand All @@ -2071,33 +2074,38 @@ class KTUTILS_EXPORT IconHelper : public QObject {
* of specified color and weight. */
static QPixmap pixmap(Font fontType, QChar ch, int size = 16,
const QColor& color = Qt::white,
QFont::Weight weight = QFont::Normal);
QFont::Weight weight = QFont::Normal,
bool cached = true);
/** \brief Generate QIcon with given font and charactor code of specified
* color and weight. */
static QIcon icon(Font fontType, QChar ch, const QColor& color = Qt::white,
QFont::Weight weight = QFont::Normal);
QFont::Weight weight = QFont::Normal, bool cached = true);

/**
* \brief Set icon to given widget
* \note This function is EXTREMELY SLOW, please avoid calling multiple times.
* \note This function is EXTREMELY SLOW, please avoid calling multiple times,
* or turn on cached parameter.
* \tparam T Type of given widget.
* \param widget Widget to be set icon fpr.
* \param iconType Enum value for wanted icon.
* \param color Fill color of the icon, QIcon::Disabled will for to gray.
* \param cached Cache the generated icon, return it next time.
* \sa Icon, pixmap, icon
*/
template <typename T>
inline static void SetIcon(T* widget, Icon iconType,
const QColor& color = Qt::white) {
widget->setProperty("icon", icon(iconType, color));
const QColor& color = Qt::white,
bool cached = true) {
widget->setProperty("icon", icon(iconType, color, cached));
}
/** \brief Set widget icon with given font and charactor code of specified
* color and weight. */
template <typename T>
inline static void SetIcon(T* widget, Font fontType, QChar ch,
const QColor& color = Qt::white,
QFont::Weight weight = QFont::Normal) {
widget->setProperty("icon", icon(fontType, ch, color, weight));
QFont::Weight weight = QFont::Normal,
bool cached = true) {
widget->setProperty("icon", icon(fontType, ch, color, weight, cached));
}

private:
Expand Down
99 changes: 94 additions & 5 deletions src/IconHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,54 @@ QPixmap RenderPixmap(QSharedPointer<QSvgRenderer> renderer, int size) {
return pixmap;
}

QPixmap IconHelper::pixmap(Icon iconType, int size, const QColor& color) {
QPixmap IconHelper::pixmap(Icon iconType, int size, const QColor& color,
bool cached) {
static QMutex mutex;
using Key = std::tuple<Icon, int, QColor, bool>;
static std::vector<std::pair<Key, QPixmap>> cache;
if (cached) {
QMutexLocker locker(&mutex);
auto it = std::find_if(cache.begin(), cache.end(),
[&](const std::pair<Key, QPixmap>& p) {
return std::get<0>(p.first) == iconType &&
std::get<1>(p.first) == size &&
std::get<2>(p.first) == color &&
std::get<3>(p.first) == cached;
});
if (it != cache.end()) {
return it->second;
}
}

QSharedPointer<QSvgRenderer> renderer = GetRenderer(iconType, color);
return RenderPixmap(renderer, size);
QPixmap pixmap = RenderPixmap(renderer, size);
if (cached) {
QMutexLocker locker(&mutex);
cache.emplace_back(Key{iconType, size, color, cached}, pixmap);
}
return pixmap;
}

QIcon IconHelper::icon(Icon iconType, const QColor& color) {
QIcon IconHelper::icon(Icon iconType, const QColor& color, bool cached) {
static const QVector<int> sizes = {16, 24, 32, 36, 48, 64,
72, 96, 128, 144, 192, 256};

static QMutex mutex;
using Key = std::tuple<Icon, QColor, bool>;
static std::vector<std::pair<Key, QIcon>> cache;
if (cached) {
QMutexLocker locker(&mutex);
auto it = std::find_if(cache.begin(), cache.end(),
[&](const std::pair<Key, QIcon>& p) {
return std::get<0>(p.first) == iconType &&
std::get<1>(p.first) == color &&
std::get<2>(p.first) == cached;
});
if (it != cache.end()) {
return it->second;
}
}

QIcon icon;
QSharedPointer<QSvgRenderer> renderer = GetRenderer(iconType, color);
QSharedPointer<QSvgRenderer> renderer_gray = GetRenderer(iconType, Qt::gray);
Expand All @@ -141,6 +180,10 @@ QIcon IconHelper::icon(Icon iconType, const QColor& color) {
icon.addPixmap(px, QIcon::Disabled, QIcon::On);
icon.addPixmap(px, QIcon::Disabled, QIcon::Off);
}
if (cached) {
QMutexLocker locker(&mutex);
cache.emplace_back(Key{iconType, color, cached}, icon);
}
return icon;
}

Expand All @@ -160,7 +203,27 @@ QFont IconHelper::font(Font fontType) {
}

QPixmap IconHelper::pixmap(Font fontType, QChar ch, int size,
const QColor& color, QFont::Weight weight) {
const QColor& color, QFont::Weight weight,
bool cached) {
static QMutex mutex;
using Key = std::tuple<Font, QChar, int, QColor, QFont::Weight, bool>;
static std::vector<std::pair<Key, QPixmap>> cache;

if (cached) {
QMutexLocker locker(&mutex);
auto it = std::find_if(
cache.begin(), cache.end(), [&](const std::pair<Key, QPixmap>& p) {
return std::get<0>(p.first) == fontType &&
std::get<1>(p.first) == ch && std::get<2>(p.first) == size &&
std::get<3>(p.first) == color &&
std::get<4>(p.first) == weight &&
std::get<5>(p.first) == cached;
});
if (it != cache.end()) {
return it->second;
}
}

QFont font = IconHelper::font(fontType);
font.setPixelSize(size);
font.setWeight(weight);
Expand All @@ -173,14 +236,36 @@ QPixmap IconHelper::pixmap(Font fontType, QChar ch, int size,
painter.setFont(font);
painter.drawText(QRect(0, 0, size, size), Qt::AlignCenter, QString(ch));
painter.end();
if (cached) {
QMutexLocker locker(&mutex);
cache.emplace_back(Key{fontType, ch, size, color, weight, cached}, pixmap);
}
return pixmap;
}

QIcon IconHelper::icon(Font fontType, QChar ch, const QColor& color,
QFont::Weight weight) {
QFont::Weight weight, bool cached) {
static const QVector<int> sizes = {16, 24, 32, 36, 48, 64,
72, 96, 128, 144, 192, 256};

static QMutex mutex;
using Key = std::tuple<Font, QChar, QColor, QFont::Weight, bool>;
static std::vector<std::pair<Key, QIcon>> cache;

if (cached) {
QMutexLocker locker(&mutex);
auto it = std::find_if(
cache.begin(), cache.end(), [&](const std::pair<Key, QIcon>& p) {
return std::get<0>(p.first) == fontType &&
std::get<1>(p.first) == ch && std::get<2>(p.first) == color &&
std::get<3>(p.first) == weight &&
std::get<4>(p.first) == cached;
});
if (it != cache.end()) {
return it->second;
}
}

QIcon icon;
for (const int size : sizes) {
QPixmap px = pixmap(fontType, ch, size, color, weight);
Expand All @@ -195,6 +280,10 @@ QIcon IconHelper::icon(Font fontType, QChar ch, const QColor& color,
icon.addPixmap(px, QIcon::Disabled, QIcon::On);
icon.addPixmap(px, QIcon::Disabled, QIcon::Off);
}
if (cached) {
QMutexLocker locker(&mutex);
cache.emplace_back(Key{fontType, ch, color, weight, cached}, icon);
}
return icon;
}
} // namespace KtUtils

0 comments on commit f8db333

Please sign in to comment.