diff --git a/Common/UI/IconCache.cpp b/Common/UI/IconCache.cpp index 1abcea8030..467e3504cf 100644 --- a/Common/UI/IconCache.cpp +++ b/Common/UI/IconCache.cpp @@ -1,4 +1,5 @@ #include +#include #include "Common/UI/IconCache.h" #include "Common/UI/Context.h" @@ -38,6 +39,20 @@ struct DiskCacheEntry { }; static_assert(sizeof(DiskCacheEntry) == 24, "DiskCacheEntry is written to disk as is"); +// Reads the size from the header, so layout can use it before there's a texture. 0x0 if unknown. +static void PeekIconSize(const std::string &data, IconFormat format, int *width, int *height) { + *width = 0; + *height = 0; + if (format == IconFormat::PNG && data.size() >= sizeof(PNGHeaderPeek)) { + PNGHeaderPeek peek; + memcpy(&peek, data.data(), sizeof(peek)); + if (peek.IsValidPNGHeader()) { + *width = peek.Width(); + *height = peek.Height(); + } + } +} + void IconCache::SaveToFile(FILE *file) { std::unique_lock lock(lock_); @@ -115,6 +130,7 @@ bool IconCache::LoadFromFile(FILE *file) { entry.format = entryHeader.format; entry.insertedTimeStamp = entryHeader.insertedTimestamp; entry.usedTimeStamp = now; + PeekIconSize(entry.data, entry.format, &entry.width, &entry.height); cache_.emplace(key, entry); } @@ -224,14 +240,12 @@ bool IconCache::GetDimensions(std::string_view key, int *width, int *height) { } const auto &entry = iter->second; - if (entry.texture) { - // TODO: Store the width/height in the cache. - *width = entry.texture->Width(); - *height = entry.texture->Height(); - return true; - } else { + if (entry.width <= 0 || entry.height <= 0) { return false; } + *width = entry.width; + *height = entry.height; + return true; } bool IconCache::Contains(std::string_view key) { @@ -305,7 +319,9 @@ bool IconCache::InsertIcon(std::string_view key, IconFormat format, std::string } double now = time_now_d(); - cache_.emplace(key, Entry{ std::move(data), format, nullptr, now, now }); + Entry entry{ std::move(data), format, nullptr, now, now }; + PeekIconSize(entry.data, entry.format, &entry.width, &entry.height); + cache_.emplace(key, std::move(entry)); return true; } diff --git a/Common/UI/IconCache.h b/Common/UI/IconCache.h index 3c62379764..45eee95f54 100644 --- a/Common/UI/IconCache.h +++ b/Common/UI/IconCache.h @@ -63,6 +63,8 @@ private: double insertedTimeStamp; double usedTimeStamp; double uploadFailedTime; // When CreateTexture last failed, or 0. + int width; // From the image header, 0 if unknown. + int height; }; std::map> cache_; diff --git a/Common/UI/Notice.cpp b/Common/UI/Notice.cpp index 60d304b619..a5ee6c88eb 100644 --- a/Common/UI/Notice.cpp +++ b/Common/UI/Notice.cpp @@ -54,7 +54,6 @@ void MeasureNotice(const UIContext &dc, NoticeLevel level, std::string_view text // Normal entry but with a cached icon. int iconWidth, iconHeight; if (g_iconCache.GetDimensions(iconName, &iconWidth, &iconHeight)) { - *width += 5.0f + iconWidth; iconW = iconWidth; iconH = iconHeight; }