From 889acc7d74a8d5c79d4016900294246a9b04b9c2 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Thu, 30 Jul 2020 17:41:22 +0200 Subject: [PATCH] Fix use of an SVG image in Fl_Tiled_Image when display is rescaled. --- FL/Fl_Graphics_Driver.H | 3 ++- src/Fl_Graphics_Driver.cxx | 8 ++++---- src/Fl_SVG_Image.cxx | 12 ++++++------ src/Fl_Screen_Driver.H | 3 --- src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H | 1 - src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 8 ++++---- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H | 1 + src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx | 5 +++++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 10 +++++----- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 88c70b3fd..813613fbb 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -82,6 +82,7 @@ class FL_EXPORT Fl_Graphics_Driver { friend class Fl_Pixmap; friend class Fl_Bitmap; friend class Fl_RGB_Image; + friend class Fl_SVG_Image; friend void fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L); friend void fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L); friend void fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D); @@ -235,7 +236,7 @@ protected: static void draw_empty(Fl_Image* img, int X, int Y) {img->draw_empty(X, Y);} Fl_Graphics_Driver(); - void cache_size(Fl_Image *img, int &width, int &height); + virtual void cache_size(int &width, int &height); static unsigned need_pixmap_bg_color; public: virtual ~Fl_Graphics_Driver() {} ///< Destructor diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index 81b9f29ed..125f79072 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -200,7 +200,7 @@ unsigned Fl_Graphics_Driver::font_desc_size() { /** Converts \p width and \p height from FLTK units to drawing units. The conversion performed consists in multiplying \p width and \p height by scale() and in slightly modifying that to help support tiled images. */ -void Fl_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) +void Fl_Graphics_Driver::cache_size(int &width, int &height) { if ( int(scale()) == scale() ) { width = width * scale(); @@ -222,7 +222,7 @@ void Fl_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int } // to allow rescale at runtime int w2=pxm->w(), h2=pxm->h(); - cache_size(pxm, w2, h2); // after this, w2 x h2 is size of desired cached image + cache_size(w2, h2); // after this, w2 x h2 is size of desired cached image int *pw, *ph; cache_w_h(pxm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap if (*id(pxm) && (*pw != w2 || *ph != h2)) { @@ -255,7 +255,7 @@ void Fl_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int return; } int w2 = bm->w(), h2 = bm->h(); - cache_size(bm, w2, h2); // after this, w2 x h2 is size of desired cached image + cache_size(w2, h2); // after this, w2 x h2 is size of desired cached image int *pw, *ph; cache_w_h(bm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap if (*id(bm) && (*pw != w2 || *ph != h2)) { @@ -295,7 +295,7 @@ void Fl_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int int w2, h2, *pw, *ph; if (need_scaled_drawing) { w2 = img->w(); h2 = img->h(); - cache_size(img, w2, h2); + cache_size(w2, h2); } else { w2 = img->data_w(); h2 = img->data_h(); } // after this, w2 x h2 is desired cached image size diff --git a/src/Fl_SVG_Image.cxx b/src/Fl_SVG_Image.cxx index 06c3beb61..ca9644fe1 100644 --- a/src/Fl_SVG_Image.cxx +++ b/src/Fl_SVG_Image.cxx @@ -235,18 +235,18 @@ void Fl_SVG_Image::resize(int width, int height) { void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) { - float f = fl_graphics_driver->scale(); - if (fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) f *= 2; - else f *= Fl::screen_driver()->retina_factor(); - int w1 = w(), h1 = h(); - /* When f > 1, there may be several pixels per FLTK unit in an area + /* There may be several pixels per FLTK unit in an area of size w() x h() of the display. This occurs, e.g., with Apple retina displays and when the display is rescaled. The SVG is rasterized to the area dimension in pixels. The image is then drawn scaled to its size expressed in FLTK units. With this procedure, the SVG image is drawn using the full resolution of the display. */ - resize(f*w(), f*h()); + int w1 = w(), h1 = h(); + int f = fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER) ? 2 : 1; + int w2 = f*w(), h2 = f*h(); + fl_graphics_driver->cache_size(w2, h2); + resize(w2, h2); scale(w1, h1, 0, 1); Fl_RGB_Image::draw(X, Y, W, H, cx, cy); } diff --git a/src/Fl_Screen_Driver.H b/src/Fl_Screen_Driver.H index 5ab942f21..1e1d90460 100644 --- a/src/Fl_Screen_Driver.H +++ b/src/Fl_Screen_Driver.H @@ -187,9 +187,6 @@ public: /** Returns the platform's support for rescaling the application with ctrl-/+/-/0/ keys. */ virtual APP_SCALING_CAPABILITY rescalable() { return NO_APP_SCALING; } - /* Number of pixels per drawing unit for the display. - The default implementation may be enough. */ - virtual float retina_factor() { return 1; } // supports Fl_Window::default_icons() virtual void default_icons(const Fl_RGB_Image *icons[], int count); }; diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H index 23af18f6f..4ea00677d 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H +++ b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H @@ -98,7 +98,6 @@ public: virtual void open_display_platform(); // --- compute dimensions of an Fl_Offscreen virtual void offscreen_size(Fl_Offscreen o, int &width, int &height); - virtual float retina_factor() { return 2; } virtual APP_SCALING_CAPABILITY rescalable() { return SYSTEMWIDE_APP_SCALING; } virtual float scale(int n) {return scale_;} diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index 6bc9ad82d..37507b435 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx @@ -400,7 +400,7 @@ void Fl_GDI_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { 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); + cache_size(W, H); cx *= scale(); cy *= scale(); HDC tempdc = CreateCompatibleDC(gc_); @@ -500,7 +500,7 @@ void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img) 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); + cache_size(W, H); 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; @@ -538,7 +538,7 @@ void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, 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); + cache_size(W, H); HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb)); @@ -628,7 +628,7 @@ void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) { 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); + cache_size(W, H); cx *= scale(); cy *= scale(); Fl_Region r2 = scale_clip(scale()); if (*Fl_Graphics_Driver::mask(pxm)) { diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index 6f511c6e4..67265c304 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -59,6 +59,7 @@ protected: CGLineJoin quartz_line_join_; CGFloat *quartz_line_pattern; int quartz_line_pattern_size; + virtual void cache_size(int &width, int &height); public: Fl_Quartz_Graphics_Driver(); virtual ~Fl_Quartz_Graphics_Driver() { if (p) free(p); } diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx index 4ea518c9a..f8fab114e 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx @@ -153,3 +153,8 @@ void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r) { free(r); } } + +void Fl_Quartz_Graphics_Driver::cache_size(int &width, int &height) { + width *= 2 * scale(); + height *= 2 * scale(); +} diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index b20a84cfe..2e0b4af50 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -625,7 +625,7 @@ void Fl_Xlib_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) { 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); + cache_size(W, H); cx *= scale(); cy *= scale(); XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm)); int ox = X-cx; if (ox < 0) ox += bm->w()*scale(); @@ -727,7 +727,7 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) { 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); + cache_size(W, H); 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); @@ -764,9 +764,9 @@ 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); } - cache_size(rgb, W, H); + cache_size(W, H); int Wfull = rgb->w(), Hfull = rgb->h(); - cache_size(rgb, Wfull, Hfull); + cache_size(Wfull, Hfull); scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull), cx*scale(), cy*scale(), (X + offset_x_)*scale(), (Y + offset_y_)*scale(), W, H); @@ -829,7 +829,7 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) { 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); + cache_size(W, H); cx *= scale(); cy *= scale(); Fl_Region r2 = scale_clip(scale()); if (*Fl_Graphics_Driver::mask(pxm)) {