From 16705ef734cd00e114e422e2cb4a5c84ad49c09f Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Thu, 12 Apr 2018 13:07:00 +0000 Subject: Image drawing: simplify the code organisation to better support Fl_Image::scale(). Graphics drivers now use up to 6 virtual member functions to support Fl_Image drawing in the context of GUI and image rescaling : virtual void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) virtual void draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) virtual void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) and virtual void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) virtual void draw_fixed(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) virtual void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12828 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_Bitmap.cxx | 2 +- src/Fl_Graphics_Driver.cxx | 38 ++--- src/Fl_Image.cxx | 2 +- src/Fl_Pixmap.cxx | 2 +- src/drivers/Android/Fl_Android_Graphics_Driver.H | 22 +-- src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 120 +++++++-------- src/drivers/GDI/Fl_GDI_Graphics_Driver.H | 15 +- src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx | 2 +- src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 169 +++++++++++++-------- src/drivers/Pico/Fl_Pico_Graphics_Driver.H | 1 - .../PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H | 1 - src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H | 1 - src/drivers/PostScript/Fl_PostScript_image.cxx | 8 +- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H | 7 +- .../Quartz/Fl_Quartz_Graphics_Driver_image.cxx | 64 ++++---- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 10 +- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 118 +++++++------- 17 files changed, 292 insertions(+), 290 deletions(-) (limited to 'src') diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index c3cbaea2a..d98d79acc 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -113,7 +113,7 @@ Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *array) } void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { - fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); + fl_graphics_driver->draw_bitmap(this, XP, YP, WP, HP, cx, cy); } int Fl_Bitmap::prepare(int XP, int YP, int WP, int HP, int &cx, int &cy, diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index cbabda596..e7b9036b9 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -69,14 +69,6 @@ void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) line_style(FL_SOLID); } -/** Draws an Fl_Image scaled to width \p W & height \p H with top-left corner at \em X,Y - \return zero when the graphics driver doesn't implement scaled drawing for the received image, - non-zero if it does implement it. - */ -int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { - return 0; -} - /** 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) { @@ -308,7 +300,7 @@ void Fl_Scalable_Graphics_Driver::circle(double x, double y, double r) { } // compute width & height of cached image so it can be tiled without undrawn gaps when scaling output -void Fl_Scalable_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) +void Fl_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) { if ( int(scale_) == scale_ ) { width = width * scale_; @@ -320,7 +312,7 @@ void Fl_Scalable_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &hei } -void Fl_Scalable_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; @@ -344,11 +336,11 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, i } else *id(pxm) = cache(pxm); } // draw pxm using its scaled id_ & pixmap_ - draw_unscaled(pxm, scale_, X, Y, W, H, cx, cy); + draw_fixed(pxm, X, Y, W, H, cx, cy); } -void Fl_Scalable_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; @@ -369,11 +361,11 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, in } else *id(bm) = cache(bm); } // draw bm using its scaled id_ - draw_unscaled(bm, scale_, X, Y, W, H, cx, cy); + draw_fixed(bm, X, Y, W, H, cx, cy); } -void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { // Don't draw an empty image... if (!img->d() || !img->array) { Fl_Graphics_Driver::draw_empty(img, XP, YP); @@ -382,14 +374,8 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP if (start_image(img, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { return; } - int need_scaled_drawing = fabs(img->w() - img->data_w()/scale_)/img->w() > 0.05 || - fabs(img->h() - img->data_h()/scale_)/img->h() > 0.05; - if (need_scaled_drawing && can_do_alpha_blending()) { // try and use the system's scaled image drawing - push_clip(XP, YP, WP, HP); - int done = draw_scaled(img, XP-cx, YP-cy, img->w(), img->h()); - pop_clip(); - if (done) return; - } + int need_scaled_drawing = ( fabs(img->w() - img->data_w()/scale_)/img->w() > 0.05 || + fabs(img->h() - img->data_h()/scale_)/img->h() > 0.05 ); // to allow rescale at runtime int w2, h2, *pw, *ph; if (need_scaled_drawing) { @@ -407,15 +393,19 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w2, h2); Fl_Image::RGB_scaling(keep); - draw_unscaled(img2, scale_, XP, YP, WP, HP, cx, cy); + cache(img2); + draw_fixed(img2, XP, YP, WP, HP, cx, cy); *id(img) = *id(img2); + *mask(img) = *mask(img2); *id(img2) = 0; + *mask(img2) = 0; *pw = w2; *ph = h2; delete img2; } else { // draw img using its scaled id_ - draw_unscaled(img, scale_, XP, YP, WP, HP, cx, cy); + if (!*id(img)) cache(img); + draw_fixed(img, XP, YP, WP, HP, cx, cy); } } diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index b1b8b64d7..0142d209d 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -643,7 +643,7 @@ void Fl_RGB_Image::desaturate() { } void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { - fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); + fl_graphics_driver->draw_rgb(this, XP, YP, WP, HP, cx, cy); } void Fl_RGB_Image::label(Fl_Widget* widget) { diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index 33c76233d..960efa8cc 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -47,7 +47,7 @@ void Fl_Pixmap::measure() { } void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { - fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); + fl_graphics_driver->draw_pixmap(this, XP, YP, WP, HP, cx, cy); } diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H index a8c7ddfd7..046735c1c 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.H +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.H @@ -54,6 +54,9 @@ protected: // - methods marked with // super: use the implemnetation of the super class // - virtual ... override functions are implemented for Android private: + virtual void draw_fixed(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) override; + virtual void draw_fixed(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) override; + virtual void draw_fixed(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) override; // some platforms may need to reimplement this // This is called from the surface device, see: end_current_() // super: virtual void set_current_(); @@ -67,6 +70,7 @@ protected: virtual fl_uintptr_t cache(Fl_Pixmap *img) override; /** Support function for Fl_Bitmap drawing */ virtual fl_uintptr_t cache(Fl_Bitmap *img) override; + virtual fl_uintptr_t cache(Fl_RGB_Image *img) override; /** Support function for Fl_RGB_Image drawing */ virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) override; // --- implementation is in src/drivers/xxx/Fl_xxx_Graphics_Driver_image.cxx @@ -78,20 +82,6 @@ protected: virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) override; /** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */ virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) override; - /** \brief Draws an Fl_RGB_Image object using this graphics driver. */ - virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) override; - /** \brief Draws an Fl_Pixmap object using this graphics driver. - * - Specifies a bounding box for the image, with the origin (upper left-hand corner) of - the image offset by the cx and cy arguments. - */ - virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) override; - /** \brief Draws an Fl_Bitmap object using this graphics driver. - * - Specifies a bounding box for the image, with the origin (upper left-hand corner) of - the image offset by the cx and cy arguments. - */ - virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) override; #if 0 virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); @@ -282,9 +272,6 @@ public: virtual const char *font_name(int num) override; /** Support for Fl::set_font() */ virtual void font_name(int num, const char *name) override; - // Draws an Fl_Image scaled to width W & height H - // TODO: we don't seem to need this until we introduce a scaling graphis driver - // super: virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); /** Support function for fl_overlay_rect() and scaled GUI. Defaut implementation may be enough */ // super: virtual bool overlay_rect_unscaled(); @@ -358,7 +345,6 @@ public: virtual int has_feature(driver_feature mask) { return mask & (NATIVE | PRINTER); } void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); #endif diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx index d4cd77951..05af4bed6 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx @@ -962,31 +962,23 @@ void Fl_Android_Graphics_Driver::circle(double x, double y, double r) } -void Fl_Android_Graphics_Driver::draw(Fl_Pixmap * pxm, int XP, int YP, int WP, int HP, int cx, int cy) +void Fl_Android_Graphics_Driver::draw_fixed(Fl_Pixmap * pxm, int X, int Y, int W, int H, int cx, int cy) { - int X, Y, W, H; - if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; - } if (*Fl_Graphics_Driver::id(pxm)) { Fl_Android_565A_Map *cache = (Fl_Android_565A_Map*)*Fl_Graphics_Driver::id(pxm); for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) { - draw(XP, YP, cache, it->clipped_rect()); + draw(X-cx, Y-cy, cache, it->clipped_rect()); } } } -void Fl_Android_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) +void Fl_Android_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { - int X, Y, W, H; - if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; - } if (*Fl_Graphics_Driver::id(bm)) { Fl_Android_Bytemap *cache = (Fl_Android_Bytemap*)*Fl_Graphics_Driver::id(bm); for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(X, Y, W, H))) { - draw(XP, YP, cache, it->clipped_rect()); + draw(X-cx, Y-cy, cache, it->clipped_rect()); } } } @@ -1050,68 +1042,65 @@ void Fl_Android_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) delete img; } - -void Fl_Android_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) +fl_uintptr_t Fl_Android_Graphics_Driver::cache(Fl_RGB_Image *img) { - int X, Y, W, H; - // Don't draw an empty image... - if (!img->d() || !img->array) { - Fl_Graphics_Driver::draw_empty(img, XP, YP); - return; - } - if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; - } - Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)*Fl_Graphics_Driver::id(img); - if (!cgimg) { - int w = img->w(), h = img->h(), d = img->d(), stride = w*d + img->ld(); - cgimg = new Fl_Android_565A_Map(w, h); - *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg; - if (d==1) { // grayscale - for (int iy=0; iyarray + iy*stride; - uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; - for (int ix=0; ixdata_w(), h = img->data_h(), d = img->d(), stride = w*d + img->ld(); + Fl_Android_565A_Map *cgimg = new Fl_Android_565A_Map(w, h); + *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg; + int *pw, *ph; + cache_w_h(img, pw, ph); + *pw = img->data_w(); + *ph = img->data_h(); + if (d==1) { // grayscale + for (int iy=0; iyarray + iy*stride; + uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; + for (int ix=0; ixarray + iy*stride; - uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; - for (int ix=0; ixarray + iy*stride; + uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; + for (int ix=0; ixarray + iy*stride; - uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; - for (int ix=0; ixarray + iy*stride; + uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; + for (int ix=0; ixarray + iy*stride; - uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; - for (int ix=0; ixarray + iy*stride; + uint32_t *dst = cgimg->pWords + iy*cgimg->pStride; + for (int ix=0; ixclipped_rect()); + draw(X-cx, Y-cy, cgimg, it->clipped_rect()); } } } @@ -1232,6 +1221,7 @@ void Fl_Android_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_ui { Fl_Android_565A_Map *cgimg = (Fl_Android_565A_Map*)id_; delete cgimg; + id_ = 0; } diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H index f6554a076..eae3b7925 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H @@ -40,7 +40,11 @@ private: int depth; // to support translation POINT *origins; // to support translation void set_current_(); + void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); protected: + void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy); + fl_uintptr_t cache(Fl_RGB_Image *rgb); HDC gc_; int numcount; int counts[20]; @@ -64,10 +68,7 @@ public: virtual void draw_unscaled(int angle, const char *str, int n, int x, int y); virtual void rtl_draw_unscaled(const char* str, int n, int x, int y); virtual void font_unscaled(Fl_Font face, Fl_Fontsize size); - void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy); - int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); + virtual void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); @@ -163,9 +164,9 @@ private: transparent_f_type TransparentBlt(); public: virtual int has_feature(driver_feature mask) { return mask & (NATIVE | PRINTER); } - void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); + void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy); }; diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx index acc58c860..a07e97313 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx @@ -125,7 +125,7 @@ void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,H SelectObject(new_gc, bitmap); BOOL alpha_ok = 0; // first try to alpha blend - if ( can_do_alpha_blending() ) { + if ( fl_can_do_alpha_blending() ) { alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h); } // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index 6b9cb6d87..af919cf5e 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx @@ -400,15 +400,11 @@ void Fl_GDI_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { DeleteObject((HGDIOBJ)bm); } -void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy) { - int X, Y, W, H; - if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; - } - X = X*s; - Y = Y*s; +void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { + X = X*scale_; + Y = Y*scale_; cache_size(bm, W, H); - cx *= s; cy *= s; + cx *= scale_; cy *= scale_; HDC tempdc = CreateCompatibleDC(gc_); int save = SaveDC(tempdc); @@ -428,17 +424,26 @@ Fl_GDI_Printer_Graphics_Driver::transparent_f_type Fl_GDI_Printer_Graphics_Drive return fpter; } -void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_GDI_Printer_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; + if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { + return; + } transparent_f_type fl_TransparentBlt = TransparentBlt(); if (!fl_TransparentBlt) { - Fl_GDI_Graphics_Driver::draw(bm, XP, YP, WP, HP, cx, cy); + Fl_Graphics_Driver::draw_bitmap(bm, X, Y, W, H, cx, cy); return; } - if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { - return; + bool recache = false; + if (*id(bm)) { + int *pw, *ph; + cache_w_h(bm, pw, ph); + recache = (*pw != bm->data_w() || *ph != bm->data_h()); + } + if (recache || !*id(bm)) { + bm->uncache(); + *Fl_Graphics_Driver::id(bm) = cache(bm); } - HDC tempdc; int save; // algorithm for bitmap output to Fl_GDI_Printer @@ -449,28 +454,31 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X g = 255-g; b = 255-b; Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's - Fl_Offscreen tmp_id = fl_create_offscreen(W, H); - fl_begin_offscreen(tmp_id); + Fl_Image_Surface *img_surf = new Fl_Image_Surface(bm->data_w(), bm->data_h()); + Fl_Surface_Device::push_current(img_surf); fl_color(background); - fl_rectf(0,0,W,H); // use this color as offscreen background + fl_rectf(0,0, bm->data_w(), bm->data_h()); // use this color as offscreen background fl_color(save_c); // back to bitmap's color HDC off_gc = (HDC)fl_graphics_driver->gc(); tempdc = CreateCompatibleDC(off_gc); save = SaveDC(tempdc); SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm)); SelectObject(off_gc, fl_brush()); // use bitmap's desired color - BitBlt(off_gc, 0, 0, W, H, tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen - fl_end_offscreen(); // offscreen data is in tmp_id - SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data + BitBlt(off_gc, 0, 0, bm->data_w(), bm->data_h(), tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen + Fl_Surface_Device::pop_current(); + SelectObject(tempdc, (HGDIOBJ)img_surf->offscreen()); // use offscreen data // draw it to printer context with background color as transparent - fl_TransparentBlt(gc_, X,Y,W,H, tempdc, cx, cy, bm->data_w(), bm->data_h(), RGB(r, g, b) ); - fl_delete_offscreen(tmp_id); + float scaleW = bm->data_w()/float(bm->w()); + float scaleH = bm->data_h()/float(bm->h()); + fl_TransparentBlt(gc_, X, Y, W, H, tempdc, cx * scaleW, cy * scaleH, W * scaleW, H * scaleH, RGB(r, g, b) ); + delete img_surf; RestoreDC(tempdc, save); DeleteDC(tempdc); -} + if (recache) bm->uncache(); +} -static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) +fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img) { Fl_Image_Surface *surface = new Fl_Image_Surface(img->data_w(), img->data_h()); Fl_Surface_Device::push_current(surface); @@ -479,31 +487,35 @@ static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) } else { fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d(), img->ld()); if (img->d() == 2 || img->d() == 4) { - *pmask = fl_create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array); + *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array); } } Fl_Surface_Device::pop_current(); Fl_Offscreen offs = surface->get_offscreen_before_delete(); delete surface; - return offs; + int *pw, *ph; + cache_w_h(img, pw, ph); + *pw = img->data_w(); + *ph = img->data_h(); + *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)offs; + return (fl_uintptr_t)offs; } -void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, int Y, int W, int H, int cx, int cy) { - X = X*s; - Y = Y*s; +void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { + X = X*scale_; + Y = Y*scale_; cache_size(img, W, H); - cx *= s; cy *= s; + cx *= scale_; cy *= scale_; if (W + cx > img->data_w()) W = img->data_w() - cx; if (H + cy > img->data_h()) H = img->data_h() - cy; if (!*Fl_Graphics_Driver::id(img)) { - *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)build_id(img, (void**)(Fl_Graphics_Driver::mask(img))); + *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cache(img); int *pw, *ph; cache_w_h(img, pw, ph); *pw = img->data_w(); *ph = img->data_h(); } - Fl_Region r2 = scale_clip(s); if (*Fl_Graphics_Driver::mask(img)) { HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); @@ -518,52 +530,65 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, in } else { copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy); } - unscale_clip(r2); -} - -int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { - XFORM old_tr, tr; - GetWorldTransform(gc_, &old_tr); // storing old transform - tr.eM11 = float(WP)/float(img->data_w()); - tr.eM22 = float(HP)/float(img->data_h()); - tr.eM12 = tr.eM21 = 0; - tr.eDx = float(XP); - tr.eDy = float(YP); - ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY); - img->draw(0, 0, img->data_w(), img->data_h(), 0, 0); - SetWorldTransform(gc_, &old_tr); - return 1; } -int Fl_GDI_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { - Fl_RGB_Image *rgb = img->as_rgb_image(); - if (!rgb || !rgb->array) return 0; // for bitmaps and pixmaps - if ((rgb->d() % 2) == 0 && !can_do_alpha_blending()) return 0; - +void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { + if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { + return; + } + if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) { + Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy); + return; + } if (!*Fl_Graphics_Driver::id(rgb)) { - *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)build_id(rgb, - (void**)(Fl_Graphics_Driver::mask(rgb))); + *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)cache(rgb); int *pw, *ph; cache_w_h(rgb, pw, ph); *pw = rgb->data_w(); *ph = rgb->data_h(); } - cache_size(img, WP, HP); + float scaleW = float(rgb->data_w())/rgb->w(); + float scaleH = float(rgb->data_h())/rgb->h(); + int W = WP, H = HP; + cache_size(rgb, W, H); HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb)); if ( (rgb->d() % 2) == 0 ) { - alpha_blend_(XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h()); + alpha_blend_(XP*scale_, YP*scale_, W, H, new_gc, cx*scaleW, cy*scaleH, WP*scaleW, HP*scaleH); } else { SetStretchBltMode(gc_, HALFTONE); - StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY); + StretchBlt(gc_, XP*scale_, YP*scale_, W, H, new_gc, cx*scaleW, cy*scaleH, WP*scaleW, HP*scaleH, SRCCOPY); } RestoreDC(new_gc, save); DeleteDC(new_gc); - return 1; } + +void Fl_GDI_Printer_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { + if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { + return; + } + XFORM old_tr, tr; + GetWorldTransform(gc_, &old_tr); // storing old transform + tr.eM11 = float(rgb->w())/float(rgb->data_w()); + tr.eM22 = float(rgb->h())/float(rgb->data_h()); + tr.eM12 = tr.eM21 = 0; + tr.eDx = float(XP); + tr.eDy = float(YP); + ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY); + if (*id(rgb)) { + int *pw, *ph; + cache_w_h(rgb, pw, ph); + if ( *pw != rgb->data_w() || *ph != rgb->data_h()) rgb->uncache(); + } + if (!*id(rgb)) cache(rgb); + draw_fixed(rgb, 0, 0, WP/tr.eM11, HP/tr.eM22, cx/tr.eM11, cy/tr.eM22); + SetWorldTransform(gc_, &old_tr); +} + + void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { @@ -613,12 +638,12 @@ fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) { return (fl_uintptr_t)fl_create_bitmap(bm->data_w(), bm->data_h(), bm->array); } -void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) { - X = X*s; - Y = Y*s; +void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { + X = X*scale_; + Y = Y*scale_; cache_size(pxm, W, H); - cx *= s; cy *= s; - Fl_Region r2 = scale_clip(s); + cx *= scale_; cy *= scale_; + Fl_Region r2 = scale_clip(scale_); if (*Fl_Graphics_Driver::mask(pxm)) { HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); @@ -635,18 +660,32 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y } -void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; - if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; + if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; transparent_f_type fl_TransparentBlt = TransparentBlt(); if (fl_TransparentBlt) { + bool recache = false; + if (*id(pxm)) { + int *pw, *ph; + cache_w_h(pxm, pw, ph); + recache = (*pw != pxm->data_w() || *ph != pxm->data_h()); + } + if (recache || !*id(pxm)) { + pxm->uncache(); + *Fl_Graphics_Driver::id(pxm) = cache(pxm); + } HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm)); // print all of offscreen but its parts in background color - fl_TransparentBlt(gc_, X, Y, W, H, new_gc, cx, cy, W, H, *Fl_Graphics_Driver::pixmap_bg_color(pxm) ); + float scaleW = pxm->data_w()/float(pxm->w()); + float scaleH = pxm->data_h()/float(pxm->h()); + fl_TransparentBlt(gc_, X, Y, W, H, new_gc, cx * scaleW, cy * scaleH, W * scaleW, H * scaleH, + *Fl_Graphics_Driver::pixmap_bg_color(pxm) ); RestoreDC(new_gc,save); DeleteDC(new_gc); + if (recache) pxm->uncache(); } else { copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy); diff --git a/src/drivers/Pico/Fl_Pico_Graphics_Driver.H b/src/drivers/Pico/Fl_Pico_Graphics_Driver.H index b7cca4529..bfc55c630 100644 --- a/src/drivers/Pico/Fl_Pico_Graphics_Driver.H +++ b/src/drivers/Pico/Fl_Pico_Graphics_Driver.H @@ -195,7 +195,6 @@ class Fl_Pico_Graphics_Driver : public Fl_Graphics_Driver { // the image offset by the cx and cy arguments. // */ // virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {} -// virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); // virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); // // /** Sets the value of the driver-specific graphics context. */ diff --git a/src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H b/src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H index 05cc6cc9b..e7708dc11 100644 --- a/src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H +++ b/src/drivers/PicoAndroid/Fl_PicoAndroid_Graphics_Driver.H @@ -49,7 +49,6 @@ public: // void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); // void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); // void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); - // int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); // void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); // 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); diff --git a/src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H b/src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H index d0bb20ff5..fd1a696a5 100644 --- a/src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H +++ b/src/drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H @@ -48,7 +48,6 @@ public: // void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); // void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); // void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); - // int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); // void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); // 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); diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx index cc91f24da..4b7c26744 100644 --- a/src/drivers/PostScript/Fl_PostScript_image.cxx +++ b/src/drivers/PostScript/Fl_PostScript_image.cxx @@ -575,7 +575,7 @@ void Fl_PostScript_Graphics_Driver::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int need_clip = cx || cy || WP != pxm->w() || HP != pxm->h(); if (need_clip) push_clip(XP, YP, WP, HP); if (pxm->w() != pxm->data_w() || pxm->h() != pxm->data_h()) { - draw_scaled(pxm, XP-cx, YP-cy, pxm->w(), pxm->h()); + scale_and_draw(pxm, XP-cx, YP-cy, pxm->w(), pxm->h()); } else { const char * const * di =pxm->data(); int w,h; @@ -597,7 +597,7 @@ void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int int need_clip = cx || cy || WP != rgb->w() || HP != rgb->h(); if (need_clip) push_clip(XP, YP, WP, HP); if (rgb->w() != rgb->data_w() || rgb->h() != rgb->data_h()) { - draw_scaled(rgb, XP-cx, YP-cy, rgb->w(), rgb->h()); + scale_and_draw(rgb, XP-cx, YP-cy, rgb->w(), rgb->h()); } else { const uchar * di = rgb->array; int w = rgb->w(); @@ -612,7 +612,7 @@ void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int if (need_clip) pop_clip(); } -int Fl_PostScript_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP){ +int Fl_PostScript_Graphics_Driver::scale_and_draw(Fl_Image *img, int XP, int YP, int WP, int HP){ int X, Y, W, H; clip_box(XP,YP,WP,HP,X,Y,W,H); // X,Y,W,H will give the unclipped area of XP,YP,WP,HP if (W == 0 || H == 0) return 1; @@ -632,7 +632,7 @@ void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int int need_clip = cx || cy || WP != bitmap->w() || HP != bitmap->h(); if (need_clip) push_clip(XP, YP, WP, HP); if (bitmap->w() != bitmap->data_w() || bitmap->h() != bitmap->data_h()) { - draw_scaled(bitmap, XP-cx, YP-cy, bitmap->w(), bitmap->h()); + scale_and_draw(bitmap, XP-cx, YP-cy, bitmap->w(), bitmap->h()); } else { const uchar * di = bitmap->array; int w,h; diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index 6aa8f9ef9..97389d15a 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -67,15 +67,16 @@ public: // --- bitmap stuff Fl_Bitmask create_bitmask(int w, int h, const uchar *array); void delete_bitmask(Fl_Bitmask bm); - void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); - void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); - void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_bitmap(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); 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); fl_uintptr_t cache(Fl_Bitmap *img); + fl_uintptr_t cache(Fl_RGB_Image *img); void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh); diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index db00f7935..2d8c1074f 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx @@ -132,7 +132,7 @@ void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { fl_rectf(x,y,w,h); } -void Fl_Quartz_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Quartz_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; @@ -142,8 +142,38 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int } } +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_RGB_Image *rgb) { + CGColorSpaceRef lut = rgb->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); + int ld = rgb->ld(); + if (!ld) ld = rgb->data_w() * rgb->d(); + CGDataProviderRef src; + if ( has_feature(PRINTER) ) { + // When printing, the data at rgb->array are used when the printed page is completed, + // that is, after return from this function. + // At that stage, the rgb object has possibly been deleted. It is therefore necessary + // to use a copy of rgb->array for printing. The mask_ member of rgb + // is used to avoid repeating the copy operation if rgb is printed again. + // The CGImage data provider deletes the copy at the latest of these two events: + // deletion of rgb, and completion of the page where rgb was printed. + size_t total = ld * rgb->data_h(); + uchar *copy = new uchar[total]; + memcpy(copy, rgb->array, total); + src = CGDataProviderCreateWithData(NULL, copy, total, dataReleaseCB); + *Fl_Graphics_Driver::mask(rgb) = 1; + } else { + // the CGImage data provider must not release the image data. + src = CGDataProviderCreateWithData(NULL, rgb->array, ld * rgb->data_h(), NULL); + } + CGImageRef cgimg = CGImageCreate(rgb->data_w(), rgb->data_h(), 8, rgb->d()*8, ld, + lut, (rgb->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, + src, 0L, false, kCGRenderingIntentDefault); + *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)cgimg; + CGColorSpaceRelease(lut); + CGDataProviderRelease(src); + return (fl_uintptr_t)cgimg; +} -void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Quartz_Graphics_Driver::draw_rgb(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) { @@ -160,40 +190,14 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, cgimg = NULL; } if (!cgimg) { - CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); - int ld = img->ld(); - if (!ld) ld = img->data_w() * img->d(); - CGDataProviderRef src; - if ( has_feature(PRINTER) ) { - // When printing, the data at img->array are used when the printed page is completed, - // that is, after return from this function. - // At that stage, the img object has possibly been deleted. It is therefore necessary - // to use a copy of img->array for printing. The mask_ member of img - // is used to avoid repeating the copy operation if img is printed again. - // The CGImage data provider deletes the copy at the latest of these two events: - // deletion of img, and completion of the page where img was printed. - size_t total = ld * img->data_h(); - uchar *copy = new uchar[total]; - memcpy(copy, img->array, total); - src = CGDataProviderCreateWithData(NULL, copy, total, dataReleaseCB); - *Fl_Graphics_Driver::mask(img) = 1; - } else { - // the CGImage data provider must not release the image data. - src = CGDataProviderCreateWithData(NULL, img->array, ld * img->data_h(), NULL); - } - cgimg = CGImageCreate(img->data_w(), img->data_h(), 8, img->d()*8, ld, - lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, - src, 0L, false, kCGRenderingIntentDefault); - *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg; - CGColorSpaceRelease(lut); - CGDataProviderRelease(src); + cgimg = (CGImageRef)cache(img); } if (cgimg && gc_) { draw_CGImage(cgimg, X,Y,W,H, cx,cy, img->w(), img->h()); } } -void Fl_Quartz_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { +void Fl_Quartz_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; CGImageRef cgimg = (CGImageRef)*Fl_Graphics_Driver::id(pxm); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H index 785c76369..7d56cad61 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H @@ -62,16 +62,16 @@ private: int line_delta_; virtual void set_current_(); int clip_max_; // +/- x/y coordinate limit (16-bit coordinate space) + virtual void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + virtual void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); + virtual void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy); protected: - virtual void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - virtual void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy); - virtual void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy); + virtual void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy); virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); #if HAVE_XRENDER - virtual int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP); #endif virtual int height_unscaled(); @@ -101,7 +101,7 @@ protected: static Window draw_window; static struct _XftDraw* draw_; #endif - Fl_Offscreen cache_rgb(Fl_RGB_Image *img); + fl_uintptr_t cache(Fl_RGB_Image *img); public: Fl_Xlib_Graphics_Driver(void); virtual ~Fl_Xlib_Graphics_Driver(); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index c271dae53..b9271e3b5 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -624,14 +624,14 @@ void Fl_Xlib_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { XFreePixmap(fl_display, bm); } -void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X, int Y, int W, int H, int cx, int cy) { - X = (X+offset_x_)*s; - Y = (Y+offset_y_)*s; +void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { + X = (X+offset_x_)*scale_; + Y = (Y+offset_y_)*scale_; cache_size(bm, W, H); - cx *= s; cy *= s; + cx *= scale_; cy *= scale_; XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm)); - int ox = X-cx; if (ox < 0) ox += bm->w()*s; - int oy = Y-cy; if (oy < 0) oy += bm->h()*s; + int ox = X-cx; if (ox < 0) ox += bm->w()*scale_; + int oy = Y-cy; if (oy < 0) oy += bm->h()*scale_; XSetTSOrigin(fl_display, gc_, ox, oy); XSetFillStyle(fl_display, gc_, FillStippled); XFillRectangle(fl_display, fl_window, gc_, X, Y, W, H); @@ -696,7 +696,7 @@ static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, i delete[] dst; } -Fl_Offscreen Fl_Xlib_Graphics_Driver::cache_rgb(Fl_RGB_Image *img) { +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) { Fl_Image_Surface *surface; int depth = img->d(); if (depth == 1 || depth == 3) { @@ -717,48 +717,53 @@ Fl_Offscreen Fl_Xlib_Graphics_Driver::cache_rgb(Fl_RGB_Image *img) { cache_w_h(img, pw, ph); *pw = img->data_w(); *ph = img->data_h(); - return off; + *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)off; + return (fl_uintptr_t)off; } -// X,Y,W,H,cx,cy are in FLTK units -// if s != 1 and id(img) != 0, the offscreen has been previously scaled by s -// if s != 1 and id(img) == 0, img has been previously scaled by s -void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, int Y, int W, int H, int cx, int cy) { - X = (X+offset_x_)*s; - Y = (Y+offset_y_)*s; + +void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { + X = (X+offset_x_)*scale_; + Y = (Y+offset_y_)*scale_; cache_size(img, W, H); - cx *= s; cy *= s; - if (W + cx > img->data_w()) W = img->data_w() - cx; - if (H + cy > img->data_h()) H = img->data_h() - cy; - if (!*Fl_Graphics_Driver::id(img)) { - *Fl_Graphics_Driver::id(img) = cache_rgb(img); - } - Fl_Region r2 = scale_clip(s); - if (*Fl_Graphics_Driver::id(img)) { - if (img->d() == 4 || img->d() == 2) { -#if HAVE_XRENDER - scale_ = 1; - scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), img->d(), 1, 1, cx, cy, X, Y, W, H); - scale_ = s; -#endif - } else { - XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y); - } - } else { - // Composite image with alpha manually each time... - scale_ = 1; - int ox = offset_x_, oy = offset_y_; - offset_x_ = offset_y_ = 0; - Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver(); - int nscreen = Fl_Window::current()->driver()->screen_num(); - float keep = d->scale(nscreen); - d->scale(nscreen, 1); - alpha_blend(img, X, Y, W, H, cx, cy); - d->scale(nscreen, keep); - scale_ = s; - offset_x_ = ox; offset_y_ = oy; + cx *= scale_; cy *= scale_; + if (img->d() == 1 || img->d() == 3) { + XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y); + return; } - unscale_clip(r2); + // Composite image with alpha manually each time... + float s = scale_; + scale_ = 1; + int ox = offset_x_, oy = offset_y_; + offset_x_ = offset_y_ = 0; + Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver(); + int nscreen = Fl_Window::current()->driver()->screen_num(); + float keep = d->scale(nscreen); + d->scale(nscreen, 1); + push_no_clip(); + alpha_blend(img, X, Y, W, H, cx, cy); + pop_clip(); + d->scale(nscreen, keep); + scale_ = s; + offset_x_ = ox; offset_y_ = oy; +} + +void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { + if (!fl_can_do_alpha_blending()) { + Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy); + return; + } + int X, Y, W, H; + if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { + return; + } + if (!*Fl_Graphics_Driver::id(rgb)) { + *Fl_Graphics_Driver::id(rgb) = cache(rgb); + } + cache_size(rgb, W, H); + scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), + rgb->data_w() / double(rgb->w()*scale_), rgb->data_h() / double(rgb->h()*scale_), + cx*scale_, cy*scale_, (X + offset_x_)*scale_, (Y + offset_y_)*scale_, W, H); } void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) @@ -777,12 +782,12 @@ fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) { return (fl_uintptr_t)create_bitmask(bm->data_w(), bm->data_h(), bm->array); } -void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) { - X = (X+offset_x_)*s; - Y = (Y+offset_y_)*s; +void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { + X = (X+offset_x_)*scale_; + Y = (Y+offset_y_)*scale_; cache_size(pxm, W, H); - cx *= s; cy *= s; - Fl_Region r2 = scale_clip(s); + cx *= scale_; cy *= scale_; + Fl_Region r2 = scale_clip(scale_); if (*Fl_Graphics_Driver::mask(pxm)) { // make X use the bitmap as a mask: XSetClipMask(fl_display, gc_, *Fl_Graphics_Driver::mask(pxm)); @@ -813,7 +818,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int } // put the old clip region back XSetClipOrigin(fl_display, gc_, 0, 0); - s = scale_; scale_ = 1; + float s = scale_; scale_ = 1; restore_clip(); scale_ = s; } @@ -884,17 +889,6 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de return 1; } -// XP,YP,WP,HP are in FLTK units -int Fl_Xlib_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { - Fl_RGB_Image *rgb = img->as_rgb_image(); - if (!rgb || !can_do_alpha_blending()) return 0; - if (!*Fl_Graphics_Driver::id(rgb)) { - *Fl_Graphics_Driver::id(rgb) = cache_rgb(rgb); - } - cache_size(img, WP, HP); - return scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), - rgb->data_w() / double(WP), rgb->data_h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP); -} #endif // HAVE_XRENDER -- cgit v1.2.3