diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index 0429eac0c..b47b8fd88 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -22,6 +22,7 @@ #include #include #include +#include FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current driver of graphics operations @@ -75,8 +76,10 @@ int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { /** see fl_copy_offscreen() */ void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { - // This platform-independent version is used when the current graphics driver is PostScript. - // It requires that pixmap has been created by fl_create_offscreen(). + // This platform-independent version can be used by any graphics driver, + // noticeably the PostScript driver. + // More efficient platform-specific implementations exist for other graphics drivers. + Fl_Image_Surface *surface = NULL; int px_width = w, px_height = h; Fl::screen_driver()->offscreen_size(pixmap, px_width, px_height); int px = srcx, py = srcy, pw = w, ph = h; @@ -84,9 +87,19 @@ void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen if (py < 0) {py = 0; ph += srcy; y -= srcy;} if (px + pw > px_width) {pw = px_width - px;} if (py + ph > px_height) {ph = px_height - py;} + Fl_Surface_Device *current = Fl_Surface_Device::surface(); fl_begin_offscreen(pixmap); + // test whether pixmap was not created by fl_create_offscreen() + if (current == Fl_Surface_Device::surface()) { + surface = new Fl_Image_Surface(px_width, px_height, 0, pixmap); + Fl_Surface_Device::push_current(surface); + } uchar *img = fl_read_image(NULL, px, py, pw, ph, 0); - fl_end_offscreen(); + if (surface) { + Fl_Surface_Device::pop_current(); + surface->get_offscreen_before_delete(); // so deleting surface does not touch pixmap + delete surface; + } else fl_end_offscreen(); if (img) { fl_draw_image(img, x, y, pw, ph, 3, 0); delete[] img; diff --git a/src/Fl_Image_Surface.cxx b/src/Fl_Image_Surface.cxx index 2fa60fd1f..632bc3de0 100644 --- a/src/Fl_Image_Surface.cxx +++ b/src/Fl_Image_Surface.cxx @@ -146,6 +146,7 @@ void fl_delete_offscreen(Fl_Offscreen ctx) { if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen() == ctx) { delete offscreen_api_surface[i]; offscreen_api_surface[i] = NULL; + return; } } } diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx index 54a4a038f..933593e6d 100644 --- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx @@ -34,7 +34,7 @@ public: Window pre_window; HDC _sgc; int _savedc; - Fl_GDI_Image_Surface_Driver(int w, int h, int high_res); + Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_GDI_Image_Surface_Driver(); void set_current(); void translate(int x, int y); @@ -45,13 +45,13 @@ public: Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { - return new Fl_GDI_Image_Surface_Driver(w, h, high_res); + return new Fl_GDI_Image_Surface_Driver(w, h, high_res, off); } -Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res) : Fl_Image_Surface_Driver(w, h, high_res, 0) { +Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, 0) { previous = 0; - offscreen = CreateCompatibleBitmap( (fl_graphics_driver->gc() ? (HDC)fl_graphics_driver->gc() : fl_GetDC(0) ) , w, h); + offscreen = off ? off : CreateCompatibleBitmap( (fl_graphics_driver->gc() ? (HDC)fl_graphics_driver->gc() : fl_GetDC(0) ) , w, h); driver(new Fl_Translated_GDI_Graphics_Driver); _sgc = NULL; } diff --git a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx index cb22904aa..2404c531f 100644 --- a/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx @@ -30,7 +30,7 @@ class Fl_Quartz_Image_Surface_Driver : public Fl_Image_Surface_Driver { virtual void end_current_(); public: Window pre_window; - Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res); + Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_Quartz_Image_Surface_Driver(); void set_current(); void translate(int x, int y); @@ -39,17 +39,17 @@ public: }; -Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen) +Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { - return new Fl_Quartz_Image_Surface_Driver(w, h, high_res); + return new Fl_Quartz_Image_Surface_Driver(w, h, high_res, off); } -Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res) : Fl_Image_Surface_Driver(w, h, high_res, 0) { +Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, 0) { int W = high_res ? 2*w : w; int H = high_res ? 2*h : h; CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); - offscreen = CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast); + offscreen = off ? off : CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(lut); driver(new Fl_Quartz_Graphics_Driver); CGContextTranslateCTM(offscreen, 0.5, -0.5); // as when drawing to a window