Fix fl_draw_image sometimes crashes when window is scaled - cont'd (#1134)
This commit is contained in:
parent
6df2219aa0
commit
1f05a0df44
@ -79,8 +79,8 @@ class FL_EXPORT Fl_Graphics_Driver {
|
||||
friend class Fl_Bitmap;
|
||||
friend class Fl_RGB_Image;
|
||||
friend class Fl_SVG_Image;
|
||||
friend FL_EXPORT void fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L);
|
||||
friend FL_EXPORT void fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L);
|
||||
friend void fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L);
|
||||
friend void fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L);
|
||||
friend void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D);
|
||||
friend void fl_draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D);
|
||||
friend void fl_copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
@ -137,6 +137,8 @@ private:
|
||||
virtual void make_unused_color_(unsigned char &r, unsigned char &g, unsigned char &b, int color_count, void **data);
|
||||
// some platforms may need to reimplement this
|
||||
virtual void set_current_();
|
||||
void draw_image_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L);
|
||||
void draw_image_mono_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L);
|
||||
float scale_; // scale between FLTK and drawing coordinates: drawing = FLTK * scale_
|
||||
public:
|
||||
/** Creates the graphics driver that is used for core operations. */
|
||||
|
||||
@ -1078,13 +1078,17 @@ FL_EXPORT void fl_draw_radio(int x, int y, int d, Fl_Color color);
|
||||
any visual of 8 bits or less, and all common TrueColor visuals up
|
||||
to 32 bits.
|
||||
*/
|
||||
FL_EXPORT void fl_draw_image(const uchar *buf, int X, int Y, int W, int H, int D = 3, int L = 0);
|
||||
inline void fl_draw_image(const uchar *buf, int X, int Y, int W, int H, int D = 3, int L = 0) {
|
||||
fl_graphics_driver->draw_image_general_(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
/**
|
||||
Draw a gray-scale (1 channel) image.
|
||||
\see fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L)
|
||||
*/
|
||||
FL_EXPORT void fl_draw_image_mono(const uchar *buf, int X, int Y, int W, int H, int D = 1, int L = 0);
|
||||
inline void fl_draw_image_mono(const uchar *buf, int X, int Y, int W, int H, int D = 1, int L = 0) {
|
||||
fl_graphics_driver->draw_image_mono_general_(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
/**
|
||||
Draw an image using a callback function to generate image data.
|
||||
|
||||
@ -445,6 +445,60 @@ void Fl_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y
|
||||
/** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
|
||||
void Fl_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {}
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uchar *buf;
|
||||
int D_in;
|
||||
int D_out;
|
||||
int L;
|
||||
} image_data;
|
||||
|
||||
|
||||
static void scan_cb(image_data *data, int x, int y, int w, uchar *buffer) {
|
||||
const uchar *from = data->buf + y * data->L + data->D_in * x;
|
||||
while (w-- > 0) {
|
||||
memcpy(buffer, from, data->D_out);
|
||||
buffer += data->D_out;
|
||||
from += data->D_in;
|
||||
}
|
||||
}
|
||||
|
||||
/* used only by inline fl_draw_image() */
|
||||
void Fl_Graphics_Driver::draw_image_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L) {
|
||||
const bool alpha = !!(abs(D) & FL_IMAGE_WITH_ALPHA);
|
||||
int d_corrected, d_out;
|
||||
if (alpha) {
|
||||
d_corrected = D ^ FL_IMAGE_WITH_ALPHA;
|
||||
d_out = 4;
|
||||
} else {
|
||||
d_corrected = D;
|
||||
d_out = 3;
|
||||
}
|
||||
if (abs(d_corrected) > d_out) {
|
||||
image_data data;
|
||||
data.buf = buf;
|
||||
data.D_in = d_corrected;
|
||||
data.D_out = d_out;
|
||||
data.L = (L ? L : W * d_corrected);
|
||||
if (alpha) d_out |= FL_IMAGE_WITH_ALPHA;
|
||||
fl_graphics_driver->draw_image((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, d_out);
|
||||
} else
|
||||
fl_graphics_driver->draw_image(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
/* used only by inline fl_draw_image_mono() */
|
||||
void Fl_Graphics_Driver::draw_image_mono_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L) {
|
||||
if (abs(D) > 1) {
|
||||
image_data data;
|
||||
data.buf = buf;
|
||||
data.D_in = D;
|
||||
data.D_out = 1;
|
||||
data.L = (L ? L : W * D);
|
||||
fl_graphics_driver->draw_image_mono((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, 1);
|
||||
} else
|
||||
fl_graphics_driver->draw_image_mono(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
/** Support function for image drawing */
|
||||
void Fl_Graphics_Driver::delete_bitmask(fl_uintptr_t /*bm*/) {}
|
||||
|
||||
|
||||
@ -779,48 +779,3 @@ void fl_draw_radio(int x, int y, int d, Fl_Color color) {
|
||||
}
|
||||
fl_color(current);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uchar *buf;
|
||||
int D_in;
|
||||
int D_out;
|
||||
int L;
|
||||
} image_data;
|
||||
|
||||
|
||||
static void scan_cb(image_data *data, int x, int y, int w, uchar *buffer) {
|
||||
const uchar *from = data->buf + y * data->L + data->D_in * x;
|
||||
while (w-- > 0) {
|
||||
memcpy(buffer, from, data->D_out);
|
||||
buffer += data->D_out;
|
||||
from += data->D_in;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fl_draw_image(const uchar *buf, int X, int Y, int W, int H, int D, int L) {
|
||||
if (abs(D) > 3) {
|
||||
image_data data;
|
||||
data.buf = buf;
|
||||
data.D_in = D;
|
||||
data.D_out = 3;
|
||||
data.L = (L ? L : W * D);
|
||||
fl_graphics_driver->draw_image((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, 3);
|
||||
} else
|
||||
fl_graphics_driver->draw_image(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
|
||||
void fl_draw_image_mono(const uchar *buf, int X, int Y, int W, int H, int D, int L) {
|
||||
if (abs(D) > 1) {
|
||||
image_data data;
|
||||
data.buf = buf;
|
||||
data.D_in = D;
|
||||
data.D_out = 1;
|
||||
data.L = (L ? L : W * D);
|
||||
fl_graphics_driver->draw_image_mono((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, 1);
|
||||
} else
|
||||
fl_graphics_driver->draw_image_mono(buf, X, Y, W, H, D, L);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user