From e1d92dff19ceda103a86cdea5333e1c97fa21c97 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 15 Oct 2023 14:59:24 +0200 Subject: [PATCH] Correct CairoImage::loadFromMemory Signed-off-by: falkTX --- dgl/src/Cairo.cpp | 57 ++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/dgl/src/Cairo.cpp b/dgl/src/Cairo.cpp index d913c4e8..6f31d5f6 100644 --- a/dgl/src/Cairo.cpp +++ b/dgl/src/Cairo.cpp @@ -375,11 +375,13 @@ CairoImage::~CairoImage() void CairoImage::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept { const cairo_format_t cairoformat = asCairoImageFormat(fmt); + DISTRHO_SAFE_ASSERT_RETURN(cairoformat != CAIRO_FORMAT_INVALID,); + const int width = static_cast(s.getWidth()); const int height = static_cast(s.getHeight()); const int stride = cairo_format_stride_for_width(cairoformat, width); - uchar* const newdata = (uchar*)std::malloc(static_cast(width * height * stride * 4)); + uchar* const newdata = static_cast(std::malloc(static_cast(width * height * stride * 4))); DISTRHO_SAFE_ASSERT_RETURN(newdata != nullptr,); cairo_surface_t* const newsurface = cairo_image_surface_create_for_data(newdata, cairoformat, width, height, stride); @@ -392,12 +394,14 @@ void CairoImage::loadFromMemory(const char* const rdata, const Size& s, co if (datarefcount != nullptr && --(*datarefcount) == 0) std::free(surfacedata); else - datarefcount = (int*)malloc(sizeof(*datarefcount)); + datarefcount = static_cast(std::malloc(sizeof(int))); surface = newsurface; surfacedata = newdata; *datarefcount = 1; + const uchar* const urdata = reinterpret_cast(rdata); + switch (fmt) { case kImageFormatNull: @@ -412,42 +416,53 @@ void CairoImage::loadFromMemory(const char* const rdata, const Size& s, co { for (int w = 0; w < width; ++w) { - newdata[h*width*4+w*4+0] = static_cast(rdata[h*width*3+w*3+0]); - newdata[h*width*4+w*4+1] = static_cast(rdata[h*width*3+w*3+1]); - newdata[h*width*4+w*4+2] = static_cast(rdata[h*width*3+w*3+2]); + newdata[h*width*4+w*4+0] = urdata[h*width*3+w*3+0]; + newdata[h*width*4+w*4+1] = urdata[h*width*3+w*3+1]; + newdata[h*width*4+w*4+2] = urdata[h*width*3+w*3+2]; newdata[h*width*4+w*4+3] = 0; } } break; case kImageFormatBGRA: // BGRA8 to CAIRO_FORMAT_ARGB32 - // FIXME something is wrong here... - for (int h = 0, t; h < height; ++h) + for (int h = 0; h < height; ++h) { for (int w = 0; w < width; ++w) { - if ((t = rdata[h*width*4+w*4+3]) != 0) - { - newdata[h*width*4+w*4+0] = static_cast(rdata[h*width*4+w*4+0]); - newdata[h*width*4+w*4+1] = static_cast(rdata[h*width*4+w*4+1]); - newdata[h*width*4+w*4+2] = static_cast(rdata[h*width*4+w*4+2]); - newdata[h*width*4+w*4+3] = static_cast(t); - } - else - { - // make all pixels zero, cairo does not render full transparency otherwise - memset(&newdata[h*width*4+w*4], 0, 4); - } + const uchar a = urdata[h*width*4+w*4+3]; + newdata[h*width*4+w*4+0] = (urdata[h*width*4+w*4+0] * a) >> 8; + newdata[h*width*4+w*4+1] = (urdata[h*width*4+w*4+1] * a) >> 8; + newdata[h*width*4+w*4+2] = (urdata[h*width*4+w*4+2] * a) >> 8; + newdata[h*width*4+w*4+3] = a; } } break; case kImageFormatRGB: // RGB8 to CAIRO_FORMAT_RGB24 - // TODO + for (int h = 0; h < height; ++h) + { + for (int w = 0; w < width; ++w) + { + newdata[h*width*4+w*4+0] = urdata[h*width*3+w*3+2]; + newdata[h*width*4+w*4+1] = urdata[h*width*3+w*3+1]; + newdata[h*width*4+w*4+2] = urdata[h*width*3+w*3+0]; + newdata[h*width*4+w*4+3] = 0; + } + } break; case kImageFormatRGBA: // RGBA8 to CAIRO_FORMAT_ARGB32 - // TODO + for (int h = 0; h < height; ++h) + { + for (int w = 0; w < width; ++w) + { + const uchar a = urdata[h*width*4+w*4+3]; + newdata[h*width*4+w*4+0] = (urdata[h*width*4+w*4+2] * a) >> 8; + newdata[h*width*4+w*4+1] = (urdata[h*width*4+w*4+1] * a) >> 8; + newdata[h*width*4+w*4+2] = (urdata[h*width*4+w*4+0] * a) >> 8; + newdata[h*width*4+w*4+3] = a; + } + } break; }