From 94f0278d4771c816f3303efd2e8fa10fc6c41b7a Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Tue, 9 Feb 2016 21:54:38 +0000 Subject: [PATCH] Porting efforts, minimal Android stuff, cleanup. - Moving code around for Fl_Double_Window, but not yet happy - Tested CMake for Android cross compilation. Very happy! git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11142 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Graphics_Driver.H | 1 + FL/fl_utf8.h | 3 + FL/x.H | 2 + README.Android.txt | 95 +++++++ src/Fl_Double_Window.cxx | 249 +----------------- src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx | 86 ++++++ src/drivers/GDI/Fl_GDI_Graphics_Driver.h | 1 + .../Quartz/Fl_Quartz_Graphics_Driver.cxx | 112 ++++++++ .../Quartz/Fl_Quartz_Graphics_Driver.h | 1 + src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx | 41 +++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h | 1 + 11 files changed, 344 insertions(+), 248 deletions(-) create mode 100644 README.Android.txt diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 45e008a6a..1b5452bed 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -136,6 +136,7 @@ public: Fl_Graphics_Driver(); virtual ~Fl_Graphics_Driver() { if (p) free(p); } public: + virtual char can_do_alpha_blending() { return 0; } // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx virtual void point(int x, int y) = 0; virtual void rect(int x, int y, int w, int h) = 0; diff --git a/FL/fl_utf8.h b/FL/fl_utf8.h index b19f2a962..2b283400d 100644 --- a/FL/fl_utf8.h +++ b/FL/fl_utf8.h @@ -57,6 +57,9 @@ # include # include # define xchar wchar_t +#elif defined(ANDROID) +# include +# define xchar wchar_t #elif defined(FL_PORTING) # pragma message "FL_PORTING: include utf8 support files and define utf8 types" # define xchar unsigned short diff --git a/FL/x.H b/FL/x.H index 2358ed003..d5a3e6e94 100644 --- a/FL/x.H +++ b/FL/x.H @@ -30,6 +30,8 @@ # include "win32.H" # elif defined(__APPLE__) # include "mac.H" +# elif defined(ANDROID) +# error "A clean port requires a driver-style system for Fl_X" # elif defined(FL_PORTING) # pragma message "FL_PORTING: write a header file based on this file, win32.H, or mac.H to define the FLTK core internals" # include "porting.H" diff --git a/README.Android.txt b/README.Android.txt new file mode 100644 index 000000000..e8a23b873 --- /dev/null +++ b/README.Android.txt @@ -0,0 +1,95 @@ +README.Android.txt - Building and using FLTK with CMake for the Android platform +-------------------------------------------------------------------------------- + + +WARNING: BUILDING FLTK FOR ANDROID IS WORK IN PROGRESS IN A PRETTY EARLY STAGE. +WARNING: THIS FILE MERELY CONTAINS A ROUGH LAYOUT AND SOME SIMPLE IDEAS HOW + FLTK WILL BUILD FOR ANDROID EVENTUALLY. + + + CONTENTS +========== + + 1 INTRODUCTION TO CMAKE + 2 USING CMAKE TO BUILD FLTK + 2.1 Prerequisites + 2.2 Options + 2.3 Building under Linux with Unix Makefiles + 2.4 Crosscompiling + 3 USING CMAKE WITH FLTK + 3.1 Library names + 3.2 Using Fluid files + 4 DOCUMENT HISTORY + + + INTRODUCTION TO CMAKE +======================= + +Please read README.CMake.txt in the same directory to learn about CMake. + +More information on CMake can be found on its web site http://www.cmake.org. + + + + USING CMAKE TO BUILD FLTK FOR ANDROID ON OS X AND LINUX +========================================================= + + + PREREQUISITES +--------------- + +Get CMake 3.2.3 or newer. + +Go to https://github.com/taka-no-me/android-cmake and download the content +as a zip file. + +Go into the FLTK base directory, then: + +> mkdir build +> cd build +> unzip ~/Downloads/android-cmake-master.zip +> mv android-cmake-master Android +> cd Android +> cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK=~/dev/android-ndk-r10e -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a" ../.. +> make + +At this time, compilation will fail relatively soon, but we are working hard to make porting easier, +and to prove our work, we poert FLTK to Android at the same time. Using CMake to cross-compile +is one of the many steps required to make life easier and maintenance more flexible. + + + OPTIONS +--------- +Options can be specified to cmake with the -D flag: + + cmake -D = + + + +WARNING: Old outdated information: + +Building FLTK on Android (pre alpha, don't expect miracles) + + +1. cd to the root of its source code ('cd android/hello') + +2. Run ndk-build. This builds the native code, and should result in some .so files being put into the libs directory. + +3. android update project --path . --name hello + +4. ant debug (or similar). This will build the Java code and create an .apk. Crucially, the build process will pick up the .so files left within the libs directory and include them into the .apk. + +5. adb install bin/name-of-project.apk + +6. Then launch as normal using the Android GUI or using an am start command such as you give. +6a. emulator -avd Intel_x86 + +7. adb shell am start -n com.example.native_activity + +8. adb uninstall com.example.native_activity + + + DOCUMENT HISTORY +================== + +Feb 9 2016 - matt: recreated document with more warnings and active support diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx index 9bdbf4406..c8e0dabcc 100644 --- a/src/Fl_Double_Window.cxx +++ b/src/Fl_Double_Window.cxx @@ -105,256 +105,9 @@ void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen delete[] img; } -#if defined(USE_X11) - -#include "drivers/Xlib/Fl_Xlib_Graphics_Driver.h" - -#if HAVE_XRENDER -#include -#endif - -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 -} - char fl_can_do_alpha_blending() { - return Fl_X::xrender_supported(); + return Fl_Display_Device::display_device()->driver()->can_do_alpha_blending(); } -#elif defined(WIN32) - -#include "drivers/GDI/Fl_GDI_Graphics_Driver.h" - -// 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_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); -} - - -#elif defined(__APPLE_QUARTZ__) || defined(FL_DOXYGEN) - -#include "src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h" - -char fl_can_do_alpha_blending() { - return 1; -} - -/** \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) { - 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; -} - -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); -} - -/** 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); -} - -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; - -/** 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_ix0) - stack_ix--; - else - fprintf(stderr, "FLTK CGContext Stack underflow error\n"); - if (stack_ixset_current(); -} - -/** @} */ - -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement offscreen render space generation and management" -#else -# error unsupported platform -#endif /** Forces the window to be redrawn. 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_ixpush_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_ixset_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 +#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);