diff options
| author | Manolo Gouy <Manolo> | 2016-02-27 13:52:27 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2016-02-27 13:52:27 +0000 |
| commit | 0b406baa0f05d8b829d2c35b10c8450e7628be53 (patch) | |
| tree | 62d91890f7194e00ea9f40e89f640c7c013c7b45 /src | |
| parent | 5d24872dc40e1047cea6337d8823718ac2acd575 (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.cxx | 3 | ||||
| -rw-r--r-- | src/Fl_Double_Window.cxx | 16 | ||||
| -rw-r--r-- | src/Fl_Image_Surface.cxx | 153 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 7 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 8 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx | 90 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx | 3 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 4 |
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; |
