pngs can now be embedded

This commit is contained in:
Felix Salcher 2025-07-01 21:16:05 +02:00
parent b3d628d016
commit bba4596882
No known key found for this signature in database
4 changed files with 79 additions and 1 deletions

View file

@ -6,10 +6,15 @@
#include <hyprutils/memory/SharedPtr.hpp>
namespace Hyprgraphics {
enum ImageFormat {
PNG
};
class CImage {
public:
// create an image from a provided path.
CImage(const std::string& path);
CImage(const unsigned char*, size_t, ImageFormat);
~CImage();
CImage(const CImage&) = delete;

View file

@ -12,6 +12,30 @@
using namespace Hyprgraphics;
using namespace Hyprutils::Memory;
Hyprgraphics::CImage::CImage(const unsigned char* data, size_t size, ImageFormat format) {
std::expected<cairo_surface_t*, std::string> CAIROSURFACE;
if (format == ImageFormat::PNG) {
CAIROSURFACE = PNG::createSurfaceFromPNG(data, size);
mime = "image/png";
} else {
lastError = "Currently only PNG images are supported for embedding";
return;
}
if (!CAIROSURFACE) {
lastError = CAIROSURFACE.error();
return;
}
if (const auto STATUS = cairo_surface_status(*CAIROSURFACE); STATUS != CAIRO_STATUS_SUCCESS) {
lastError = std::format("Could not create surface: {}", cairo_status_to_string(STATUS));
return;
}
loadSuccess = true;
pCairoSurface = makeShared<CCairoSurface>(CAIROSURFACE.value());
}
Hyprgraphics::CImage::CImage(const std::string& path) : filepath(path) {
std::expected<cairo_surface_t*, std::string> CAIROSURFACE;
const auto len = path.length();

View file

@ -1,6 +1,7 @@
#include "Png.hpp"
#include <cstddef>
#include <vector>
#include <memory>
#include <fstream>
#include <filesystem>
#include <cstdint>
@ -32,6 +33,50 @@ std::expected<cairo_surface_t*, std::string> PNG::createSurfaceFromPNG(const std
return std::unexpected("loading png: couldn't setjmp");
png_init_io(png, fp);
return loadPNG(png, info);
}
struct MemoryReadState {
const unsigned char* data;
size_t size;
size_t offset;
};
void custom_read_function(png_structp png, png_bytep data, png_size_t length) {
MemoryReadState* state = static_cast<MemoryReadState*>(png_get_io_ptr(png));
if (state->offset + length > state->size) {
png_error(png, "read error");
return;
}
memcpy(data, state->data + state->offset, length);
state->offset += length;
}
std::expected<cairo_surface_t*, std::string> PNG::createSurfaceFromPNG(const unsigned char* data, size_t size) {
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
png_infop info = png_create_info_struct(png);
if (!png || !info)
return std::unexpected("loading png: couldn't init libpng");
CScopeGuard x([&png, &info] { png_destroy_read_struct(&png, &info, nullptr); });
if (setjmp(png_jmpbuf(png)))
return std::unexpected("loading png: couldn't setjmp");
MemoryReadState readState;
readState.data = reinterpret_cast<const unsigned char*>(data);
readState.size = size;
readState.offset = 0;
png_set_read_fn(png, &readState, custom_read_function);
png_set_sig_bytes(png, 0);
return loadPNG(png, info);
}
static std::expected<cairo_surface_t*, std::string> loadPNG(png_structp png, png_infop info) {
png_read_info(png, info);
const size_t W = png_get_image_width(png, info);

View file

@ -3,7 +3,11 @@
#include <cairo/cairo.h>
#include <string>
#include <expected>
#include <png.h>
namespace PNG {
std::expected<cairo_surface_t*, std::string> createSurfaceFromPNG(const std::string&);
};
std::expected<cairo_surface_t*, std::string> createSurfaceFromPNG(const unsigned char*, size_t);
};
static std::expected<cairo_surface_t*, std::string> loadPNG(png_structp, png_infop);