summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-02-27 13:52:27 +0000
committerManolo Gouy <Manolo>2016-02-27 13:52:27 +0000
commit0b406baa0f05d8b829d2c35b10c8450e7628be53 (patch)
tree62d91890f7194e00ea9f40e89f640c7c013c7b45 /src
parent5d24872dc40e1047cea6337d8823718ac2acd575 (diff)
Rewrite all fl_XXX_offscreen() functions so they use an Fl_Image_Surface object.
These functions become therefore platform-independent. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11241 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
-rw-r--r--src/Fl_Copy_Surface.cxx3
-rw-r--r--src/Fl_Double_Window.cxx16
-rw-r--r--src/Fl_Image_Surface.cxx153
-rw-r--r--src/Fl_cocoa.mm7
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx8
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx90
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx3
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx4
8 files changed, 139 insertions, 145 deletions
diff --git a/src/Fl_Copy_Surface.cxx b/src/Fl_Copy_Surface.cxx
index 1484504b6..8076325bc 100644
--- a/src/Fl_Copy_Surface.cxx
+++ b/src/Fl_Copy_Surface.cxx
@@ -77,6 +77,7 @@ Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_Widget_Surface(NULL)
Fl::first_window()->make_current();
oldwindow = fl_xid(Fl::first_window());
xid = fl_create_offscreen(w,h);
+ _ss = NULL;
Fl_Surface_Device *present_surface = Fl_Surface_Device::surface();
set_current();
fl_color(FL_WHITE);
@@ -128,7 +129,7 @@ void Fl_Copy_Surface::set_current()
# pragma message "FL_PORTING: implement Fl_Copy_Surface::set_current"
#else
fl_window=xid;
- _ss = Fl_Surface_Device::surface();
+ if (!_ss) _ss = Fl_Surface_Device::surface();
Fl_Surface_Device::set_current();
fl_push_no_clip();
#endif
diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx
index 975c23dd4..243101f96 100644
--- a/src/Fl_Double_Window.cxx
+++ b/src/Fl_Double_Window.cxx
@@ -81,20 +81,6 @@ void Fl_Double_Window::show() {
}
-/** \addtogroup fl_drawings
- @{
- */
-/** Copy a rectangular area of the given offscreen buffer into the current drawing destination.
- \param x,y position where to draw the copied rectangle
- \param w,h size of the copied rectangle
- \param pixmap offscreen buffer containing the rectangle to copy
- \param srcx,srcy origin in offscreen buffer of rectangle to copy
- */
-void fl_copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
- fl_graphics_driver->copy_offscreen(x, y, w, h, pixmap, srcx, srcy);
-}
-/** @} */
-
/** 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)
{
@@ -209,7 +195,7 @@ void Fl_Double_Window::flush(int eraseoverlay) {
// on Irix (at least) it is faster to reduce the area copied to
// the current clip region:
int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H);
- if (myi->other_xid) fl_copy_offscreen(X, Y, W, H, myi->other_xid, X, Y);
+ if (myi->other_xid) fl_graphics_driver->copy_offscreen(X, Y, W, H, myi->other_xid, X, Y);
}
void Fl_Double_Window::resize(int X,int Y,int W,int H) {
diff --git a/src/Fl_Image_Surface.cxx b/src/Fl_Image_Surface.cxx
index e8642c2bf..747b051af 100644
--- a/src/Fl_Image_Surface.cxx
+++ b/src/Fl_Image_Surface.cxx
@@ -40,38 +40,56 @@
/** Constructor with optional high resolution.
\param w and \param h give the size in pixels of the resulting image.
- \param highres if non-zero, the surface pixel size is twice as high and wide as w and h,
+ \param high_res if non-zero, the surface pixel size is twice as high and wide as w and h,
which is useful to draw it later on a high resolution display (e.g., retina display).
This is implemented for the Mac OS platform only.
If \p highres is non-zero, use Fl_Image_Surface::highres_image() to get the image data.
\version 1.3.4 (1.3.3 without the highres parameter)
*/
-Fl_Image_Surface::Fl_Image_Surface(int w, int h, int highres) : Fl_Widget_Surface(NULL) {
+Fl_Image_Surface::Fl_Image_Surface(int w, int h, int high_res) : Fl_Widget_Surface(NULL) {
+ initialize_(NULL, w, h, high_res);
+}
+
+void Fl_Image_Surface::initialize_(Fl_Offscreen pixmap, int w, int h, int high_res) {
width = w;
height = h;
+ previous = 0;
#ifdef __APPLE__ // PORTME: platform image surface
- offscreen = fl_create_offscreen(highres ? 2*w : w, highres ? 2*h : h);
+ 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);
+ CGColorSpaceRelease(lut);
driver(new Fl_Quartz_Graphics_Driver);
- if (highres) {
+ CGContextTranslateCTM(offscreen, -0.5, 0.5); // as when drawing to a window
+ if (high_res) {
CGContextScaleCTM(offscreen, 2, 2);
}
CGContextSetShouldAntialias(offscreen, false);
CGContextSaveGState(offscreen);
CGContextTranslateCTM(offscreen, 0, height);
CGContextScaleCTM(offscreen, 1.0f, -1.0f);
- CGContextSetRGBFillColor(offscreen, 1, 1, 1, 1);
+ CGContextSetRGBFillColor(offscreen, 1, 1, 1, 0);
CGContextFillRect(offscreen, CGRectMake(0,0,w,h));
#elif defined(WIN32)
- offscreen = fl_create_offscreen(w, h);
+ offscreen = CreateCompatibleBitmap( (fl_graphics_driver->gc() ? (HDC)fl_graphics_driver->gc() : fl_GetDC(0) ) , w, h);
driver(new Fl_Translated_GDI_Graphics_Driver);
+ _sgc = NULL;
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
- offscreen = fl_create_offscreen(w, h);
+ offscreen = pixmap ? pixmap : XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
driver(new Fl_Translated_Xlib_Graphics_Driver());
#endif
}
+#if USE_X11
+// private constructor for X11 only
+Fl_Image_Surface::Fl_Image_Surface(Fl_Offscreen pixmap, int w, int h) : Fl_Widget_Surface(NULL) {
+ initialize_(pixmap, w, h, 0);
+ }
+#endif
+
/** The destructor.
*/
Fl_Image_Surface::~Fl_Image_Surface() {
@@ -80,11 +98,11 @@ Fl_Image_Surface::~Fl_Image_Surface() {
free(data);
CGContextRelease((CGContextRef)offscreen);
#elif defined(WIN32)
- fl_delete_offscreen(offscreen);
+ DeleteObject(offscreen);
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
- fl_delete_offscreen(offscreen);
+ XFreePixmap(fl_display, offscreen);
#endif
}
@@ -100,24 +118,16 @@ Fl_RGB_Image* Fl_Image_Surface::image()
CGContextFlush(offscreen);
W = CGBitmapContextGetWidth(offscreen);
H = CGBitmapContextGetHeight(offscreen);
- Fl_X::set_high_resolution(0);
data = fl_read_image(NULL, 0, 0, W, H, 0);
#elif defined(WIN32)
- fl_pop_clip();
data = fl_read_image(NULL, 0, 0, width, height, 0);
- HDC gc = (HDC)driver()->gc();
- RestoreDC(gc, _savedc);
- DeleteDC(gc);
- _ss->set_current();
- fl_window=_sw;
- _ss->driver()->gc(_sgc);
+ end_current();
+ previous->driver()->gc(_sgc);
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
- fl_pop_clip();
data = fl_read_image(NULL, 0, 0, width, height, 0);
- fl_window = pre_window;
- previous->set_current();
+ end_current();
#endif
Fl_RGB_Image *image = new Fl_RGB_Image(data, W, H);
image->alloc_array = 1;
@@ -141,32 +151,49 @@ Fl_Shared_Image* Fl_Image_Surface::highres_image()
void Fl_Image_Surface::set_current()
{
+ pre_window = fl_window;
+ if (!previous) previous = Fl_Surface_Device::surface();
#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform image surface
driver()->gc(offscreen);
fl_window = 0;
Fl_Surface_Device::set_current();
+ was_high = Fl_Display_Device::high_resolution();
Fl_X::set_high_resolution( CGBitmapContextGetWidth(offscreen) > width );
#elif defined(WIN32)
- _sw = fl_window;
- _ss = Fl_Surface_Device::surface();
- _sgc = (HDC)_ss->driver()->gc();
+ if (!_sgc) _sgc = (HDC)previous->driver()->gc();
HDC gc = fl_makeDC(offscreen);
Fl_Surface_Device::set_current();
driver()->gc(gc);
- _savedc = SaveDC(gc);
- fl_window=(HWND)offscreen;
+ _savedc = SaveDC(gc);
+ fl_window=(HWND)offscreen;
fl_push_no_clip();
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: implement Fl_Image_Surface"
#else
- pre_window = fl_window;
- fl_window = offscreen;
- previous = Fl_Surface_Device::surface();
+ fl_window = offscreen;
Fl_Surface_Device::set_current();
fl_push_no_clip();
#endif
}
+void Fl_Image_Surface::end_current()
+{
+#if defined(__APPLE__)
+ Fl_X::set_high_resolution(was_high);
+#elif defined(WIN32)
+ HDC gc = (HDC)driver()->gc();
+ RestoreDC(gc, _savedc);
+ DeleteDC(gc);
+ fl_pop_clip();
+#elif defined(FL_PORTING)
+# pragma message "FL_PORTING: implement Fl_Image_Surface"
+#else
+ fl_pop_clip();
+#endif
+ previous->Fl_Surface_Device::set_current();
+ fl_window = pre_window;
+}
+
#if defined(__APPLE__) // PORTME: Fl_Surface_Driver - platform image surface
void Fl_Image_Surface::translate(int x, int y) {
@@ -205,6 +232,76 @@ void Fl_Image_Surface::untranslate() {
#endif
+static Fl_Image_Surface *offscreen_api_surface[20];
+static int count = 0;
+static int current;
+
+static int find_slot() { // return an available slot to memorize an Fl_Image_Surface object
+ for (int num = 0; num < count; num++) {
+ if (!offscreen_api_surface[num]) return num;
+ }
+ if (count >= sizeof(offscreen_api_surface)/sizeof(Fl_Image_Surface*)) return -1;
+ return count++;
+ }
+
+/** \addtogroup fl_drawings
+ @{
+ */
+
+/**
+ Creation of an offscreen graphics buffer.
+ \param w,h width and height in pixels of the buffer.
+ \return the created graphics buffer.
+ */
+Fl_Offscreen fl_create_offscreen(int w, int h) {
+ int rank = find_slot();
+ if (rank < 0) return NULL;
+ offscreen_api_surface[rank] = new Fl_Image_Surface(w, h);
+ return offscreen_api_surface[rank]->offscreen;
+}
+
+#if USE_X11
+Fl_Offscreen fl_create_offscreen_with_alpha(int w, int h) {
+ int rank = find_slot();
+ if (rank < 0) return NULL;
+ Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, 32);
+ offscreen_api_surface[rank] = new Fl_Image_Surface(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; i++) {
+ if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen == ctx) {
+ delete offscreen_api_surface[i];
+ offscreen_api_surface[i] = NULL;
+ }
+ }
+}
+
+/** Send all subsequent drawing commands to this offscreen buffer.
+ \param ctx the offscreen buffer.
+ */
+void fl_begin_offscreen(Fl_Offscreen ctx) {
+ for (current = 0; current < count; current++) {
+ if (offscreen_api_surface[current] && offscreen_api_surface[current]->offscreen == ctx) {
+ offscreen_api_surface[current]->set_current();
+ return;
+ }
+ }
+}
+
+/** Quit sending drawing commands to the current offscreen buffer.
+ */
+void fl_end_offscreen() {
+ offscreen_api_surface[current]->end_current();
+}
+
+/** @} */
//
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 898c68136..5b70130ad 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -3309,7 +3309,7 @@ void Fl_X::q_release_context(Fl_X *x) {
if (!gc) return;
CGContextRestoreGState(gc); // match the CGContextSaveGState's of make_current
CGContextRestoreGState(gc);
- Fl_X::set_high_resolution(false);
+// Fl_X::set_high_resolution(false);
CGContextFlush(gc);
Fl_Display_Device::display_device()->driver()->gc(0);
#if defined(FLTK_USE_CAIRO)
@@ -3886,12 +3886,13 @@ static NSImage *imageFromText(const char *text, int *pwidth, int *pheight)
}
height = nl * fl_height() + 3;
width += 6;
- Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(width, height);
+ Fl_Offscreen off = fl_create_offscreen(width, height);
fl_begin_offscreen(off);
CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0);
fl_rectf(0,0,width,height);
fl_color(FL_BLACK);
p = text;
+ fl_font(FL_HELVETICA, 10);
int y = fl_height();
while(TRUE) {
q = strchr(p, '\n');
@@ -3922,7 +3923,7 @@ static NSImage *defaultDragImage(int *pwidth, int *pheight)
else {
width = 16; height = 16;
}
- Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(width, height);
+ Fl_Offscreen off = fl_create_offscreen(width, height);
fl_begin_offscreen(off);
if (fl_mac_os_version >= version_threshold) {
fl_font(FL_HELVETICA, 20);
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 4a1c6e007..f750e1785 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -173,7 +173,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
int blocking = h;
{int size = linesize*h;
// when printing, don't limit buffer size not to get a crash in StretchDIBits
- if (size > MAXBUFFER && Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) {
+ if (size > MAXBUFFER && !fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) {
size = MAXBUFFER;
blocking = MAXBUFFER/linesize;
}
@@ -251,7 +251,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
}
}
}
- if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) {
+ if (fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) {
// if print context, device and logical units are not equal, so SetDIBitsToDevice
// does not do the expected job, whereas StretchDIBits does it.
StretchDIBits(gc, x, y+j-k, w, k, 0, 0, w, k,
@@ -633,11 +633,11 @@ fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const c
id = fl_create_offscreen(w, h);
fl_begin_offscreen(id);
uchar *bitmap = 0;
- mask_bitmap(&bitmap);
+ fl_graphics_driver->mask_bitmap(&bitmap);
fl_draw_pixmap(data, 0, 0, FL_BLACK);
extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap()
img->pixmap_bg_color = win_pixmap_bg_color;
- mask_bitmap(0);
+ fl_graphics_driver->mask_bitmap(0);
if (bitmap) {
img->mask_ = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap);
delete[] bitmap;
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
index 7186a030a..f1b159960 100644
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
+++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
@@ -40,16 +40,6 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
return new Fl_Quartz_Graphics_Driver();
}
-#ifndef FL_DOXYGEN
-Fl_Offscreen Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(int w, int h) {
- void *data = calloc(w*h,4);
- CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
- CGContextRef ctx = CGBitmapContextCreate(data, w, h, 8, w*4, lut, kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(lut);
- return (Fl_Offscreen)ctx;
-}
-#endif
-
char Fl_Quartz_Graphics_Driver::can_do_alpha_blending() {
return 1;
}
@@ -80,86 +70,6 @@ void Fl_Quartz_Graphics_Driver::copy_offscreen(int x,int y,int w,int h,Fl_Offscr
CGDataProviderRelease(src_bytes);
}
-/** \addtogroup fl_drawings
- @{
- */
-
-// FIXME: driver system
-/**
- Creation of an offscreen graphics buffer.
- \param w,h width and height in pixels of the buffer.
- \return the created graphics buffer.
- */
-Fl_Offscreen fl_create_offscreen(int w, int h) {
- void *data = calloc(w*h,4);
- CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
- CGContextRef ctx = CGBitmapContextCreate(
- data, w, h, 8, w*4, lut, kCGImageAlphaNoneSkipLast);
- CGColorSpaceRelease(lut);
- return (Fl_Offscreen)ctx;
-}
-
-// FIXME: driver system
-/** Deletion of an offscreen graphics buffer.
- \param ctx the buffer to be deleted.
- */
-void fl_delete_offscreen(Fl_Offscreen ctx) {
- if (!ctx) return;
- void *data = CGBitmapContextGetData((CGContextRef)ctx);
- CFIndex count = CFGetRetainCount(ctx);
- CGContextRelease((CGContextRef)ctx);
- if(count == 1) free(data);
-}
-
-// FIXME: driver system
-const int stack_max = 16;
-static int stack_ix = 0;
-static CGContextRef stack_gc[stack_max];
-static Window stack_window[stack_max];
-static Fl_Surface_Device *_ss;
-
-// FIXME: driver system
-/** Send all subsequent drawing commands to this offscreen buffer.
- \param ctx the offscreen buffer.
- */
-void fl_begin_offscreen(Fl_Offscreen ctx) {
- _ss = Fl_Surface_Device::surface();
- Fl_Display_Device::display_device()->set_current();
- if (stack_ix<stack_max) {
- stack_gc[stack_ix] = (CGContextRef)fl_graphics_driver->gc();
- stack_window[stack_ix] = fl_window;
- } else
- fprintf(stderr, "FLTK CGContext Stack overflow error\n");
- stack_ix++;
-
- fl_graphics_driver->gc(ctx);
- fl_window = 0;
- CGContextSaveGState(ctx);
- fl_graphics_driver->push_no_clip();
-}
-
-// FIXME: driver system
-/** Quit sending drawing commands to the current offscreen buffer.
- */
-void fl_end_offscreen() {
- fl_graphics_driver->pop_clip();
- CGContextRef gc = (CGContextRef)fl_graphics_driver->gc();
-
- CGContextRestoreGState(gc); // matches CGContextSaveGState in fl_begin_offscreen()
- CGContextFlush(gc);
- if (stack_ix>0)
- stack_ix--;
- else
- fprintf(stderr, "FLTK CGContext Stack underflow error\n");
- if (stack_ix<stack_max) {
- fl_graphics_driver->gc(stack_gc[stack_ix]);
- fl_window = stack_window[stack_ix];
- }
- _ss->set_current();
-}
-
-/** @} */
-
//
// End of "$Id$".
//
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
index a72e09b1e..3574adce5 100644
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
+++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
@@ -301,8 +301,7 @@ fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uc
}
fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
- Fl_Offscreen id;
- id = create_offscreen_with_alpha(w, h);
+ Fl_Offscreen id = fl_create_offscreen(w, h);
fl_begin_offscreen(id);
fl_draw_pixmap(data, 0, 0, FL_BLACK);
fl_end_offscreen();
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
index e1da7df3f..723c22838 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
@@ -812,9 +812,9 @@ fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const
id = fl_create_offscreen(w, h);
fl_begin_offscreen(id);
uchar *bitmap = 0;
- mask_bitmap(&bitmap);
+ fl_graphics_driver->mask_bitmap(&bitmap);
fl_draw_pixmap(data, 0, 0, FL_BLACK);
- mask_bitmap(0);
+ fl_graphics_driver->mask_bitmap(0);
if (bitmap) {
img->mask_ = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap);
delete[] bitmap;