summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2018-03-19 17:43:18 +0000
committerManolo Gouy <Manolo>2018-03-19 17:43:18 +0000
commit916b44e361f275555c5f22b9d91c973ccc089037 (patch)
treea36b734804a82d3e5d4bd900bc9031b8fe60d35a /src/drivers
parentc4f7c09b7bacbfe19d1dcea5a28eeb30b1136a95 (diff)
New member function Fl_Image::scale(int width, int height) to set the FLTK size of an image.
Each image has now two sizes implemented as follows: - the pixel size is stored in private members pixel_w_ and pixel_h_ with public accessors pixel_w() and pixel_h() - the FLTK size is stored in private members w_ and h_ and read by w() and h() - when the image is constructed, the two sizes have the same value - the protected w(int) and h(int) member functions set both FLTK and pixel sizes. - the public scale(int, int) member function is essentially nothing but set the FLTK size and don't change the pixel size. - when the image is drawn, its FLTK size determines how big it is drawn, its pixel size determines how much data are available to draw it. FLTK 1.3.4 with FL_ABI_VERSION=10304 contained an equivalent member function but only for the Fl_Shared_Image class. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12776 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.H4
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx34
-rw-r--r--src/drivers/PostScript/Fl_PostScript_image.cxx138
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H5
-rw-r--r--src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx34
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H4
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx66
7 files changed, 162 insertions, 123 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
index 5bfd9b515..f6554a076 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
@@ -72,9 +72,9 @@ public:
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);
- fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
+ fl_uintptr_t cache(Fl_Pixmap *img);
virtual void uncache_pixmap(fl_uintptr_t p);
- fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
+ fl_uintptr_t cache(Fl_Bitmap *img);
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
virtual double width_unscaled(const char *str, int n);
virtual double width_unscaled(unsigned int c);
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 31d308464..349775aad 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -463,7 +463,7 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X
fl_end_offscreen(); // offscreen data is in tmp_id
SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data
// draw it to printer context with background color as transparent
- fl_TransparentBlt(gc_, X,Y,W,H, tempdc, cx, cy, bm->w(), bm->h(), RGB(r, g, b) );
+ fl_TransparentBlt(gc_, X,Y,W,H, tempdc, cx, cy, bm->pixel_w(), bm->pixel_h(), RGB(r, g, b) );
fl_delete_offscreen(tmp_id);
RestoreDC(tempdc, save);
DeleteDC(tempdc);
@@ -472,14 +472,14 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X
static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask)
{
- Fl_Image_Surface *surface = new Fl_Image_Surface(img->w(), img->h());
+ Fl_Image_Surface *surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h());
Fl_Surface_Device::push_current(surface);
if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) {
- fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
+ fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
} else {
- fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld());
+ fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), img->d(), img->ld());
if (img->d() == 2 || img->d() == 4) {
- *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array);
+ *pmask = fl_create_alphamask(img->pixel_w(), img->pixel_h(), img->d(), img->ld(), img->array);
}
}
Fl_Surface_Device::pop_current();
@@ -494,6 +494,8 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, in
Y = Y*s;
cache_size(img, W, H);
cx *= s; cy *= s;
+ if (W + cx > img->pixel_w()) W = img->pixel_w() - cx;
+ if (H + cy > img->pixel_h()) H = img->pixel_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)));
*cache_scale(img) = 1;
@@ -519,13 +521,13 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, in
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->w());
- tr.eM22 = float(HP)/float(img->h());
+ tr.eM11 = float(WP)/float(img->pixel_w());
+ tr.eM22 = float(HP)/float(img->pixel_h());
tr.eM12 = tr.eM21 = 0;
tr.eDx = float(XP);
tr.eDy = float(YP);
ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY);
- img->draw(0, 0, img->w(), img->h(), 0, 0);
+ img->draw(0, 0, img->pixel_w(), img->pixel_h(), 0, 0);
SetWorldTransform(gc_, &old_tr);
return 1;
}
@@ -546,10 +548,10 @@ int Fl_GDI_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, i
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->w(), rgb->h());
+ alpha_blend_(XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->pixel_w(), rgb->pixel_h());
} else {
SetStretchBltMode(gc_, HALFTONE);
- StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h(), SRCCOPY);
+ StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->pixel_w(), rgb->pixel_h(), SRCCOPY);
}
RestoreDC(new_gc, save);
DeleteDC(new_gc);
@@ -597,9 +599,9 @@ static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) {
return bm;
}
-fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) {
*cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale();
- return (fl_uintptr_t)fl_create_bitmap(w, h, array);
+ return (fl_uintptr_t)fl_create_bitmap(bm->pixel_w(), bm->pixel_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) {
@@ -643,16 +645,16 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int
}
-fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
+fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) {
+ Fl_Image_Surface *surf = new Fl_Image_Surface(img->pixel_w(), img->pixel_h());
Fl_Surface_Device::push_current(surf);
uchar *bitmap = 0;
Fl_Surface_Device::surface()->driver()->mask_bitmap(&bitmap);
- fl_draw_pixmap(data, 0, 0, FL_BLACK);
+ fl_draw_pixmap(img->data(), 0, 0, FL_BLACK);
*Fl_Graphics_Driver::pixmap_bg_color(img) = Fl_WinAPI_System_Driver::win_pixmap_bg_color; // computed by fl_draw_pixmap()
Fl_Surface_Device::surface()->driver()->mask_bitmap(0);
if (bitmap) {
- *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap);
+ *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(img->pixel_w(), img->pixel_h(), bitmap);
delete[] bitmap;
}
Fl_Surface_Device::pop_current();
diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx
index 579375ebc..49cb9cebe 100644
--- a/src/drivers/PostScript/Fl_PostScript_image.cxx
+++ b/src/drivers/PostScript/Fl_PostScript_image.cxx
@@ -572,33 +572,44 @@ void Fl_PostScript_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void
void Fl_PostScript_Graphics_Driver::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy){
- const char * const * di =pxm->data();
- int w,h;
- if (!fl_measure_pixmap(di, w, h)) return;
- mask=0;
- mask_bitmap(&mask);
- mx = WP;
- my = HP;
- push_clip(XP, YP, WP, HP);
- fl_draw_pixmap(di,XP -cx, YP -cy, FL_BLACK );
- pop_clip();
- delete[] mask;
- mask=0;
- mask_bitmap(0);
+ int need_clip = cx || cy || WP != pxm->w() || HP != pxm->h();
+ if (need_clip) push_clip(XP, YP, WP, HP);
+ if (pxm->w() != pxm->pixel_w() || pxm->h() != pxm->pixel_h()) {
+ draw_scaled(pxm, XP-cx, YP-cy, pxm->w(), pxm->h());
+ } else {
+ const char * const * di =pxm->data();
+ int w,h;
+ if (!fl_measure_pixmap(di, w, h)) return;
+ mask=0;
+ mask_bitmap(&mask);
+ mx = WP;
+ my = HP;
+ fl_draw_pixmap(di, XP -cx, YP -cy, FL_BLACK);
+ delete[] mask;
+ mask=0;
+ mask_bitmap(0);
+ }
+ if (need_clip) pop_clip();
}
-void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy){
- const uchar * di = rgb->array;
- int w = rgb->w();
- int h = rgb->h();
- mask=0;
- if (lang_level_>2) //when not true, not making alphamask, mixing colors instead...
- if (alpha_mask(di, w, h, rgb->d(),rgb->ld())) return; //everthing masked, no need for painting!
- push_clip(XP, YP, WP, HP);
- draw_image(di, XP + cx, YP + cy, w, h, rgb->d(), rgb->ld());
- pop_clip();
- delete[]mask;
- mask=0;
+void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy)
+{
+ int need_clip = cx || cy || WP != rgb->w() || HP != rgb->h();
+ if (need_clip) push_clip(XP, YP, WP, HP);
+ if (rgb->w() != rgb->pixel_w() || rgb->h() != rgb->pixel_h()) {
+ draw_scaled(rgb, XP-cx, YP-cy, rgb->w(), rgb->h());
+ } else {
+ const uchar * di = rgb->array;
+ int w = rgb->w();
+ int h = rgb->h();
+ mask=0;
+ if (lang_level_>2) //when not true, not making alphamask, mixing colors instead...
+ if (alpha_mask(di, w, h, rgb->d(),rgb->ld())) return; //everthing masked, no need for painting!
+ draw_image(di, XP + cx, YP + cy, w, h, rgb->d(), rgb->ld());
+ delete[]mask;
+ mask=0;
+ }
+ if (need_clip) pop_clip();
}
int Fl_PostScript_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP){
@@ -607,48 +618,55 @@ int Fl_PostScript_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, in
if (W == 0 || H == 0) return 1;
push_no_clip(); // remove the FLTK clip that can't be rescaled
clocale_printf("%d %d %i %i CL\n", X, Y, W, H);
- clocale_printf("GS %d %d TR %f %f SC GS\n", XP, YP, float(WP)/img->w(), float(HP)/img->h());
- if (img->as_rgb_image()) draw(img->as_rgb_image(), 0, 0, img->w(), img->h(), 0, 0);
- else img->draw(0, 0, img->w(), img->h(), 0, 0);
+ clocale_printf("GS %d %d TR %f %f SC GS\n", XP, YP, float(WP)/img->pixel_w(), float(HP)/img->pixel_h());
+ int keep_w = img->w(), keep_h = img->h();
+ img->scale(img->pixel_w(), img->pixel_h(), 0, 1);
+ img->draw(0, 0, img->pixel_w(), img->pixel_h(), 0, 0);
clocale_printf("GR GR\n");
+ img->scale(keep_w, keep_h, 0, 1);
pop_clip(); // restore FLTK's clip
return 1;
}
-void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy){
- const uchar * di = bitmap->array;
- int w,h;
- int LD=(bitmap->w()+7)/8;
- int xx;
-
- if (WP> bitmap->w() - cx){// to assure that it does not go out of bounds;
- w = bitmap->w() - cx;
- xx = (bitmap->w()+7)/8 - cx/8; //length of mask in bytes
- }else{
- w =WP;
- xx = (w+7)/8 - cx/8;
- }
- if ( HP > bitmap->h()-cy)
- h = bitmap->h() - cy;
- else
- h = HP;
-
- di += cy*LD + cx/8;
- int si = cx % 8; // small shift to be clipped, it is simpler than shifting whole mask
-
- int i,j;
- push_clip(XP, YP, WP, HP);
- fprintf(output , "%i %i %i %i %i %i MI\n", XP - si, YP + HP , WP , -HP , w , h);
-
- void *rle85 = prepare_rle85();
- for (j=0; j<HP; j++){
- for (i=0; i<xx; i++){
- write_rle85(swap_byte(*di), rle85);
- di++;
+void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
+ int need_clip = cx || cy || WP != bitmap->w() || HP != bitmap->h();
+ if (need_clip) push_clip(XP, YP, WP, HP);
+ if (bitmap->w() != bitmap->pixel_w() || bitmap->h() != bitmap->pixel_h()) {
+ draw_scaled(bitmap, XP-cx, YP-cy, bitmap->w(), bitmap->h());
+ } else {
+ const uchar * di = bitmap->array;
+ int w,h;
+ int LD=(bitmap->w()+7)/8;
+ int xx;
+
+ if (WP> bitmap->w() - cx){// to assure that it does not go out of bounds;
+ w = bitmap->w() - cx;
+ xx = (bitmap->w()+7)/8 - cx/8; //length of mask in bytes
+ }else{
+ w =WP;
+ xx = (w+7)/8 - cx/8;
+ }
+ if ( HP > bitmap->h()-cy)
+ h = bitmap->h() - cy;
+ else
+ h = HP;
+
+ di += cy*LD + cx/8;
+ int si = cx % 8; // small shift to be clipped, it is simpler than shifting whole mask
+
+ int i,j;
+ fprintf(output , "%i %i %i %i %i %i MI\n", XP - si, YP + HP , WP , -HP , w , h);
+
+ void *rle85 = prepare_rle85();
+ for (j=0; j<HP; j++){
+ for (i=0; i<xx; i++){
+ write_rle85(swap_byte(*di), rle85);
+ di++;
+ }
}
+ close_rle85(rle85); fputc('\n', output);
}
- close_rle85(rle85); fputc('\n', output);
- pop_clip();
+ if (need_clip) pop_clip();
}
#endif // !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT)
diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
index b23817d46..6aa8f9ef9 100644
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
+++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
@@ -70,13 +70,12 @@ 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);
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);
+ fl_uintptr_t cache(Fl_Pixmap *img);
+ fl_uintptr_t cache(Fl_Bitmap *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 e9200f3c2..1bd4d8fbc 100644
--- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
+++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
@@ -162,7 +162,7 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP,
if (!cgimg) {
CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
int ld = img->ld();
- if (!ld) ld = img->w() * img->d();
+ if (!ld) ld = img->pixel_w() * img->d();
CGDataProviderRef src;
if ( has_feature(PRINTER) ) {
// When printing, the data at img->array are used when the printed page is completed,
@@ -172,16 +172,16 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP,
// 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->h();
+ size_t total = ld * img->pixel_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->h(), NULL);
+ src = CGDataProviderCreateWithData(NULL, img->array, ld * img->pixel_h(), NULL);
}
- cgimg = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld,
+ cgimg = CGImageCreate(img->pixel_w(), img->pixel_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;
@@ -193,22 +193,6 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP,
}
}
-int Fl_Quartz_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
- int X, Y, W, H;
- fl_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;
- fl_push_no_clip(); // remove the FLTK clip that can't be rescaled
- CGContextSaveGState(gc_);
- CGContextClipToRect(gc_, CGRectMake(X, Y, W, H)); // this clip path will be rescaled & translated
- CGContextTranslateCTM(gc_, XP, YP);
- CGContextScaleCTM(gc_, float(WP)/img->w(), float(HP)/img->h());
- if (img->as_rgb_image()) draw(img->as_rgb_image(), 0, 0, img->w(), img->h(), 0, 0);
- else img->draw(0, 0, img->w(), img->h(), 0, 0);
- CGContextRestoreGState(gc_);
- fl_pop_clip(); // restore FLTK's clip
- return 1;
-}
-
void Fl_Quartz_Graphics_Driver::draw(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;
@@ -245,8 +229,8 @@ void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uin
}
}
-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);
+fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap *bm) {
+ return (fl_uintptr_t)create_bitmask(bm->pixel_w(), bm->pixel_h(), bm->array);
}
@@ -254,10 +238,10 @@ static void pmProviderRelease (void *ctxt, const void *data, size_t size) {
CFRelease(ctxt);
}
-fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
+fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img) {
+ Fl_Image_Surface *surf = new Fl_Image_Surface(img->pixel_w(), img->pixel_h());
Fl_Surface_Device::push_current(surf);
- fl_draw_pixmap(data, 0, 0, FL_BLACK);
+ fl_draw_pixmap(img->data(), 0, 0, FL_BLACK);
CGContextRef src = surf->get_offscreen_before_delete();
Fl_Surface_Device::pop_current();
delete surf;
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
index a20ec1dd3..7d74b70e1 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
@@ -122,9 +122,9 @@ 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);
- fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
+ fl_uintptr_t cache(Fl_Pixmap *img);
virtual void uncache_pixmap(fl_uintptr_t p);
- fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
+ fl_uintptr_t cache(Fl_Bitmap *img);
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
virtual double width_unscaled(const char *str, int n);
virtual double width_unscaled(unsigned int c);
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
index 901ec0078..baa0cc7c3 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
@@ -58,6 +58,8 @@
# include "../../flstring.h"
#if HAVE_XRENDER
#include <X11/extensions/Xrender.h>
+// set this to 1 to activate experimental way to cache RGB images with Xrender Picture instead of X11 Pixmap
+#define USE_XRENDER_PICTURE 0
#endif
static XImage xi; // template used to pass info to X
@@ -643,7 +645,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X, int Y
// 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();
+ if (ld == 0) ld = img->pixel_w() * img->d();
uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d();
int srcskip = ld - img->d() * W;
@@ -700,19 +702,30 @@ static Fl_Offscreen cache_rgb(Fl_RGB_Image *img) {
Fl_Image_Surface *surface;
int depth = img->d();
if (depth == 1 || depth == 3) {
- surface = new Fl_Image_Surface(img->w(), img->h());
+ surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h());
} else if (fl_can_do_alpha_blending()) {
- Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->w(), img->h(), 32);
- surface = new Fl_Image_Surface(img->w(), img->h(), 0, pixmap);
+ Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->pixel_w(), img->pixel_h(), 32);
+ surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h(), 0, pixmap);
depth |= FL_IMAGE_WITH_ALPHA;
} else {
return 0;
}
Fl_Surface_Device::push_current(surface);
- fl_draw_image(img->array, 0, 0, img->w(), img->h(), depth, img->ld());
+ fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), depth, img->ld());
Fl_Surface_Device::pop_current();
Fl_Offscreen off = surface->get_offscreen_before_delete();
delete surface;
+#if HAVE_XRENDER && USE_XRENDER_PICTURE
+ if (fl_can_do_alpha_blending()) {
+ XRenderPictureAttributes srcattr;
+ memset(&srcattr, 0, sizeof(XRenderPictureAttributes));
+ static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
+ static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24);
+ Picture pict = XRenderCreatePicture(fl_display, off, (depth%2==0 ? fmt32:fmt24), 0, &srcattr);
+ XFreePixmap(fl_display, off);
+ off = pict;
+ }
+#endif
return off;
}
@@ -724,15 +737,24 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, i
Y = (Y+offset_y_)*s;
cache_size(img, W, H);
cx *= s; cy *= s;
+ if (W + cx > img->pixel_w()) W = img->pixel_w() - cx;
+ if (H + cy > img->pixel_h()) H = img->pixel_h() - cy;
if (!*Fl_Graphics_Driver::id(img)) {
*Fl_Graphics_Driver::id(img) = cache_rgb(img);
*cache_scale(img) = 1;
}
Fl_Region r2 = scale_clip(s);
if (*Fl_Graphics_Driver::id(img)) {
- if (img->d() == 4 || img->d() == 2) {
+#if HAVE_XRENDER && USE_XRENDER_PICTURE
+ int condition = can_do_alpha_blending();
+#else
+ int condition = 0;
+#endif
+ if (img->d() == 4 || img->d() == 2 || condition) {
#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);
@@ -757,14 +779,18 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, i
void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
{
if (id_) {
- XFreePixmap(fl_display, (Fl_Offscreen)id_);
+#if HAVE_XRENDER && USE_XRENDER_PICTURE
+ if (can_do_alpha_blending()) XRenderFreePicture(fl_display, id_);
+ else
+#endif
+ XFreePixmap(fl_display, (Fl_Offscreen)id_);
id_ = 0;
}
}
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) {
*cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale();
- return (fl_uintptr_t)create_bitmask(w, h, array);
+ return (fl_uintptr_t)create_bitmask(bm->pixel_w(), bm->pixel_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) {
@@ -812,15 +838,15 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int
}
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm, int w, int h, const char *const*data) {
- Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm) {
+ Fl_Image_Surface *surf = new Fl_Image_Surface(pxm->pixel_w(), pxm->pixel_h());
Fl_Surface_Device::push_current(surf);
uchar *bitmap = 0;
Fl_Surface_Device::surface()->driver()->mask_bitmap(&bitmap);
- fl_draw_pixmap(data, 0, 0, FL_BLACK);
+ fl_draw_pixmap(pxm->data(), 0, 0, FL_BLACK);
Fl_Surface_Device::surface()->driver()->mask_bitmap(0);
if (bitmap) {
- *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(w, h, bitmap);
+ *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(pxm->pixel_w(), pxm->pixel_h(), bitmap);
delete[] bitmap;
}
Fl_Surface_Device::pop_current();
@@ -843,9 +869,13 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de
bool has_alpha = (depth == 2 || depth == 4);
XRenderPictureAttributes srcattr;
memset(&srcattr, 0, sizeof(XRenderPictureAttributes));
- static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24);
+#if USE_XRENDER_PICTURE
+ Picture src = pixmap;
+#else
+ static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
Picture src = XRenderCreatePicture(fl_display, pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr);
+#endif
Picture dst = XRenderCreatePicture(fl_display, fl_window, fmt24, 0, &srcattr);
if (!src || !dst) {
fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst);
@@ -856,17 +886,23 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de
if (clipr)
XRenderSetPictureClipRegion(fl_display, dst, clipr);
unscale_clip(r);
+#if !USE_XRENDER_PICTURE
if (scale_x != 1 || scale_y != 1) {
+#endif
XTransform mat = {{
{ XDoubleToFixed( scale_x ), XDoubleToFixed( 0 ), XDoubleToFixed( 0 ) },
{ XDoubleToFixed( 0 ), XDoubleToFixed( scale_y ), XDoubleToFixed( 0 ) },
{ XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) }
}};
XRenderSetPictureTransform(fl_display, src, &mat);
+#if !USE_XRENDER_PICTURE
}
+#endif
XRenderComposite(fl_display, (has_alpha ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0,
XP, YP, WP, HP);
+#if !USE_XRENDER_PICTURE
XRenderFreePicture(fl_display, src);
+#endif
XRenderFreePicture(fl_display, dst);
return 1;
}
@@ -881,7 +917,7 @@ int Fl_Xlib_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP,
}
cache_size(img, WP, HP);
return scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(),
- rgb->w() / double(WP), rgb->h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP);
+ rgb->pixel_w() / double(WP), rgb->pixel_h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP);
}
#endif // HAVE_XRENDER