From 62973e4356ce6af47189af79167610994bd35505 Mon Sep 17 00:00:00 2001 From: Brede Johansen Date: Mon, 9 Dec 2024 10:58:39 +0100 Subject: [PATCH] Add missing make_pixmap --- lib/include/elements/support/pixmap.hpp | 26 ++++++++++++- lib/src/support/pixmap.cpp | 50 +++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/include/elements/support/pixmap.hpp b/lib/include/elements/support/pixmap.hpp index 90655d71f..f6b4e0544 100644 --- a/lib/include/elements/support/pixmap.hpp +++ b/lib/include/elements/support/pixmap.hpp @@ -25,6 +25,11 @@ namespace cycfi { namespace elements using std::runtime_error::runtime_error; }; + enum class pixel_format { + invalid = -1, + rgba32, + }; + class pixmap { public: @@ -47,6 +52,13 @@ namespace cycfi { namespace elements friend class canvas; friend class pixmap_context; + template + friend typename std::enable_if::type + make_pixmap(std::uint8_t const *data, extent size, float scale); + + explicit pixmap(std::uint8_t const *data, pixel_format fmt, extent size, + float scale); + cairo_surface_t* _surface; }; @@ -101,6 +113,18 @@ namespace cycfi { namespace elements } return *this; } -}} + + //-------------------------------------------------------------------------- + // Inlines + //-------------------------------------------------------------------------- + + template + inline typename std::enable_if::type + make_pixmap(std::uint8_t const *data, extent size, float scale=1) + { + return pixmap(reinterpret_cast(data), fmt, size, scale); + } + + }} #endif diff --git a/lib/src/support/pixmap.cpp b/lib/src/support/pixmap.cpp index f95475852..d30b0a171 100644 --- a/lib/src/support/pixmap.cpp +++ b/lib/src/support/pixmap.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,55 @@ namespace cycfi { namespace elements cairo_surface_mark_dirty(_surface); } + pixmap::pixmap(uint8_t const *data, pixel_format fmt, extent size, float scale) + : _surface(nullptr) + { + if (fmt == pixel_format::invalid) + throw std::runtime_error{"Error: Cannot initialize format: INVALID"}; + + if (fmt != pixel_format::rgba32) + throw std::runtime_error{"Error: Format not supported"}; + + _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.x, size.y); + if (!_surface) + throw std::runtime_error{"Failed to create pixmap."}; + + uint8_t *dest_data = cairo_image_surface_get_data(_surface); + size_t src_stride = size.x * 4; + size_t dest_stride = cairo_image_surface_get_stride(_surface); + + for (int y = 0; y != size.y; ++y) + { + uint8_t const *src = data + (y * src_stride); + uint8_t *dest = dest_data + (y * dest_stride); + for (int x = 0; x != size.x; ++x) + { + // RGBA32 to ARGB32 + if constexpr (std::endian::native == std::endian::big) + { + dest[0] = src[3]; // alpha + dest[1] = src[0]; // red + dest[2] = src[1]; // green + dest[3] = src[2]; // blue + } + else if constexpr (std::endian::native == std::endian::little) + { + dest[0] = src[1]; // blue + dest[1] = src[2]; // green + dest[2] = src[3]; // red + dest[3] = src[0]; // alpha + } + + src += 4; + dest += 4; + } + } + + // Set scale and flag the surface as dirty + cairo_surface_set_device_scale(_surface, 1 / scale, 1 / scale); + cairo_surface_mark_dirty(_surface); + } + pixmap::~pixmap() { if (_surface)