Fix for issue #159.

This commit is contained in:
ManoloFLTK 2020-11-19 15:59:33 +01:00
parent 3ec51f0b80
commit e52e057cdf
2 changed files with 307 additions and 298 deletions

View File

@ -839,31 +839,11 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
} }
} }
if (!image) return 0;
if (s != 1) { if (s != 1) {
w = ws; w = ws;
h = hs; h = hs;
} }
#ifdef DEBUG
printf("width = %d\n", image->width);
printf("height = %d\n", image->height);
printf("xoffset = %d\n", image->xoffset);
printf("format = %d\n", image->format);
printf("data = %p\n", image->data);
printf("byte_order = %d\n", image->byte_order);
printf("bitmap_unit = %d\n", image->bitmap_unit);
printf("bitmap_bit_order = %d\n", image->bitmap_bit_order);
printf("bitmap_pad = %d\n", image->bitmap_pad);
printf("depth = %d\n", image->depth);
printf("bytes_per_line = %d\n", image->bytes_per_line);
printf("bits_per_pixel = %d\n", image->bits_per_pixel);
printf("red_mask = %08x\n", image->red_mask);
printf("green_mask = %08x\n", image->green_mask);
printf("blue_mask = %08x\n", image->blue_mask);
printf("map_entries = %d\n", fl_visual->visual->map_entries);
#endif // DEBUG
const int d = 3; // Depth of image const int d = 3; // Depth of image
uchar *p = NULL; uchar *p = NULL;
// Allocate the image data array as needed... // Allocate the image data array as needed...
@ -871,299 +851,318 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
// Initialize the default colors/alpha in the whole image... // Initialize the default colors/alpha in the whole image...
memset(p, 0, w * h * d); memset(p, 0, w * h * d);
if (image) {
// Check that we have valid mask/shift values...
if (!image->red_mask && image->bits_per_pixel > 12) {
// Greater than 12 bits must be TrueColor...
image->red_mask = fl_visual->visual->red_mask;
image->green_mask = fl_visual->visual->green_mask;
image->blue_mask = fl_visual->visual->blue_mask;
#ifdef DEBUG #ifdef DEBUG
// Defined in Fl_Xlib_Graphics_Driver_color.cxx printf("width = %d\n", image->width);
extern uchar fl_redmask, fl_greenmask, fl_bluemask; printf("height = %d\n", image->height);
extern int fl_redshift, fl_greenshift, fl_blueshift; printf("xoffset = %d\n", image->xoffset);
puts("\n---- UPDATED ----"); printf("format = %d\n", image->format);
printf("fl_redmask = %08x\n", fl_redmask); printf("data = %p\n", image->data);
printf("fl_redshift = %d\n", fl_redshift); printf("byte_order = %d\n", image->byte_order);
printf("fl_greenmask = %08x\n", fl_greenmask); printf("bitmap_unit = %d\n", image->bitmap_unit);
printf("fl_greenshift = %d\n", fl_greenshift); printf("bitmap_bit_order = %d\n", image->bitmap_bit_order);
printf("fl_bluemask = %08x\n", fl_bluemask); printf("bitmap_pad = %d\n", image->bitmap_pad);
printf("fl_blueshift = %d\n", fl_blueshift); printf("depth = %d\n", image->depth);
printf("bytes_per_line = %d\n", image->bytes_per_line);
printf("bits_per_pixel = %d\n", image->bits_per_pixel);
printf("red_mask = %08x\n", image->red_mask); printf("red_mask = %08x\n", image->red_mask);
printf("green_mask = %08x\n", image->green_mask); printf("green_mask = %08x\n", image->green_mask);
printf("blue_mask = %08x\n", image->blue_mask); printf("blue_mask = %08x\n", image->blue_mask);
printf("map_entries = %d\n", fl_visual->visual->map_entries);
#endif // DEBUG
// Check that we have valid mask/shift values...
if (!image->red_mask && image->bits_per_pixel > 12) {
// Greater than 12 bits must be TrueColor...
image->red_mask = fl_visual->visual->red_mask;
image->green_mask = fl_visual->visual->green_mask;
image->blue_mask = fl_visual->visual->blue_mask;
#ifdef DEBUG
// Defined in Fl_Xlib_Graphics_Driver_color.cxx
extern uchar fl_redmask, fl_greenmask, fl_bluemask;
extern int fl_redshift, fl_greenshift, fl_blueshift;
puts("\n---- UPDATED ----");
printf("fl_redmask = %08x\n", fl_redmask);
printf("fl_redshift = %d\n", fl_redshift);
printf("fl_greenmask = %08x\n", fl_greenmask);
printf("fl_greenshift = %d\n", fl_greenshift);
printf("fl_bluemask = %08x\n", fl_bluemask);
printf("fl_blueshift = %d\n", fl_blueshift);
printf("red_mask = %08x\n", image->red_mask);
printf("green_mask = %08x\n", image->green_mask);
printf("blue_mask = %08x\n", image->blue_mask);
#endif // DEBUG #endif // DEBUG
}
// Check if we have colormap image...
if (!image->red_mask) {
// Get the colormap entries for this window...
maxindex = fl_visual->visual->map_entries;
for (i = 0; i < maxindex; i ++) colors[i].pixel = i;
XQueryColors(fl_display, fl_colormap, colors, maxindex);
for (i = 0; i < maxindex; i ++) {
cvals[i][0] = colors[i].red >> 8;
cvals[i][1] = colors[i].green >> 8;
cvals[i][2] = colors[i].blue >> 8;
} }
// Read the pixels and output an RGB image... // Check if we have colormap image...
for (y = 0; y < image->height; y ++) { if (!image->red_mask) {
pixel = (unsigned char *)(image->data + y * image->bytes_per_line); // Get the colormap entries for this window...
line = p + y * w * d; maxindex = fl_visual->visual->map_entries;
switch (image->bits_per_pixel) { for (i = 0; i < maxindex; i ++) colors[i].pixel = i;
case 1 :
for (x = image->width, line_ptr = line, index_mask = 128; XQueryColors(fl_display, fl_colormap, colors, maxindex);
x > 0;
x --, line_ptr += d) { for (i = 0; i < maxindex; i ++) {
if (*pixel & index_mask) { cvals[i][0] = colors[i].red >> 8;
line_ptr[0] = cvals[1][0]; cvals[i][1] = colors[i].green >> 8;
line_ptr[1] = cvals[1][1]; cvals[i][2] = colors[i].blue >> 8;
line_ptr[2] = cvals[1][2]; }
} else {
line_ptr[0] = cvals[0][0]; // Read the pixels and output an RGB image...
line_ptr[1] = cvals[0][1]; for (y = 0; y < image->height; y ++) {
line_ptr[2] = cvals[0][2]; pixel = (unsigned char *)(image->data + y * image->bytes_per_line);
line = p + y * w * d;
switch (image->bits_per_pixel) {
case 1 :
for (x = image->width, line_ptr = line, index_mask = 128;
x > 0;
x --, line_ptr += d) {
if (*pixel & index_mask) {
line_ptr[0] = cvals[1][0];
line_ptr[1] = cvals[1][1];
line_ptr[2] = cvals[1][2];
} else {
line_ptr[0] = cvals[0][0];
line_ptr[1] = cvals[0][1];
line_ptr[2] = cvals[0][2];
}
if (index_mask > 1) {
index_mask >>= 1;
} else {
index_mask = 128;
pixel ++;
}
} }
break;
if (index_mask > 1) {
index_mask >>= 1; case 2 :
} else { for (x = image->width, line_ptr = line, index_shift = 6;
index_mask = 128; x > 0;
pixel ++; x --, line_ptr += d) {
i = (*pixel >> index_shift) & 3;
line_ptr[0] = cvals[i][0];
line_ptr[1] = cvals[i][1];
line_ptr[2] = cvals[i][2];
if (index_shift > 0) {
index_shift -= 2;
} else {
index_shift = 6;
pixel ++;
}
} }
} break;
break;
case 4 :
case 2 : for (x = image->width, line_ptr = line, index_shift = 4;
for (x = image->width, line_ptr = line, index_shift = 6; x > 0;
x > 0; x --, line_ptr += d) {
x --, line_ptr += d) { if (index_shift == 4) i = (*pixel >> 4) & 15;
i = (*pixel >> index_shift) & 3; else i = *pixel & 15;
line_ptr[0] = cvals[i][0]; line_ptr[0] = cvals[i][0];
line_ptr[1] = cvals[i][1]; line_ptr[1] = cvals[i][1];
line_ptr[2] = cvals[i][2]; line_ptr[2] = cvals[i][2];
if (index_shift > 0) { if (index_shift > 0) {
index_shift -= 2; index_shift = 0;
} else { } else {
index_shift = 6; index_shift = 4;
pixel ++; pixel ++;
}
} }
} break;
break;
case 8 :
case 4 : for (x = image->width, line_ptr = line;
for (x = image->width, line_ptr = line, index_shift = 4; x > 0;
x > 0; x --, line_ptr += d, pixel ++) {
x --, line_ptr += d) { line_ptr[0] = cvals[*pixel][0];
if (index_shift == 4) i = (*pixel >> 4) & 15; line_ptr[1] = cvals[*pixel][1];
else i = *pixel & 15; line_ptr[2] = cvals[*pixel][2];
line_ptr[0] = cvals[i][0];
line_ptr[1] = cvals[i][1];
line_ptr[2] = cvals[i][2];
if (index_shift > 0) {
index_shift = 0;
} else {
index_shift = 4;
pixel ++;
} }
} break;
break;
case 12 :
case 8 : for (x = image->width, line_ptr = line, index_shift = 0;
for (x = image->width, line_ptr = line; x > 0;
x > 0; x --, line_ptr += d) {
x --, line_ptr += d, pixel ++) { if (index_shift == 0) {
line_ptr[0] = cvals[*pixel][0]; i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095;
line_ptr[1] = cvals[*pixel][1]; } else {
line_ptr[2] = cvals[*pixel][2]; i = ((pixel[1] << 8) | pixel[2]) & 4095;
} }
break;
line_ptr[0] = cvals[i][0];
case 12 : line_ptr[1] = cvals[i][1];
for (x = image->width, line_ptr = line, index_shift = 0; line_ptr[2] = cvals[i][2];
x > 0;
x --, line_ptr += d) { if (index_shift == 0) {
if (index_shift == 0) { index_shift = 4;
i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; } else {
} else { index_shift = 0;
i = ((pixel[1] << 8) | pixel[2]) & 4095; pixel += 3;
}
} }
break;
line_ptr[0] = cvals[i][0]; }
line_ptr[1] = cvals[i][1]; }
line_ptr[2] = cvals[i][2]; } else {
// RGB(A) image, so figure out the shifts & masks...
if (index_shift == 0) { red_mask = image->red_mask;
index_shift = 4; red_shift = 0;
} else {
index_shift = 0; while ((red_mask & 1) == 0) {
pixel += 3; red_mask >>= 1;
red_shift ++;
}
green_mask = image->green_mask;
green_shift = 0;
while ((green_mask & 1) == 0) {
green_mask >>= 1;
green_shift ++;
}
blue_mask = image->blue_mask;
blue_shift = 0;
while ((blue_mask & 1) == 0) {
blue_mask >>= 1;
blue_shift ++;
}
// Read the pixels and output an RGB image...
for (y = 0; y < image->height; y ++) {
pixel = (unsigned char *)(image->data + y * image->bytes_per_line);
line = p + y * w * d;
switch (image->bits_per_pixel) {
case 8 :
for (x = image->width, line_ptr = line;
x > 0;
x --, line_ptr += d, pixel ++) {
i = *pixel;
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
} }
} break;
break;
} case 12 :
} for (x = image->width, line_ptr = line, index_shift = 0;
} else { x > 0;
// RGB(A) image, so figure out the shifts & masks... x --, line_ptr += d) {
red_mask = image->red_mask; if (index_shift == 0) {
red_shift = 0; i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095;
} else {
while ((red_mask & 1) == 0) { i = ((pixel[1] << 8) | pixel[2]) & 4095;
red_mask >>= 1; }
red_shift ++;
} line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
green_mask = image->green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
green_shift = 0;
if (index_shift == 0) {
while ((green_mask & 1) == 0) { index_shift = 4;
green_mask >>= 1; } else {
green_shift ++; index_shift = 0;
} pixel += 3;
}
blue_mask = image->blue_mask; }
blue_shift = 0; break;
while ((blue_mask & 1) == 0) { case 16 :
blue_mask >>= 1; if (image->byte_order == LSBFirst) {
blue_shift ++; // Little-endian...
} for (x = image->width, line_ptr = line;
x > 0;
// Read the pixels and output an RGB image... x --, line_ptr += d, pixel += 2) {
for (y = 0; y < image->height; y ++) { i = (pixel[1] << 8) | pixel[0];
pixel = (unsigned char *)(image->data + y * image->bytes_per_line);
line = p + y * w * d; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
switch (image->bits_per_pixel) { line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
case 8 : }
for (x = image->width, line_ptr = line; } else {
x > 0; // Big-endian...
x --, line_ptr += d, pixel ++) { for (x = image->width, line_ptr = line;
i = *pixel; x > 0;
x --, line_ptr += d, pixel += 2) {
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; i = (pixel[0] << 8) | pixel[1];
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
} line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
break; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
}
case 12 : }
for (x = image->width, line_ptr = line, index_shift = 0; break;
x > 0;
x --, line_ptr += d) { case 24 :
if (index_shift == 0) { if (image->byte_order == LSBFirst) {
i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; // Little-endian...
} else { for (x = image->width, line_ptr = line;
i = ((pixel[1] << 8) | pixel[2]) & 4095; x > 0;
} x --, line_ptr += d, pixel += 3) {
i = (((pixel[2] << 8) | pixel[1]) << 8) | pixel[0];
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
if (index_shift == 0) { }
index_shift = 4; } else {
} else { // Big-endian...
index_shift = 0; for (x = image->width, line_ptr = line;
pixel += 3; x > 0;
} x --, line_ptr += d, pixel += 3) {
} i = (((pixel[0] << 8) | pixel[1]) << 8) | pixel[2];
break;
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
case 16 : line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
if (image->byte_order == LSBFirst) { line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
// Little-endian... }
for (x = image->width, line_ptr = line; }
x > 0; break;
x --, line_ptr += d, pixel += 2) {
i = (pixel[1] << 8) | pixel[0]; case 32 :
if (image->byte_order == LSBFirst) {
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; // Little-endian...
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; for (x = image->width, line_ptr = line;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; x > 0;
} x --, line_ptr += d, pixel += 4) {
} else { i = (((((pixel[3] << 8) | pixel[2]) << 8) | pixel[1]) << 8) | pixel[0];
// Big-endian...
for (x = image->width, line_ptr = line; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
x > 0; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
x --, line_ptr += d, pixel += 2) { line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
i = (pixel[0] << 8) | pixel[1]; }
} else {
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; // Big-endian...
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; for (x = image->width, line_ptr = line;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; x > 0;
} x --, line_ptr += d, pixel += 4) {
} i = (((((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]) << 8) | pixel[3];
break;
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
case 24 : line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
if (image->byte_order == LSBFirst) { line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
// Little-endian... }
for (x = image->width, line_ptr = line; }
x > 0; break;
x --, line_ptr += d, pixel += 3) { }
i = (((pixel[2] << 8) | pixel[1]) << 8) | pixel[0];
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
}
} else {
// Big-endian...
for (x = image->width, line_ptr = line;
x > 0;
x --, line_ptr += d, pixel += 3) {
i = (((pixel[0] << 8) | pixel[1]) << 8) | pixel[2];
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
}
}
break;
case 32 :
if (image->byte_order == LSBFirst) {
// Little-endian...
for (x = image->width, line_ptr = line;
x > 0;
x --, line_ptr += d, pixel += 4) {
i = (((((pixel[3] << 8) | pixel[2]) << 8) | pixel[1]) << 8) | pixel[0];
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
}
} else {
// Big-endian...
for (x = image->width, line_ptr = line;
x > 0;
x --, line_ptr += d, pixel += 4) {
i = (((((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]) << 8) | pixel[3];
line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask;
line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask;
line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask;
}
}
break;
} }
} }
// Destroy the X image we've read and return the RGB(A) image...
XDestroyImage(image);
} }
// Destroy the X image we've read and return the RGB(A) image...
XDestroyImage(image);
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, d); Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, d);
rgb->alloc_array = 1; rgb->alloc_array = 1;
return rgb; return rgb;

View File

@ -644,6 +644,16 @@ static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, i
if (cy < 0) { H += cy; Y -= cy; cy = 0; } if (cy < 0) { H += cy; Y -= cy; cy = 0; }
if (W + cx > img->data_w()) W = img->data_w() - cx; if (W + cx > img->data_w()) W = img->data_w() - cx;
if (H + cy > img->data_h()) H = img->data_h() - cy; if (H + cy > img->data_h()) H = img->data_h() - cy;
// don't attempt to read outside the window/offscreen buffer limits
Window root_return;
int x_return, y_return;
unsigned int winW, winH;
unsigned int border_width_return;
unsigned int depth_return;
XGetGeometry(fl_display, fl_window, &root_return, &x_return, &y_return, &winW,
&winH, &border_width_return, &depth_return);
if (X+W > winW) W = winW-X;
if (Y+H > winH) H = winH-Y;
if (W <= 0 || H <= 0) return; if (W <= 0 || H <= 0) return;
int ld = img->ld(); int ld = img->ld();
if (ld == 0) ld = img->data_w() * img->d(); if (ld == 0) ld = img->data_w() * img->d();