From 2f506407327762ce30b4d895c856baa7f681d9bc Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Thu, 25 Nov 2021 11:19:10 +0100 Subject: X11+XRender platform: more accurate drawing of RGB images when GUI is scaled. RGB images are now drawn to a size that exactly fit discretised rectangles when non integral GUI scaling values are used. --- src/drivers/X11/Fl_X11_Screen_Driver.cxx | 12 ++++++++---- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 16 +++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx index 1dbd52154..4fd36edb6 100644 --- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx @@ -774,8 +774,10 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int Window xid = (win && !allow_outside ? fl_xid(win) : fl_window); float s = allow_outside ? Fl::screen_driver()->scale(win->screen_num()) : Fl_Surface_Device::surface()->driver()->scale(); - int Xs = Fl_Scalable_Graphics_Driver::floor(X, s), Ys = Fl_Scalable_Graphics_Driver::floor(Y, s), - ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs, hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys; + int Xs = Fl_Scalable_Graphics_Driver::floor(X, s); + int Ys = Fl_Scalable_Graphics_Driver::floor(Y, s); + int ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs; + int hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys; # ifdef __sgi if (XReadDisplayQueryExtension(fl_display, &i, &i)) { @@ -800,12 +802,14 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int sw = screens[ns].width; sh = screens[ns].height; } +#if ! HAVE_XRENDER if (win && !allow_outside && int(s) != s) { ws = (w+1) * s; // approximates what Fl_Graphics_Driver::cache_size() does hs = (h+1) * s; - if (Xs + ws >= int(win->w()*s)) ws = win->w()*s - Xs -1; - if (Ys + hs >= int(win->h()*s)) hs = win->h()*s - Ys -1; } +#endif + if (win && Xs + ws >= int(win->w()*s)) ws = win->w()*s - Xs -1; + if (win && Ys + hs >= int(win->h()*s)) hs = win->h()*s - Ys -1; if (ws < 1) ws = 1; if (hs < 1) hs = 1; if (!win || (dx >= sx && dy >= sy && dx + ws <= sx+sw && dy + hs <= sy+sh) ) { diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index 216f5826a..92ee52548 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -772,9 +772,15 @@ void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP if (!*Fl_Graphics_Driver::id(rgb)) { cache(rgb); } - push_clip(XP, YP, WP, HP); - int Wfull = rgb->w(), Hfull = rgb->h(), offset = 0; - cache_size(rgb, Wfull, Hfull); + float s = scale(); + int Xs = Fl_Scalable_Graphics_Driver::floor(XP - cx, s); + int Wfull = Fl_Scalable_Graphics_Driver::floor(XP - cx + rgb->w(), s) - Xs ; + int Ys = Fl_Scalable_Graphics_Driver::floor(YP - cy, s); + int Hfull = Fl_Scalable_Graphics_Driver::floor(YP - cy + rgb->h(), s) - Ys; + if (Wfull == 0 || Hfull == 0) return; + bool need_clip = (cx || cy || WP < rgb->w() || HP < rgb->h()); + if (need_clip) push_clip(XP, YP, WP, HP); + int offset = 0; if (Wfull > rgb->data_w() || Hfull > rgb->data_h()) { // When enlarging while drawing with XRender, 1 pixel around target area seems unpainted, // so we increase a bit the target area and move it 1 pixel to left and top. @@ -783,9 +789,9 @@ void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP } scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull), - floor(XP-cx) + floor(offset_x_) - offset, floor(YP-cy) + floor(offset_y_) - offset, + Xs + this->floor(offset_x_) - offset, Ys + this->floor(offset_y_) - offset, Wfull, Hfull); - pop_clip(); + if (need_clip) pop_clip(); } /* Draws with Xrender an Fl_Offscreen with optional scaling and accounting for transparency if necessary. -- cgit v1.2.3