diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.h | 6 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 188 | ||||
| -rw-r--r-- | src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h | 2 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h | 13 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx | 41 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h | 6 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 207 |
7 files changed, 442 insertions, 21 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h index 06e040f1a..1dd62a4e6 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.h +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_GDI_GRAPHICS_DRIVER_H #define FL_GDI_GRAPHICS_DRIVER_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** @@ -56,6 +56,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); double width(const char *str, int n); double width(unsigned int c); void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index a6d32d6e4..f12de853b 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx @@ -43,6 +43,8 @@ #define MAXBUFFER 0x40000 // 256k +void fl_release_dc(HWND, HDC); // from Fl_win32.cxx + #if USE_COLORMAP // error-diffusion dither into the FLTK colormap @@ -459,6 +461,192 @@ void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, } +static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) +{ + Fl_Offscreen offs = fl_create_offscreen(img->w(), img->h()); + if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { + fl_begin_offscreen(offs); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); + fl_end_offscreen(); + } else { + fl_begin_offscreen(offs); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); + fl_end_offscreen(); + if (img->d() == 2 || img->d() == 4) { + *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array); + } + } + return offs; +} + + +static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, + int &X, int &Y, int &W, int &H) +{ + // account for current clip region (faster on Irix): + fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w) W = w-cx; + if (W <= 0) return 1; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} + + +void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + // Don't draw an empty image... + if (!img->d() || !img->array) { + img->draw_empty(XP, YP); + return; + } + if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!img->id_) img->id_ = build_id(img, &(img->mask_)); + if (img->mask_) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)img->mask_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)img->id_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } else if (img->d()==2 || img->d()==4) { + copy_offscreen_with_alpha(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); + } else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy); + } +} + +int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { + XFORM old_tr, tr; + GetWorldTransform(fl_gc, &old_tr); // storing old transform + tr.eM11 = float(WP)/float(img->w()); + tr.eM22 = float(HP)/float(img->h()); + tr.eM12 = tr.eM21 = 0; + tr.eDx = XP; + tr.eDy = YP; + ModifyWorldTransform(fl_gc, &tr, MWT_LEFTMULTIPLY); + img->draw(0, 0, img->w(), img->h(), 0, 0); + SetWorldTransform(fl_gc, &old_tr); + return 1; +} + +void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) +{ + if (id_) { + fl_delete_offscreen((Fl_Offscreen)id_); + id_ = 0; + } + + if (mask_) { + fl_delete_bitmask((Fl_Bitmask)mask_); + mask_ = 0; + } +} + +// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... +static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) { + // we need to pad the lines out to words & swap the bits + // in each byte. + int w1 = (w + 7) / 8; + int w2 = ((w + 15) / 16) * 2; + uchar* newarray = new uchar[w2*h]; + const uchar* src = data; + uchar* dest = newarray; + Fl_Bitmask bm; + static uchar reverse[16] = /* Bit reversal lookup table */ + { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, + 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; + + for (int y = 0; y < h; y++) { + for (int n = 0; n < w1; n++, src++) + *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) | + (reverse[(*src >> 4) & 0x0f] & 0x0f)); + dest += w2 - w1; + } + + bm = CreateBitmap(w, h, 1, 1, newarray); + + delete[] newarray; + + return bm; +} + +fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmap(w, h, array); +} + +void Fl_GDI_Graphics_Driver::uncache(Fl_Bitmap *img, fl_uintptr_t &id_) { + delete_bitmask((Fl_Offscreen)id_); +} + +void Fl_GDI_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + if (pxm->mask_) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)pxm->mask_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND); + SelectObject(new_gc, (void*)pxm->id_); + BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); + } +} + + +void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); + static HMODULE hMod = NULL; + static fl_transp_func fl_TransparentBlt = NULL; + if (!hMod) { + hMod = LoadLibrary("MSIMG32.DLL"); + if(hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); + } + if (fl_TransparentBlt) { + HDC new_gc = CreateCompatibleDC(fl_gc); + int save = SaveDC(new_gc); + SelectObject(new_gc, (void*)pxm->id_); + // print all of offscreen but its parts in background color + fl_TransparentBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, W, H, pxm->pixmap_bg_color ); + RestoreDC(new_gc,save); + DeleteDC(new_gc); + } + else { + copy_offscreen(X, Y, W, H, (Fl_Offscreen)pxm->id_, cx, cy); + } +} + +fl_uintptr_t Fl_GDI_Printer_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { + Fl_Offscreen id; + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen(id); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(data, 0, 0, FL_BLACK); + extern UINT win_pixmap_bg_color; // computed by fl_draw_pixmap() + this->pixmap_bg_color = win_pixmap_bg_color; + fl_mask_bitmap = 0; + if (bitmap) { + img->mask_ = (fl_uintptr_t)fl_create_bitmask(w(), h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); + return (fl_uintptr_t)id; +} + // // End of "$Id$". // diff --git a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h index 206b90029..d4e7074fe 100644 --- a/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h +++ b/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_CFG_GFX_OPENGL_H #define FL_CFG_GFX_OPENGL_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h index f72e8be8d..04d214504 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.h @@ -22,14 +22,10 @@ \brief Definition of Apple Quartz graphics driver. */ -#include "../../config_lib.h" -#ifdef FL_CFG_GFX_QUARTZ - #ifndef FL_QUARTZ_GRAPHICS_DRIVER_H #define FL_QUARTZ_GRAPHICS_DRIVER_H -#include <FL/Fl_Device.H> - +#include <FL/Fl_Graphics_Driver.H> // typedef what the x,y fields in a point are: // FIXME: this is still defined in Fl_Device.H, but should be invisible to the user @@ -59,6 +55,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); #if ! defined(FL_DOXYGEN) static Fl_Offscreen create_offscreen_with_alpha(int w, int h); #endif @@ -122,11 +122,8 @@ protected: int descent(); }; - #endif // FL_QUARTZ_GRAPHICS_DRIVER_H -#endif // FL_CFG_GFX_QUARTZ - // // End of "$Id: quartz.H 11017 2016-01-20 21:40:12Z matt $". // diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index 442b8b29a..9a2180910 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx @@ -17,7 +17,6 @@ // #include "../../config_lib.h" -#ifdef FL_CFG_GFX_QUARTZ #include "Fl_Quartz_Graphics_Driver.h" @@ -221,12 +220,12 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, // If the CGImage is printed, it is not deallocated until after the end of the page, // therefore, with img->alloc_array != 0, the RGB image can be safely deleted any time after return from this function. // The previously unused mask_ member allows to make sure the RGB image data is not deleted by Fl_RGB_Image::uncache(). - if (img->alloc_array) img->mask_ = new bool(true); - CGDataProviderRef src = CGDataProviderCreateWithData(img->mask_, img->array, ld * img->h(), + if (img->alloc_array) img->mask_ = (fl_uintptr_t)new bool(true); + CGDataProviderRef src = CGDataProviderCreateWithData((void*)img->mask_, img->array, ld * img->h(), img->alloc_array?imgProviderReleaseData:NULL); - img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, - lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, - src, 0L, false, kCGRenderingIntentDefault); + img->id_ = (fl_uintptr_t)CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, + lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, false, kCGRenderingIntentDefault); CGColorSpaceRelease(lut); CGDataProviderRelease(src); } @@ -244,9 +243,9 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, img->uncache(); CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGDataProviderRef src = CGDataProviderCreateWithData( NULL, img_bytes, ld * img->h(), imgProviderReleaseData); - img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, - lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, - src, 0L, true, kCGRenderingIntentDefault); + img->id_ = (fl_uintptr_t)CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, + lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, true, kCGRenderingIntentDefault); CGColorSpaceRelease(lut); CGDataProviderRelease(src); } @@ -298,9 +297,31 @@ void Fl_Quartz_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { if (bm) CGImageRelease((CGImageRef)bm); } +void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { + if (id_) { + if (mask_) *(bool*)mask_ = false; + CGImageRelease((CGImageRef)id_); + id_ = 0; + mask_ = NULL; + } +} + +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmask(w, h, array); +} +void Fl_Quartz_Graphics_Driver::uncache(Fl_Bitmap*, fl_uintptr_t &id_) { + delete_bitmask((Fl_Bitmask)id_); +} -#endif // FL_CFG_GFX_QUARTZ +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_begin_offscreen(id); + fl_draw_pixmap(data, 0, 0, FL_BLACK); + fl_end_offscreen(); + return (fl_uintptr_t)id; +} // // End of "$Id$". diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h index bb55c1f53..577f5f573 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.h @@ -25,7 +25,7 @@ #ifndef FL_CFG_GFX_XLIB_H #define FL_CFG_GFX_XLIB_H -#include <FL/Fl_Device.H> +#include <FL/Fl_Graphics_Driver.H> /** \brief The Xlib-specific graphics class. @@ -52,6 +52,10 @@ public: void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); + fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + void uncache(Fl_Bitmap *img, fl_uintptr_t &id_); + void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); double width(const char *str, int n); double width(unsigned int c); void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index cf91cb3a7..479696b77 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -624,6 +624,213 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP XSetFillStyle(fl_display, fl_gc, FillSolid); } + +static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, + int &X, int &Y, int &W, int &H) +{ + // account for current clip region (faster on Irix): + fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; + // clip the box down to the size of image, quit if empty: + if (cx < 0) {W += cx; X -= cx; cx = 0;} + if (cx+W > w) W = w-cx; + if (W <= 0) return 1; + if (cy < 0) {H += cy; Y -= cy; cy = 0;} + if (cy+H > h) H = h-cy; + if (H <= 0) return 1; + return 0; +} + + +// Composite an image with alpha on systems that don't have accelerated +// alpha compositing... +static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { + int ld = img->ld(); + if (ld == 0) ld = img->w() * img->d(); + uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d(); + int srcskip = ld - img->d() * W; + + uchar *dst = new uchar[W * H * 3]; + uchar *dstptr = dst; + + fl_read_image(dst, X, Y, W, H, 0); + + uchar srcr, srcg, srcb, srca; + uchar dstr, dstg, dstb, dsta; + + if (img->d() == 2) { + // Composite grayscale + alpha over RGB... + for (int y = H; y > 0; y--, srcptr+=srcskip) + for (int x = W; x > 0; x--) { + srcg = *srcptr++; + srca = *srcptr++; + + dstr = dstptr[0]; + dstg = dstptr[1]; + dstb = dstptr[2]; + dsta = 255 - srca; + + *dstptr++ = (srcg * srca + dstr * dsta) >> 8; + *dstptr++ = (srcg * srca + dstg * dsta) >> 8; + *dstptr++ = (srcg * srca + dstb * dsta) >> 8; + } + } else { + // Composite RGBA over RGB... + for (int y = H; y > 0; y--, srcptr+=srcskip) + for (int x = W; x > 0; x--) { + srcr = *srcptr++; + srcg = *srcptr++; + srcb = *srcptr++; + srca = *srcptr++; + + dstr = dstptr[0]; + dstg = dstptr[1]; + dstb = dstptr[2]; + dsta = 255 - srca; + + *dstptr++ = (srcr * srca + dstr * dsta) >> 8; + *dstptr++ = (srcg * srca + dstg * dsta) >> 8; + *dstptr++ = (srcb * srca + dstb * dsta) >> 8; + } + } + + fl_draw_image(dst, X, Y, W, H, 3, 0); + + delete[] dst; +} + + +void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + // Don't draw an empty image... + if (!img->d() || !img->array) { + img->draw_empty(XP, YP); + return; + } + if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) { + return; + } + if (!img->id_) { + if (img->d() == 1 || img->d() == 3) { + img->id_ = fl_create_offscreen(img->w(), img->h()); + fl_begin_offscreen((Fl_Offscreen)img->id_); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); + fl_end_offscreen(); + } else if (img->d() == 4 && fl_can_do_alpha_blending()) { + img->id_ = (fl_uintptr_t)fl_create_offscreen_with_alpha(img->w(), img->h()); + fl_begin_offscreen((Fl_Offscreen)img->id_); + fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d() | FL_IMAGE_WITH_ALPHA, + img->ld()); + fl_end_offscreen(); + } + } + if (img->id_) { + if (img->mask_) { + // I can't figure out how to combine a mask with existing region, + // so cut the image down to a clipped rectangle: + int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H); + cx += nx-X; X = nx; + cy += ny-Y; Y = ny; + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, img->mask_); + int ox = X-cx; if (ox < 0) ox += img->w(); + int oy = Y-cy; if (oy < 0) oy += img->h(); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + } + + if (img->d() == 4 && fl_can_do_alpha_blending()) + copy_offscreen_with_alpha(X, Y, W, H, img->id_, cx, cy); + else + copy_offscreen(X, Y, W, H, img->id_, cx, cy); + + if (img->mask_) { + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + fl_restore_clip(); + } + } else { + // Composite image with alpha manually each time... + alpha_blend(img, X, Y, W, H, cx, cy); + } +} + +void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) +{ + if (id_) { + fl_delete_offscreen((Fl_Offscreen)id_); + id_ = 0; + } + + if (mask_) { + fl_delete_bitmask((Fl_Bitmask)mask_); + mask_ = 0; + } +} + +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { + return (fl_uintptr_t)create_bitmask(w, h, array); +} + +void Fl_Xlib_Graphics_Driver::uncache(Fl_Bitmap*, fl_uintptr_t &id_) { + delete_bitmask((Fl_Offscreen)id_); +} + + +void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + if (pxm->prepare(XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + if (pxm->mask_) { + // make X use the bitmap as a mask: + XSetClipMask(fl_display, fl_gc, pxm->mask_); + XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy); + if (clip_region()) { + // At this point, XYWH is the bounding box of the intersection between + // the current clip region and the (portion of the) pixmap we have to draw. + // The current clip region is often a rectangle. But, when a window with rounded + // corners is moved above another window, expose events may create a complex clip + // region made of several (e.g., 10) rectangles. We have to draw only in the clip + // region, and also to mask out the transparent pixels of the image. This can't + // be done in a single Xlib call for a multi-rectangle clip region. Thus, we + // process each rectangle of the intersection between the clip region and XYWH. + // See also STR #3206. + Region r = XRectangleRegion(X,Y,W,H); + XIntersectRegion(r, clip_region(), r); + int X1, Y1, W1, H1; + for (int i = 0; i < r->numRects; i++) { + X1 = r->rects[i].x1; + Y1 = r->rects[i].y1; + W1 = r->rects[i].x2 - r->rects[i].x1; + H1 = r->rects[i].y2 - r->rects[i].y1; + copy_offscreen(X1, Y1, W1, H1, pxm->id_, cx + (X1 - X), cy + (Y1 - Y)); + } + XDestroyRegion(r); + } else { + copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); + } + // put the old clip region back + XSetClipOrigin(fl_display, fl_gc, 0, 0); + restore_clip(); + } + else copy_offscreen(X, Y, W, H, pxm->id_, cx, cy); +} + +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { + Fl_Offscreen id; + id = fl_create_offscreen(w(), h()); + fl_begin_offscreen(id); + uchar *bitmap = 0; + fl_mask_bitmap = &bitmap; + fl_draw_pixmap(data(), 0, 0, FL_BLACK); + fl_mask_bitmap = 0; + if (bitmap) { + img->mask_ = (fl_uintptr_t)fl_create_bitmask(w(), h(), bitmap); + delete[] bitmap; + } + fl_end_offscreen(); + return (fl_uintptr_t)id; +} + + // // End of "$Id$". // |
