mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
IconCache: Know an icon's size before its texture exists
GetDimensions only answered once a texture had been created, so the first MeasureNotice for a new icon (and after the texture was released for being unused) measured without it, and the icon was then drawn over the text. Read the size from the PNG header when the icon is inserted or loaded. Also remove a width adjustment in MeasureNotice that was overwritten before use. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
afe4025106
commit
8b96d109ff
3 files changed
+25
-8
No files matched your search
+23
-7
@@ -1,4 +1,5 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#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<std::mutex> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::string, Entry, std::less<>> cache_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user