mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-21 03:21:28 +00:00
Add basic svg image support
This commit is contained in:
parent
19c2ea171d
commit
2d6203a0fe
6 changed files with 4630 additions and 10 deletions
|
@ -13,6 +13,9 @@ set(ZWIDGET_SOURCES
|
|||
src/core/schrift/schrift.h
|
||||
src/core/picopng/picopng.cpp
|
||||
src/core/picopng/picopng.h
|
||||
src/core/nanosvg/nanosvg.cpp
|
||||
src/core/nanosvg/nanosvg.h
|
||||
src/core/nanosvg/nanosvgrast.h
|
||||
src/widgets/lineedit/lineedit.cpp
|
||||
src/widgets/mainwindow/mainwindow.cpp
|
||||
src/widgets/menubar/menubar.cpp
|
||||
|
@ -68,6 +71,7 @@ source_group("src" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/.+")
|
|||
source_group("src\\core" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/.+")
|
||||
source_group("src\\core\\schrift" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/schrift/.+")
|
||||
source_group("src\\core\\picopng" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/picopng/.+")
|
||||
source_group("src\\core\\nanosvg" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/core/nanosvg/.+")
|
||||
source_group("src\\widgets" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/.+")
|
||||
source_group("src\\widgets\\lineedit" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/lineedit/.+")
|
||||
source_group("src\\widgets\\mainwindow" REGULAR_EXPRESSION "${CMAKE_CURRENT_SOURCE_DIR}/src/widgets/mainwindow/.+")
|
||||
|
|
|
@ -20,5 +20,5 @@ public:
|
|||
virtual void* GetData() const = 0;
|
||||
|
||||
static std::shared_ptr<Image> Create(int width, int height, ImageFormat format, const void* data);
|
||||
static std::shared_ptr<Image> LoadResource(const std::string& resourcename);
|
||||
static std::shared_ptr<Image> LoadResource(const std::string& resourcename, double dpiscale = 1.0);
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "core/image.h"
|
||||
#include "core/resourcedata.h"
|
||||
#include "picopng/picopng.h"
|
||||
#include "nanosvg/nanosvg.h"
|
||||
#include "nanosvg/nanosvgrast.h"
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -11,7 +13,8 @@ public:
|
|||
ImageImpl(int width, int height, ImageFormat format, const void* data) : Width(width), Height(height), Format(format)
|
||||
{
|
||||
Data = std::make_unique<uint32_t[]>(width * height);
|
||||
memcpy(Data.get(), data, width * height * sizeof(uint32_t));
|
||||
if (data)
|
||||
memcpy(Data.get(), data, width * height * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
int GetWidth() const override
|
||||
|
@ -45,13 +48,63 @@ std::shared_ptr<Image> Image::Create(int width, int height, ImageFormat format,
|
|||
return std::make_shared<ImageImpl>(width, height, format, data);
|
||||
}
|
||||
|
||||
std::shared_ptr<Image> Image::LoadResource(const std::string& resourcename)
|
||||
std::shared_ptr<Image> Image::LoadResource(const std::string& resourcename, double dpiscale)
|
||||
{
|
||||
auto filedata = LoadWidgetImageData(resourcename);
|
||||
std::vector<unsigned char> pixels;
|
||||
unsigned long width = 0, height = 0;
|
||||
int result = decodePNG(pixels, width, height, (const unsigned char*)filedata.data(), filedata.size(), true);
|
||||
if (result != 0)
|
||||
throw std::runtime_error("Could not decode PNG file");
|
||||
return Image::Create(width, height, ImageFormat::R8G8B8A8, pixels.data());
|
||||
size_t extensionpos = resourcename.find_last_of("./\\");
|
||||
if (extensionpos == std::string::npos || resourcename[extensionpos] != '.')
|
||||
throw std::runtime_error("Unsupported image format");
|
||||
std::string extension = resourcename.substr(extensionpos + 1);
|
||||
for (char& c : extension)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c = c - 'A' + 'a';
|
||||
}
|
||||
|
||||
if (extension == "png")
|
||||
{
|
||||
auto filedata = LoadWidgetImageData(resourcename);
|
||||
|
||||
std::vector<unsigned char> pixels;
|
||||
unsigned long width = 0, height = 0;
|
||||
int result = decodePNG(pixels, width, height, (const unsigned char*)filedata.data(), filedata.size(), true);
|
||||
if (result != 0)
|
||||
throw std::runtime_error("Could not decode PNG file");
|
||||
|
||||
return Image::Create(width, height, ImageFormat::R8G8B8A8, pixels.data());
|
||||
}
|
||||
else if (extension == "svg")
|
||||
{
|
||||
auto filedata = LoadWidgetImageData(resourcename);
|
||||
filedata.push_back(0);
|
||||
|
||||
NSVGimage* svgimage = nsvgParse((char*)filedata.data(), "px", (float)(96.0 * dpiscale));
|
||||
if (!svgimage)
|
||||
throw std::runtime_error("Could not parse SVG file");
|
||||
|
||||
try
|
||||
{
|
||||
int width = (int)(svgimage->width * dpiscale);
|
||||
int height = (int)(svgimage->height * dpiscale);
|
||||
std::shared_ptr<Image> image = Image::Create(width, height, ImageFormat::R8G8B8A8, nullptr);
|
||||
|
||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||
if (!rast)
|
||||
throw std::runtime_error("Could not create SVG rasterizer");
|
||||
|
||||
nsvgRasterize(rast, svgimage, 0.0f, 0.0f, (float)dpiscale, (unsigned char*)image->GetData(), width, height, width * 4);
|
||||
|
||||
nsvgDeleteRasterizer(rast);
|
||||
nsvgDelete(svgimage);
|
||||
return image;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
nsvgDelete(svgimage);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Unsupported image format");
|
||||
}
|
||||
}
|
||||
|
|
6
libraries/ZWidget/src/core/nanosvg/nanosvg.cpp
Normal file
6
libraries/ZWidget/src/core/nanosvg/nanosvg.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#include "nanosvg.h"
|
||||
|
||||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#include "nanosvgrast.h"
|
3098
libraries/ZWidget/src/core/nanosvg/nanosvg.h
Normal file
3098
libraries/ZWidget/src/core/nanosvg/nanosvg.h
Normal file
File diff suppressed because it is too large
Load diff
1459
libraries/ZWidget/src/core/nanosvg/nanosvgrast.h
Normal file
1459
libraries/ZWidget/src/core/nanosvg/nanosvgrast.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue