mirror of https://github.com/fltk/fltk
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
This commit is contained in:
parent
78a539f695
commit
8bd3ea6c8a
|
@ -47,9 +47,6 @@
|
|||
*/
|
||||
class FL_EXPORT Fl_Image_Surface : public Fl_Widget_Surface {
|
||||
friend Fl_Offscreen fl_create_offscreen(int w, int h);
|
||||
#ifndef FL_DOXYGEN
|
||||
friend Fl_Offscreen fl_create_offscreen_with_alpha(int, int);//X11 only
|
||||
#endif
|
||||
friend void fl_begin_offscreen(Fl_Offscreen ctx);
|
||||
friend void fl_end_offscreen(void);
|
||||
friend void fl_delete_offscreen(Fl_Offscreen ctx);
|
||||
|
@ -62,6 +59,7 @@ protected:
|
|||
void untranslate();
|
||||
public:
|
||||
Fl_Image_Surface(int w, int h, int high_res = 0);
|
||||
Fl_Image_Surface(Fl_Offscreen off, int w, int h);
|
||||
~Fl_Image_Surface();
|
||||
void set_current();
|
||||
void end_current();
|
||||
|
@ -70,6 +68,7 @@ public:
|
|||
void origin(int *x, int *y);
|
||||
void origin(int x, int y);
|
||||
int printable_rect(int *w, int *h);
|
||||
Fl_Offscreen get_offscreen_before_delete();
|
||||
};
|
||||
|
||||
#endif // Fl_Image_Surface_H
|
||||
|
|
1
FL/x.H
1
FL/x.H
|
@ -96,7 +96,6 @@ extern FL_EXPORT const XEvent* fl_xevent;
|
|||
extern FL_EXPORT ulong fl_event_time;
|
||||
|
||||
typedef ulong Fl_Offscreen;
|
||||
extern FL_EXPORT Fl_Offscreen fl_create_offscreen_with_alpha(int,int);
|
||||
|
||||
// Bitmap masks
|
||||
typedef ulong Fl_Bitmask;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue