Add fl_remove_scale()/fl_restore_scale() to transiently draw without scaling factor.

This new API is a response to this message in fltk.general :
Can custom box type functions handle their own high-DPI screen scaling?
This commit is contained in:
ManoloFLTK 2021-02-25 11:06:54 +01:00
parent bef46b5cb8
commit 5bd467fa17
7 changed files with 67 additions and 1 deletions

View File

@ -81,7 +81,9 @@ public:
/** \brief Returns the graphics driver of this drawing surface. */
inline Fl_Graphics_Driver *driver() {return pGraphicsDriver; };
/** The current drawing surface.
In other words, the Fl_Surface_Device object that currently receives all graphics requests */
In other words, the Fl_Surface_Device object that currently receives all graphics requests
\note It's possible to transiently remove the GUI scaling factor in force in the current
drawing surface with \ref fl_remove_scale(). */
static inline Fl_Surface_Device *surface() {
return surface_ ? surface_ : default_surface();
};

View File

@ -364,6 +364,8 @@ public:
virtual void font_name(int num, const char *name);
// Defaut implementation may be enough
virtual void overlay_rect(int x, int y, int w , int h);
virtual float remove_scale();
virtual void restore_scale(float);
};
#ifndef FL_DOXYGEN
@ -486,6 +488,8 @@ protected:
void transformed_vertex(double xf, double yf);
virtual void transformed_vertex0(float x, float y);
void vertex(double x, double y);
virtual float remove_scale();
virtual void restore_scale(float);
};
#endif // FL_DOXYGEN

View File

@ -687,6 +687,11 @@ FL_EXPORT const char *fl_local_to_mac_roman(const char *t, int n=-1);
/** \addtogroup fl_drawings
@{ */
FL_EXPORT float fl_remove_scale();
FL_EXPORT void fl_restore_scale(float s);
/**
Draws a nul-terminated UTF-8 string starting at the given \p x, \p y location.

View File

@ -626,6 +626,9 @@ void Fl_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1);
}
float Fl_Graphics_Driver::remove_scale() { return 1.f;}
void Fl_Graphics_Driver::restore_scale(float) { }
/**
\}
@ -976,4 +979,20 @@ void Fl_Scalable_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb,
void Fl_Scalable_Graphics_Driver::transformed_vertex0(float x, float y) {}
float Fl_Scalable_Graphics_Driver::remove_scale() {
float s = scale();
if (s != 1.f) {
push_no_clip();
scale(1.f);
}
return s;
}
void Fl_Scalable_Graphics_Driver::restore_scale(float s) {
if (s != 1.f) {
scale(s);
pop_clip();
}
}
#endif

View File

@ -188,6 +188,8 @@ protected:
void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
#endif
virtual void overlay_rect(int x, int y, int w , int h);
virtual float remove_scale();
virtual void restore_scale(float);
};
class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver {

View File

@ -17,6 +17,7 @@
#include <config.h>
#include "Fl_Quartz_Graphics_Driver.H"
#include "../Darwin/Fl_Darwin_System_Driver.H"
#include "../../Fl_Screen_Driver.H"
#include <FL/platform.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Image_Surface.H>
@ -158,3 +159,19 @@ void Fl_Quartz_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &heigh
width *= 2 * scale();
height *= 2 * scale();
}
float Fl_Quartz_Graphics_Driver::remove_scale() {
float s = scale();
if (s != 1.f && Fl_Display_Device::display_device()->is_current()) {
Fl::screen_driver()->scale(0, 1.f);
CGContextScaleCTM(gc_, 1/s, 1/s);
}
return s;
}
void Fl_Quartz_Graphics_Driver::restore_scale(float s) {
if (s != 1.f && Fl_Display_Device::display_device()->is_current()) {
Fl::screen_driver()->scale(0, s);
CGContextScaleCTM(gc_, s, s);
}
}

View File

@ -458,3 +458,20 @@ int fl_height(int font, int size) {
fl_font(tf,ts); // restore
return(height);
}
/** Removes any GUI scaling factor in subsequent drawing operations.
This must be matched by a later call to fl_restore_scale().
This function can be used to transiently perform drawing operations
that are not rescaled by the current value of the GUI scaling factor.
The resulting drawing context has no clipping region.
\return The GUI scaling factor value that was applied when the function started.
*/
float fl_remove_scale() {
return fl_graphics_driver->remove_scale();
}
/** Restores the GUI scaling factor and the clipping region in subsequent drawing operations.
\param s Value returned by a previous call to fl_remove_scale(). */
void fl_restore_scale(float s) {
fl_graphics_driver->restore_scale(s);
}