From 4d060dee5894edbe4d6f99c1d3a211424ed15ed4 Mon Sep 17 00:00:00 2001 From: LamaQuest Date: Sat, 5 Sep 2026 00:00:00 +0000 Subject: [PATCH] Load icon textures from a memory buffer NodeCore::LoadTextureFromBase64 decoded the built-in icons, wrote them to "TemporaryIcon.png" in the process working directory, handed that path to the texture loader and deleted the file again -- eight times, as soon as SetTextureLoader is given a non-null loader. That round trip through the disk is unnecessary work in every case, and it is impossible in some: the path is a bare relative name, so it lands wherever the process happens to be running, which may be read-only, may be shared between concurrently running instances, or may simply be a directory the host is not allowed to write to. Nothing in the library needs a path -- LoadTextureFromBase64 is the only caller of the loader, and it always has the bytes in hand. The loader now receives the decoded bytes directly, as a pointer and a size. Every image decoder in common use has a load-from-memory entry point, so a client keeps the same amount of code; a client that really wants a file can still write one itself, which is the choice it should have been making all along. This changes the signature of SetTextureLoader, which is public API. Keeping a path-taking overload alongside it was considered and rejected: the library has no path to give such an overload, so it could only be served by writing the temporary file again -- that is, by keeping the defect this patch removes. --- VisualNodeCore.cpp | 13 ++++--------- VisualNodeCore.h | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/VisualNodeCore.cpp b/VisualNodeCore.cpp index a837422..25bef0e 100644 --- a/VisualNodeCore.cpp +++ b/VisualNodeCore.cpp @@ -382,18 +382,13 @@ std::string NodeCore::TruncateText(const std::string& Text, float MaxWidth, Elli void NodeCore::LoadTextureFromBase64(const std::string& Base64Data, ImTextureID& TextureID) { - std::string DecodedBytes = NODE_CORE.Base64Decode(Base64Data); + const std::string DecodedBytes = NODE_CORE.Base64Decode(Base64Data); - std::ofstream OutFile("TemporaryIcon.png", std::ios::binary); - OutFile.write(DecodedBytes.data(), DecodedBytes.size()); - OutFile.close(); - - TextureID = TextureLoader("TemporaryIcon.png"); - - std::remove("TemporaryIcon.png"); + TextureID = TextureLoader(reinterpret_cast(DecodedBytes.data()), + DecodedBytes.size()); } -void NodeCore::SetTextureLoader(std::function Loader) +void NodeCore::SetTextureLoader(std::function Loader) { TextureLoader = Loader; if (TextureLoader != nullptr) diff --git a/VisualNodeCore.h b/VisualNodeCore.h index 94d003f..8cd47d4 100644 --- a/VisualNodeCore.h +++ b/VisualNodeCore.h @@ -93,7 +93,7 @@ namespace VisNodeSys "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; - std::function TextureLoader = nullptr; + std::function TextureLoader = nullptr; void LoadTextureFromBase64(const std::string& Base64Data, ImTextureID& TextureID); std::string LinkIconBase64 = "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" @@ -154,7 +154,7 @@ namespace VisNodeSys std::string TruncateText(const std::string& Text, float MaxWidth, EllipsisPosition Position = EllipsisPosition::End, const std::string& Ellipsis = "..."); - void SetTextureLoader(std::function Loader); + void SetTextureLoader(std::function Loader); void ShowToolTip(std::string Text) const; };