ImGuiFullscreen: Support loading SVGs

This commit is contained in:
Stenzek 2024-10-11 22:36:40 +10:00
parent 3e26b7ab73
commit 38a331fde4
No known key found for this signature in database
2 changed files with 48 additions and 9 deletions

View File

@ -43,7 +43,7 @@ using MessageDialogCallbackVariant = std::variant<InfoMessageDialogCallback, Con
static constexpr float MENU_BACKGROUND_ANIMATION_TIME = 0.5f; static constexpr float MENU_BACKGROUND_ANIMATION_TIME = 0.5f;
static constexpr float SMOOTH_SCROLLING_SPEED = 3.5f; static constexpr float SMOOTH_SCROLLING_SPEED = 3.5f;
static std::optional<RGBA8Image> LoadTextureImage(std::string_view path); static std::optional<RGBA8Image> LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height);
static std::shared_ptr<GPUTexture> UploadTexture(std::string_view path, const RGBA8Image& image); static std::shared_ptr<GPUTexture> UploadTexture(std::string_view path, const RGBA8Image& image);
static void TextureLoaderThread(); static void TextureLoaderThread();
@ -298,12 +298,34 @@ std::unique_ptr<GPUTexture> ImGuiFullscreen::CreateTextureFromImage(const RGBA8I
return ret; return ret;
} }
std::optional<RGBA8Image> ImGuiFullscreen::LoadTextureImage(std::string_view path) std::optional<RGBA8Image> ImGuiFullscreen::LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height)
{ {
std::optional<RGBA8Image> image; std::optional<RGBA8Image> image;
Error error; Error error;
if (Path::IsAbsolute(path)) if (StringUtil::EqualNoCase(Path::GetExtension(path), "svg"))
{
std::optional<DynamicHeapArray<u8>> svg_data;
if (Path::IsAbsolute(path))
svg_data = FileSystem::ReadBinaryFile(std::string(path).c_str(), &error);
else
svg_data = Host::ReadResourceFile(path, true);
if (svg_data.has_value())
{
image = RGBA8Image();
if (!image->RasterizeSVG(svg_data->cspan(), svg_width, svg_height))
{
ERROR_LOG("Failed to rasterize SVG texture file '{}': {}", path, error.GetDescription());
image.reset();
}
}
else
{
ERROR_LOG("Failed to read SVG texture file '{}': {}", path, error.GetDescription());
}
}
else if (Path::IsAbsolute(path))
{ {
std::string path_str(path); std::string path_str(path);
auto fp = FileSystem::OpenManagedCFile(path_str.c_str(), "rb", &error); auto fp = FileSystem::OpenManagedCFile(path_str.c_str(), "rb", &error);
@ -349,7 +371,7 @@ std::shared_ptr<GPUTexture> ImGuiFullscreen::UploadTexture(std::string_view path
GPUTexture::Format::RGBA8, image.GetPixels(), image.GetPitch()); GPUTexture::Format::RGBA8, image.GetPixels(), image.GetPitch());
if (!texture) if (!texture)
{ {
ERROR_LOG("failed to create {}x{} texture for resource", image.GetWidth(), image.GetHeight()); ERROR_LOG("Failed to create {}x{} texture for resource", image.GetWidth(), image.GetHeight());
return {}; return {};
} }
@ -357,9 +379,9 @@ std::shared_ptr<GPUTexture> ImGuiFullscreen::UploadTexture(std::string_view path
return std::shared_ptr<GPUTexture>(texture.release(), GPUDevice::PooledTextureDeleter()); return std::shared_ptr<GPUTexture>(texture.release(), GPUDevice::PooledTextureDeleter());
} }
std::shared_ptr<GPUTexture> ImGuiFullscreen::LoadTexture(std::string_view path) std::shared_ptr<GPUTexture> ImGuiFullscreen::LoadTexture(std::string_view path, u32 width_hint, u32 height_hint)
{ {
std::optional<RGBA8Image> image(LoadTextureImage(path)); std::optional<RGBA8Image> image(LoadTextureImage(path, width_hint, height_hint));
if (image.has_value()) if (image.has_value())
{ {
std::shared_ptr<GPUTexture> ret(UploadTexture(path, image.value())); std::shared_ptr<GPUTexture> ret(UploadTexture(path, image.value()));
@ -375,13 +397,29 @@ GPUTexture* ImGuiFullscreen::GetCachedTexture(std::string_view name)
std::shared_ptr<GPUTexture>* tex_ptr = s_texture_cache.Lookup(name); std::shared_ptr<GPUTexture>* tex_ptr = s_texture_cache.Lookup(name);
if (!tex_ptr) if (!tex_ptr)
{ {
std::shared_ptr<GPUTexture> tex(LoadTexture(name)); std::shared_ptr<GPUTexture> tex = LoadTexture(name);
tex_ptr = s_texture_cache.Insert(std::string(name), std::move(tex)); tex_ptr = s_texture_cache.Insert(std::string(name), std::move(tex));
} }
return tex_ptr->get(); return tex_ptr->get();
} }
GPUTexture* ImGuiFullscreen::GetCachedTexture(std::string_view name, u32 svg_width, u32 svg_height)
{
svg_width = static_cast<u32>(std::ceil(LayoutScale(static_cast<float>(svg_width))));
svg_height = static_cast<u32>(std::ceil(LayoutScale(static_cast<float>(svg_height))));
const SmallString wh_name = SmallString::from_format("{}#{}x{}", name, svg_width, svg_height);
std::shared_ptr<GPUTexture>* tex_ptr = s_texture_cache.Lookup(wh_name.view());
if (!tex_ptr)
{
std::shared_ptr<GPUTexture> tex = LoadTexture(name, svg_width, svg_height);
tex_ptr = s_texture_cache.Insert(std::string(wh_name.view()), std::move(tex));
}
return tex_ptr->get();
}
GPUTexture* ImGuiFullscreen::GetCachedTextureAsync(std::string_view name) GPUTexture* ImGuiFullscreen::GetCachedTextureAsync(std::string_view name)
{ {
std::shared_ptr<GPUTexture>* tex_ptr = s_texture_cache.Lookup(name); std::shared_ptr<GPUTexture>* tex_ptr = s_texture_cache.Lookup(name);
@ -442,7 +480,7 @@ void ImGuiFullscreen::TextureLoaderThread()
s_texture_load_queue.pop_front(); s_texture_load_queue.pop_front();
lock.unlock(); lock.unlock();
std::optional<RGBA8Image> image(LoadTextureImage(path.c_str())); std::optional<RGBA8Image> image(LoadTextureImage(path.c_str(), 0, 0));
lock.lock(); lock.lock();
// don't bother queuing back if it doesn't exist // don't bother queuing back if it doesn't exist

View File

@ -130,8 +130,9 @@ void Shutdown();
/// Texture cache. /// Texture cache.
const std::shared_ptr<GPUTexture>& GetPlaceholderTexture(); const std::shared_ptr<GPUTexture>& GetPlaceholderTexture();
std::unique_ptr<GPUTexture> CreateTextureFromImage(const RGBA8Image& image); std::unique_ptr<GPUTexture> CreateTextureFromImage(const RGBA8Image& image);
std::shared_ptr<GPUTexture> LoadTexture(std::string_view path); std::shared_ptr<GPUTexture> LoadTexture(std::string_view path, u32 svg_width = 0, u32 svg_height = 0);
GPUTexture* GetCachedTexture(std::string_view name); GPUTexture* GetCachedTexture(std::string_view name);
GPUTexture* GetCachedTexture(std::string_view name, u32 svg_width, u32 svg_height);
GPUTexture* GetCachedTextureAsync(std::string_view name); GPUTexture* GetCachedTextureAsync(std::string_view name);
bool InvalidateCachedTexture(const std::string& path); bool InvalidateCachedTexture(const std::string& path);
void UploadAsyncTextures(); void UploadAsyncTextures();