summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx86
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.h1
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx112
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h1
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx41
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h1
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);