From 38a331fde4dccf68cfc33376f88cb690b0ee0b4f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 11 Oct 2024 22:36:40 +1000 Subject: [PATCH] ImGuiFullscreen: Support loading SVGs --- src/util/imgui_fullscreen.cpp | 54 +++++++++++++++++++++++++++++------ src/util/imgui_fullscreen.h | 3 +- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/util/imgui_fullscreen.cpp b/src/util/imgui_fullscreen.cpp index f8c54bbfa..e79d0668d 100644 --- a/src/util/imgui_fullscreen.cpp +++ b/src/util/imgui_fullscreen.cpp @@ -43,7 +43,7 @@ using MessageDialogCallbackVariant = std::variant LoadTextureImage(std::string_view path); +static std::optional LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height); static std::shared_ptr UploadTexture(std::string_view path, const RGBA8Image& image); static void TextureLoaderThread(); @@ -298,12 +298,34 @@ std::unique_ptr ImGuiFullscreen::CreateTextureFromImage(const RGBA8I return ret; } -std::optional ImGuiFullscreen::LoadTextureImage(std::string_view path) +std::optional ImGuiFullscreen::LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height) { std::optional image; Error error; - if (Path::IsAbsolute(path)) + if (StringUtil::EqualNoCase(Path::GetExtension(path), "svg")) + { + std::optional> 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); auto fp = FileSystem::OpenManagedCFile(path_str.c_str(), "rb", &error); @@ -349,7 +371,7 @@ std::shared_ptr ImGuiFullscreen::UploadTexture(std::string_view path GPUTexture::Format::RGBA8, image.GetPixels(), image.GetPitch()); 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 {}; } @@ -357,9 +379,9 @@ std::shared_ptr ImGuiFullscreen::UploadTexture(std::string_view path return std::shared_ptr(texture.release(), GPUDevice::PooledTextureDeleter()); } -std::shared_ptr ImGuiFullscreen::LoadTexture(std::string_view path) +std::shared_ptr ImGuiFullscreen::LoadTexture(std::string_view path, u32 width_hint, u32 height_hint) { - std::optional image(LoadTextureImage(path)); + std::optional image(LoadTextureImage(path, width_hint, height_hint)); if (image.has_value()) { std::shared_ptr ret(UploadTexture(path, image.value())); @@ -375,13 +397,29 @@ GPUTexture* ImGuiFullscreen::GetCachedTexture(std::string_view name) std::shared_ptr* tex_ptr = s_texture_cache.Lookup(name); if (!tex_ptr) { - std::shared_ptr tex(LoadTexture(name)); + std::shared_ptr tex = LoadTexture(name); tex_ptr = s_texture_cache.Insert(std::string(name), std::move(tex)); } return tex_ptr->get(); } +GPUTexture* ImGuiFullscreen::GetCachedTexture(std::string_view name, u32 svg_width, u32 svg_height) +{ + svg_width = static_cast(std::ceil(LayoutScale(static_cast(svg_width)))); + svg_height = static_cast(std::ceil(LayoutScale(static_cast(svg_height)))); + + const SmallString wh_name = SmallString::from_format("{}#{}x{}", name, svg_width, svg_height); + std::shared_ptr* tex_ptr = s_texture_cache.Lookup(wh_name.view()); + if (!tex_ptr) + { + std::shared_ptr 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) { std::shared_ptr* tex_ptr = s_texture_cache.Lookup(name); @@ -442,7 +480,7 @@ void ImGuiFullscreen::TextureLoaderThread() s_texture_load_queue.pop_front(); lock.unlock(); - std::optional image(LoadTextureImage(path.c_str())); + std::optional image(LoadTextureImage(path.c_str(), 0, 0)); lock.lock(); // don't bother queuing back if it doesn't exist diff --git a/src/util/imgui_fullscreen.h b/src/util/imgui_fullscreen.h index a83a14e03..6cc231424 100644 --- a/src/util/imgui_fullscreen.h +++ b/src/util/imgui_fullscreen.h @@ -130,8 +130,9 @@ void Shutdown(); /// Texture cache. const std::shared_ptr& GetPlaceholderTexture(); std::unique_ptr CreateTextureFromImage(const RGBA8Image& image); -std::shared_ptr LoadTexture(std::string_view path); +std::shared_ptr 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, u32 svg_width, u32 svg_height); GPUTexture* GetCachedTextureAsync(std::string_view name); bool InvalidateCachedTexture(const std::string& path); void UploadAsyncTextures();