summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-03-03 08:32:16 +0000
committerManolo Gouy <Manolo>2016-03-03 08:32:16 +0000
commit8bd3ea6c8ac066002b035f10f3657449f6beadb1 (patch)
treeb4f8a783fc28295b6cc234d008832b5e707aab6f /src
parent78a539f69538e621f6e05ba4373508a8767705e8 (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.cxx67
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx27
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;
}