diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx | 86 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.h | 1 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx | 112 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h | 1 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx | 41 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h | 1 |
6 files changed, 242 insertions, 0 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx index 6e782b2b5..0eaf23752 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx @@ -36,6 +36,92 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() return new Fl_GDI_Graphics_Driver(); } +// Code used to switch output to an off-screen window. See macros in +// win32.H which save the old state in local variables. + +typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION; +typedef BOOL (WINAPI* fl_alpha_blend_func) +(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION); +static fl_alpha_blend_func fl_alpha_blend = NULL; +static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1}; + +/* + * This function checks if the version of MSWindows that we + * curently run on supports alpha blending for bitmap transfers + * and finds the required function if so. + */ +char Fl_GDI_Graphics_Driver::can_do_alpha_blending() { + static char been_here = 0; + static char can_do = 0; + // do this test only once + if (been_here) return can_do; + been_here = 1; + // load the library that implements alpha blending + HMODULE hMod = LoadLibrary("MSIMG32.DLL"); + // give up if that doesn't exist (Win95?) + if (!hMod) return 0; + // now find the blending function inside that dll + fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend"); + // give up if we can't find it (Win95) + if (!fl_alpha_blend) return 0; + // we have the call, but does our display support alpha blending? + // get the desktop's device context + HDC dc = GetDC(0L); + if (!dc) return 0; + // check the device capabilities flags. However GetDeviceCaps + // does not return anything useful, so we have to do it manually: + + HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1); + HDC new_gc = CreateCompatibleDC(dc); + int save = SaveDC(new_gc); + SelectObject(new_gc, bm); + /*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101); + BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc); + RestoreDC(new_gc, save); + DeleteDC(new_gc); + DeleteObject(bm); + ReleaseDC(0L, dc); + + if (alpha_ok) can_do = 1; + return can_do; +} + +HDC fl_makeDC(HBITMAP bitmap) { + HDC new_gc = CreateCompatibleDC(fl_gc); + SetTextAlign(new_gc, TA_BASELINE|TA_LEFT); + SetBkMode(new_gc, TRANSPARENT); +#if USE_COLORMAP + if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE); +#endif + SelectObject(new_gc, bitmap); + return new_gc; +} + +void Fl_GDI_Graphics_Driver::copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, bitmap); + BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); + RestoreDC(new_gc, save); + DeleteDC(new_gc); +} + +void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, bitmap); + BOOL alpha_ok = 0; + // first try to alpha blend + if ( fl_can_do_alpha_blending() ) { + alpha_ok = fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc); + } + // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 + if (!alpha_ok) { + BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); + } + RestoreDC(new_gc, save); + DeleteDC(new_gc); +} // // End of "$Id$". diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h index 1dd62a4e6..2dbdbe430 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h @@ -41,6 +41,7 @@ public: static const char *class_id; const char *class_name() {return class_id;}; virtual int has_feature(driver_feature mask) { return mask & NATIVE; } + char can_do_alpha_blending(); // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx index f2d68eaa1..a8ed4185e 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx @@ -42,6 +42,118 @@ Fl_Offscreen Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(int w, int h return (Fl_Offscreen)ctx; } +char Fl_Quartz_Graphics_Driver::can_do_alpha_blending() { + return 1; +} + +static void bmProviderRelease (void *src, const void *data, size_t size) { + CFIndex count = CFGetRetainCount(src); + CFRelease(src); + if(count == 1) free((void*)data); +} + +void Fl_Quartz_Graphics_Driver::copy_offscreen(int x,int y,int w,int h,Fl_Offscreen osrc,int srcx,int srcy) { + CGContextRef src = (CGContextRef)osrc; + void *data = CGBitmapContextGetData(src); + int sw = CGBitmapContextGetWidth(src); + int sh = CGBitmapContextGetHeight(src); + CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + // when output goes to a Quartz printercontext, release of the bitmap must be + // delayed after the end of the print page + CFRetain(src); + CGDataProviderRef src_bytes = CGDataProviderCreateWithData( src, data, sw*sh*4, bmProviderRelease); + CGImageRef img = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha, + src_bytes, 0L, false, kCGRenderingIntentDefault); + // fl_push_clip(); + CGRect rect = CGRectMake(x, y, w, h); + Fl_X::q_begin_image(rect, srcx, srcy, sw, sh); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CGImageRelease(img); + CGColorSpaceRelease(lut); + 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] = fl_gc; + stack_window[stack_ix] = fl_window; + } else + fprintf(stderr, "FLTK CGContext Stack overflow error\n"); + stack_ix++; + + fl_gc = (CGContextRef)ctx; + fl_window = 0; + CGContextSaveGState(fl_gc); + 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(); + CGContextRestoreGState(fl_gc); // matches CGContextSaveGState in fl_begin_offscreen() + CGContextFlush(fl_gc); + if (stack_ix>0) + stack_ix--; + else + fprintf(stderr, "FLTK CGContext Stack underflow error\n"); + if (stack_ix<stack_max) { + fl_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.h b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h index 04d214504..5d2c0ccb0 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h @@ -43,6 +43,7 @@ public: static const char *class_id; const char *class_name() {return class_id;}; virtual int has_feature(driver_feature mask) { return mask & NATIVE; } + char can_do_alpha_blending(); // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx index 0385413f1..cdcfd4548 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx @@ -21,6 +21,10 @@ #include "../../config_lib.h" #include "Fl_Xlib_Graphics_Driver.h" +#if HAVE_XRENDER +#include <X11/extensions/Xrender.h> +#endif + const char *Fl_Xlib_Graphics_Driver::class_id = "Fl_Xlib_Graphics_Driver"; @@ -34,6 +38,43 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() return new Fl_Xlib_Graphics_Driver(); } +char Fl_Xlib_Graphics_Driver::can_do_alpha_blending() { + return Fl_X::xrender_supported(); +} + + +void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { + XCopyArea(fl_display, pixmap, fl_window, fl_gc, srcx, srcy, w, h, x, y); +} + +void Fl_Xlib_Graphics_Driver::copy_offscreen_with_alpha(int x, int y, int w, int h, + Fl_Offscreen pixmap, int srcx, int srcy) { +#if HAVE_XRENDER + XRenderPictureAttributes srcattr; + memset(&srcattr, 0, sizeof(XRenderPictureAttributes)); + static XRenderPictFormat *srcfmt = XRenderFindStandardFormat(fl_display, PictStandardARGB32); + static XRenderPictFormat *dstfmt = XRenderFindStandardFormat(fl_display, PictStandardRGB24); + + Picture src = XRenderCreatePicture(fl_display, pixmap, srcfmt, 0, &srcattr); + Picture dst = XRenderCreatePicture(fl_display, fl_window, dstfmt, 0, &srcattr); + + if (!src || !dst) { + fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst); + return; + } + + const Fl_Region clipr = fl_clip_region(); + if (clipr) + XRenderSetPictureClipRegion(fl_display, dst, clipr); + + XRenderComposite(fl_display, PictOpOver, src, None, dst, srcx, srcy, 0, 0, + x, y, w, h); + + XRenderFreePicture(fl_display, src); + XRenderFreePicture(fl_display, dst); +#endif +} + // // End of "$Id$". // diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h index 577f5f573..8cd086a2a 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h @@ -37,6 +37,7 @@ public: static const char *class_id; const char *class_name() {return class_id;}; virtual int has_feature(driver_feature mask) { return mask & NATIVE; } + char can_do_alpha_blending(); // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); |
