DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit e1d92dff19ceda103a86cdea5333e1c97fa21c97
parent e5949582e6b5d60f9a4aa1285668efdb598ed28b
Author: falkTX <falktx@falktx.com>
Date:   Sun, 15 Oct 2023 14:58:57 +0200

Correct CairoImage::loadFromMemory

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Mdgl/src/Cairo.cpp | 57++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 21 deletions(-)

diff --git 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<uint>& 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<int>(s.getWidth()); const int height = static_cast<int>(s.getHeight()); const int stride = cairo_format_stride_for_width(cairoformat, width); - uchar* const newdata = (uchar*)std::malloc(static_cast<size_t>(width * height * stride * 4)); + uchar* const newdata = static_cast<uchar*>(std::malloc(static_cast<size_t>(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<uint>& s, co if (datarefcount != nullptr && --(*datarefcount) == 0) std::free(surfacedata); else - datarefcount = (int*)malloc(sizeof(*datarefcount)); + datarefcount = static_cast<int*>(std::malloc(sizeof(int))); surface = newsurface; surfacedata = newdata; *datarefcount = 1; + const uchar* const urdata = reinterpret_cast<const uchar*>(rdata); + switch (fmt) { case kImageFormatNull: @@ -412,42 +416,53 @@ void CairoImage::loadFromMemory(const char* const rdata, const Size<uint>& s, co { for (int w = 0; w < width; ++w) { - newdata[h*width*4+w*4+0] = static_cast<uchar>(rdata[h*width*3+w*3+0]); - newdata[h*width*4+w*4+1] = static_cast<uchar>(rdata[h*width*3+w*3+1]); - newdata[h*width*4+w*4+2] = static_cast<uchar>(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<uchar>(rdata[h*width*4+w*4+0]); - newdata[h*width*4+w*4+1] = static_cast<uchar>(rdata[h*width*4+w*4+1]); - newdata[h*width*4+w*4+2] = static_cast<uchar>(rdata[h*width*4+w*4+2]); - newdata[h*width*4+w*4+3] = static_cast<uchar>(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; }