Fix use of an SVG image in Fl_Tiled_Image when display is rescaled.

This commit is contained in:
ManoloFLTK 2020-07-30 17:41:22 +02:00
parent f9bdb5a4db
commit 889acc7d74
9 changed files with 27 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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_;}

View File

@ -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)) {

View File

@ -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); }

View File

@ -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();
}

View File

@ -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)) {