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:
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;
}