diff options
| author | Manolo Gouy <Manolo> | 2016-03-03 08:32:16 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2016-03-03 08:32:16 +0000 |
| commit | 8bd3ea6c8ac066002b035f10f3657449f6beadb1 (patch) | |
| tree | b4f8a783fc28295b6cc234d008832b5e707aab6f /src | |
| parent | 78a539f69538e621f6e05ba4373508a8767705e8 (diff) | |
A hopefully clearer implementation of the fl_XXX_offscreen() functions.
The Xlib driver is tricky because it uses two kinds of offscreen buffers.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11277 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Image_Surface.cxx | 67 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 27 |
2 files changed, 59 insertions, 35 deletions
diff --git a/src/Fl_Image_Surface.cxx b/src/Fl_Image_Surface.cxx index 2d2bbbaa3..728d8d5a9 100644 --- a/src/Fl_Image_Surface.cxx +++ b/src/Fl_Image_Surface.cxx @@ -46,6 +46,7 @@ public: int printable_rect(int *w, int *h) {*w = width; *h = height; return 0;} Fl_RGB_Image *image(); void end_current(); + Fl_Offscreen get_offscreen_before_delete(); }; Fl_Image_Surface::Helper::Helper(int w, int h, int high_res) : Fl_Widget_Surface(NULL), width(w), height(h) { @@ -69,9 +70,11 @@ Fl_Image_Surface::Helper::Helper(int w, int h, int high_res) : Fl_Widget_Surface } Fl_Image_Surface::Helper::~Helper() { - void *data = CGBitmapContextGetData((CGContextRef)offscreen); - free(data); - CGContextRelease((CGContextRef)offscreen); + if (offscreen) { + void *data = CGBitmapContextGetData((CGContextRef)offscreen); + free(data); + CGContextRelease((CGContextRef)offscreen); + } } void Fl_Image_Surface::Helper::set_current() { @@ -141,6 +144,7 @@ public: Fl_RGB_Image *image(); void end_current(); int printable_rect(int *w, int *h) {*w = width; *h = height; return 0;} + Fl_Offscreen get_offscreen_before_delete(); }; Fl_Image_Surface::Helper::Helper(int w, int h, int high_res) : Fl_Widget_Surface(NULL), width(w), height(h) { @@ -151,7 +155,7 @@ Fl_Image_Surface::Helper::Helper(int w, int h, int high_res) : Fl_Widget_Surface } Fl_Image_Surface::Helper::~Helper() { - DeleteObject(offscreen); + if (offscreen) DeleteObject(offscreen); } void Fl_Image_Surface::Helper::set_current() { @@ -204,6 +208,7 @@ void Fl_Image_Surface::Helper::end_current() class Fl_Image_Surface::Helper : public Fl_Widget_Surface { // class model friend class Fl_Image_Surface; public: + Fl_Offscreen offscreen; int width; int height; Helper(int w, int h, int high_res) : Fl_Widget_Surface(NULL), width(w), height(h) {} // to implement @@ -214,6 +219,7 @@ public: Fl_RGB_Image *image() {} // to implement void end_current() {} // to implement int printable_rect(int *w, int *h) {*w = width; *h = height; return 0;} + Fl_Offscreen get_offscreen_before_delete(); }; @@ -240,6 +246,7 @@ public: int printable_rect(int *w, int *h) {*w = width; *h = height; return 0;} Fl_RGB_Image *image(); void end_current(); + Fl_Offscreen get_offscreen_before_delete(); public: }; @@ -260,7 +267,7 @@ Fl_Image_Surface::Helper::Helper(Fl_Offscreen pixmap, int w, int h) : Fl_Widget_ } Fl_Image_Surface::Helper::~Helper() { - XFreePixmap(fl_display, offscreen); + if (offscreen) XFreePixmap(fl_display, offscreen); } void Fl_Image_Surface::Helper::set_current() { @@ -299,6 +306,12 @@ void Fl_Image_Surface::Helper::end_current() #endif +Fl_Offscreen Fl_Image_Surface::Helper::get_offscreen_before_delete() { + Fl_Offscreen keep = offscreen; + offscreen = 0; + return keep; +} + /** Constructor with optional high resolution. \param w and \param h give the size in pixels of the resulting image. \param high_res if non-zero, the surface pixel size is twice as high and wide as w and h, @@ -312,6 +325,17 @@ Fl_Image_Surface::Fl_Image_Surface(int w, int h, int high_res) : Fl_Widget_Surfa driver(platform_surface->driver()); } +/** Special constructor that is effective on the Xlib platform only. + */ +Fl_Image_Surface::Fl_Image_Surface(Fl_Offscreen pixmap, int w, int h) : Fl_Widget_Surface(NULL) { +#ifdef FL_CFG_GFX_XLIB + platform_surface = new Helper(pixmap, w, h); +#else + platform_surface = new Helper(w, h, 0); +#endif + driver(platform_surface->driver()); +} + /** The destructor. */ Fl_Image_Surface::~Fl_Image_Surface() { delete platform_surface; } @@ -354,9 +378,15 @@ Fl_Shared_Image* Fl_Image_Surface::highres_image() return s_img; } +/** Allows to delete the Fl_Image_Surface object while keeping its underlying Fl_Offscreen + */ +Fl_Offscreen Fl_Image_Surface::get_offscreen_before_delete() { + return platform_surface->get_offscreen_before_delete(); +} + // implementation of the fl_XXX_offscreen() functions -static void **offscreen_api_surface = NULL; +static Fl_Image_Surface **offscreen_api_surface = NULL; static int count_offscreens = 0; static int current_offscreen; @@ -367,7 +397,7 @@ static int find_slot(void) { // return an available slot to memorize an Fl_Image } if (count_offscreens >= max) { max += 20; - offscreen_api_surface = (void**)realloc(offscreen_api_surface, max * sizeof(void *)); + offscreen_api_surface = (Fl_Image_Surface**)realloc(offscreen_api_surface, max * sizeof(void *)); return find_slot(); } return count_offscreens++; @@ -384,27 +414,18 @@ static int find_slot(void) { // return an available slot to memorize an Fl_Image */ Fl_Offscreen fl_create_offscreen(int w, int h) { int rank = find_slot(); - offscreen_api_surface[rank] = new Fl_Image_Surface::Helper::Helper(w, h, 0); - return ((Fl_Image_Surface::Helper**)offscreen_api_surface)[rank]->offscreen; + offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, 0); + return offscreen_api_surface[rank]->offscreen(); } -#ifdef USE_X11 -Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h) { - int rank = find_slot(); - Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, 32); - offscreen_api_surface[rank] = new Fl_Image_Surface::Helper::Helper(pixmap, w, h); - return pixmap; -} -#endif - /** Deletion of an offscreen graphics buffer. \param ctx the buffer to be deleted. */ void fl_delete_offscreen(Fl_Offscreen ctx) { if (!ctx) return; for (int i = 0; i < count_offscreens; i++) { - if (offscreen_api_surface[i] && ((Fl_Image_Surface::Helper**)offscreen_api_surface)[i]->offscreen == ctx) { - delete ((Fl_Image_Surface::Helper**)offscreen_api_surface)[i]; + if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen() == ctx) { + delete offscreen_api_surface[i]; offscreen_api_surface[i] = NULL; } } @@ -416,8 +437,8 @@ void fl_delete_offscreen(Fl_Offscreen ctx) { void fl_begin_offscreen(Fl_Offscreen ctx) { for (current_offscreen = 0; current_offscreen < count_offscreens; current_offscreen++) { if (offscreen_api_surface[current_offscreen] && - ((Fl_Image_Surface::Helper**)offscreen_api_surface)[current_offscreen]->offscreen == ctx) { - ((Fl_Image_Surface::Helper**)offscreen_api_surface)[current_offscreen]->set_current(); + offscreen_api_surface[current_offscreen]->offscreen() == ctx) { + offscreen_api_surface[current_offscreen]->set_current(); return; } } @@ -426,7 +447,7 @@ void fl_begin_offscreen(Fl_Offscreen ctx) { /** Quit sending drawing commands to the current offscreen buffer. */ void fl_end_offscreen() { - ((Fl_Image_Surface::Helper**)offscreen_api_surface)[current_offscreen]->end_current(); + offscreen_api_surface[current_offscreen]->end_current(); } /** @} */ diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index 069fc925e..f9cc87c82 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -49,6 +49,7 @@ # include <FL/Fl.H> # include <FL/fl_draw.H> # include <FL/x.H> +# include <FL/Fl_Image_Surface.H> # include "../../Fl_XColor.H" # include "../../flstring.h" #include <X11/Xregion.h> @@ -713,18 +714,20 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, in return; } if (!img->id_) { - if (img->d() == 1 || img->d() == 3) { - img->id_ = fl_create_offscreen(img->w(), img->h()); - fl_begin_offscreen((Fl_Offscreen)img->id_); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); - fl_end_offscreen(); - } else if (img->d() == 4 && fl_can_do_alpha_blending()) { - img->id_ = (fl_uintptr_t)fl_create_offscreen_with_alpha(img->w(), img->h()); - fl_begin_offscreen((Fl_Offscreen)img->id_); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d() | FL_IMAGE_WITH_ALPHA, - img->ld()); - fl_end_offscreen(); + Fl_Image_Surface *surface; + int depth = img->d(); + if (depth == 1 || depth == 3) { + surface = new Fl_Image_Surface(img->w(), img->h()); + } else if (depth == 4 && fl_can_do_alpha_blending()) { + Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->w(), img->h(), 32); + surface = new Fl_Image_Surface(pixmap, img->w(), img->h()); + depth |= FL_IMAGE_WITH_ALPHA; } + surface->set_current(); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), depth, img->ld()); + surface->end_current(); + img->id_ = surface->get_offscreen_before_delete(); + delete surface; } if (img->id_) { if (img->mask_) { @@ -759,7 +762,7 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, in void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { - fl_delete_offscreen((Fl_Offscreen)id_); + XFreePixmap(fl_display, (Fl_Offscreen)id_); id_ = 0; } |
