STR 3489: fix alpha blending for X11

This commit is contained in:
Matthias Melcher 2024-03-15 20:18:02 +01:00
parent 82bd0b6652
commit b3e1df3584

View File

@ -1,7 +1,7 @@
// //
// Image drawing routines for the Fast Light Tool Kit (FLTK). // Image drawing routines for the Fast Light Tool Kit (FLTK).
// //
// Copyright 1998-2020 by Bill Spitzak and others. // Copyright 1998-2024 by Bill Spitzak and others.
// //
// This library is free software. Distribution and use rights are outlined in // This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this // the file "COPYING" which should have been included with this file. If this
@ -640,7 +640,6 @@ void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int
XSetFillStyle(fl_display, gc_, FillSolid); XSetFillStyle(fl_display, gc_, FillSolid);
} }
// Composite an image with alpha on systems that don't have accelerated // Composite an image with alpha on systems that don't have accelerated
// alpha compositing... // alpha compositing...
static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
@ -671,8 +670,9 @@ static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, i
int srcskip = ld - img->d() * W; int srcskip = ld - img->d() * W;
uchar *dstptr = dst; uchar *dstptr = dst;
uchar srcr, srcg, srcb, srca; uchar srcr, srcg, srcb; // source color components
uchar dstr, dstg, dstb, dsta; uchar dstr, dstg, dstb; // destination color components
unsigned int srca, dsta; // source alpha and inverse source alpha
if (img->d() == 2) { if (img->d() == 2) {
// Composite grayscale + alpha over RGB... // Composite grayscale + alpha over RGB...
@ -680,15 +680,23 @@ static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, i
for (int x = W; x > 0; x--) { for (int x = W; x > 0; x--) {
srcg = *srcptr++; srcg = *srcptr++;
srca = *srcptr++; srca = *srcptr++;
if (srca == 255) { // special case "copy"
dstr = dstptr[0]; *dstptr++ = srcg;
dstg = dstptr[1]; *dstptr++ = srcg;
dstb = dstptr[2]; *dstptr++ = srcg;
dsta = 255 - srca; } else if (srca == 0) { // special case "ignore"
dstptr += 3;
*dstptr++ = (srcg * srca + dstr * dsta) >> 8; } else { // common case "blend"
*dstptr++ = (srcg * srca + dstg * dsta) >> 8; srca += srca>>7; // multiply by 1.004 to compensate integer rounding error
*dstptr++ = (srcg * srca + dstb * dsta) >> 8; dstr = dstptr[0];
dstg = dstptr[1];
dstb = dstptr[2];
dsta = 256 - srca;
unsigned int srcg_pm = srcg * srca; // premultiply once
*dstptr++ = (srcg_pm + dstr * dsta) >> 8;
*dstptr++ = (srcg_pm + dstg * dsta) >> 8;
*dstptr++ = (srcg_pm + dstb * dsta) >> 8;
}
} }
} else { } else {
// Composite RGBA over RGB... // Composite RGBA over RGB...
@ -698,18 +706,24 @@ static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, i
srcg = *srcptr++; srcg = *srcptr++;
srcb = *srcptr++; srcb = *srcptr++;
srca = *srcptr++; srca = *srcptr++;
if (srca == 255) { // special case "copy"
dstr = dstptr[0]; *dstptr++ = srcr;
dstg = dstptr[1]; *dstptr++ = srcg;
dstb = dstptr[2]; *dstptr++ = srcb;
dsta = 255 - srca; } else if (srca == 0) { // special case "ignore"
dstptr += 3;
*dstptr++ = (srcr * srca + dstr * dsta) >> 8; } else { // common case "blend"
*dstptr++ = (srcg * srca + dstg * dsta) >> 8; srca += srca>>7; // multiply by 1.004 to compensate integer rounding error
*dstptr++ = (srcb * srca + dstb * dsta) >> 8; dstr = dstptr[0];
dstg = dstptr[1];
dstb = dstptr[2];
dsta = 256 - srca;
*dstptr++ = (srcr * srca + dstr * dsta) >> 8;
*dstptr++ = (srcg * srca + dstg * dsta) >> 8;
*dstptr++ = (srcb * srca + dstb * dsta) >> 8;
}
} }
} }
fl_draw_image(dst, X, Y, W, H, 3, 0); fl_draw_image(dst, X, Y, W, H, 3, 0);
delete[] dst; delete[] dst;