Browse Source

Fix possible memory leak in Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled()

Thanks to "fire-eggs" for spotting it.
Also minor optimisations in Fl_X11_Screen_Driver::read_win_rectangle_unscaled() and
Fl_Cocoa_Screen_Driver::read_win_rectangle_unscaled().

This closes PR #151.
pull/166/head
ManoloFLTK 5 years ago
parent
commit
98a4e49204
  1. 8
      src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
  2. 24
      src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
  3. 8
      src/drivers/X11/Fl_X11_Screen_Driver.cxx

8
src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx

@ -342,7 +342,7 @@ void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &h @@ -342,7 +342,7 @@ void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &h
Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window,
bool may_capture_subwins, bool *did_capture_subwins)
{
int bpp, bpr, depth = 4;
int bpp, bpr;
uchar *base, *p;
if (!window) { // read from offscreen buffer
float s = 1;
@ -364,9 +364,9 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in @@ -364,9 +364,9 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in
// Copy the image from the off-screen buffer to the memory buffer.
int idx, idy; // Current X & Y in image
uchar *pdst, *psrc;
p = new uchar[w * h * depth];
p = new uchar[w * h * 4];
for (idy = Y, pdst = p; idy < h + Y; idy ++) {
for (idx = 0, psrc = base + idy * bpr + X * bpp; idx < w; idx ++, psrc += bpp, pdst += depth) {
for (idx = 0, psrc = base + idy * bpr + X * bpp; idx < w; idx ++, psrc += bpp, pdst += 4) {
pdst[0] = psrc[0]; // R
pdst[1] = psrc[1]; // G
pdst[2] = psrc[2]; // B
@ -397,7 +397,7 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in @@ -397,7 +397,7 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in
delete surf;
CFRelease(cgimg);
}
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, depth, bpr);
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, 4, bpr);
rgb->alloc_array = 1;
return rgb;
}

24
src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx

@ -503,14 +503,7 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle( @@ -503,14 +503,7 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win)
{
int d = 3; // Depth of image
int alpha = 0; uchar *p = NULL;
// Allocate the image data array as needed...
const uchar *oldp = p;
if (!p) p = new uchar[w * h * d];
// Initialize the default colors/alpha in the whole image...
memset(p, alpha, w * h * d);
// Depth of image is always 3 here
// Grab all of the pixels in the image...
@ -534,7 +527,12 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, @@ -534,7 +527,12 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y,
Y = 0;
}
if (h < 1 || w < 1) return 0/*p*/; // nothing to copy
if (h < 1 || w < 1) return 0; // nothing to copy
// Allocate and initialize the image data array
size_t arraySize = ((size_t)w * h) * 3;
uchar *p = new uchar[arraySize];
memset(p, 0, arraySize);
int line_size = ((3*w+3)/4) * 4; // each line is aligned on a DWORD (4 bytes)
uchar *dib = new uchar[line_size*h]; // create temporary buffer to read DIB
@ -572,15 +570,13 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, @@ -572,15 +570,13 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y,
for (int j = 0; j<h; j++) {
const uchar *src = dib + j * line_size; // source line
uchar *tg = p + (j + shift_y) * d * ww + shift_x * d; // target line
uchar *tg = p + (j + shift_y) * 3 * ww + shift_x * 3; // target line
for (int i = 0; i<w; i++) {
uchar b = *src++;
uchar g = *src++;
*tg++ = *src++; // R
*tg++ = g; // G
*tg++ = b; // B
if (alpha)
*tg++ = alpha; // alpha
}
}
@ -591,8 +587,8 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, @@ -591,8 +587,8 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y,
DeleteObject(hbm);
delete[] dib; // delete DIB temporary buffer
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, d);
if (!oldp) rgb->alloc_array = 1;
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, 3);
rgb->alloc_array = 1;
return rgb;
}

8
src/drivers/X11/Fl_X11_Screen_Driver.cxx

@ -750,7 +750,6 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -750,7 +750,6 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
XImage *image; // Captured image
int i, maxindex; // Looping vars
int x, y; // Current X & Y in image
int d; // Depth of image
unsigned char *line, // Array to hold image row
*line_ptr; // Pointer to current line image
unsigned char *pixel; // Current color value
@ -865,11 +864,10 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -865,11 +864,10 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
printf("map_entries = %d\n", fl_visual->visual->map_entries);
#endif // DEBUG
d = 3;
const int d = 3; // Depth of image
uchar *p = NULL;
// Allocate the image data array as needed...
const uchar *oldp = p;
if (!p) p = new uchar[w * h * d];
p = new uchar[w * h * d];
// Initialize the default colors/alpha in the whole image...
memset(p, 0, w * h * d);
@ -1167,7 +1165,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -1167,7 +1165,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
XDestroyImage(image);
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, d);
if (!oldp) rgb->alloc_array = 1;
rgb->alloc_array = 1;
return rgb;
}

Loading…
Cancel
Save