From 5bd467fa17be55397f433dddc065b57cbb7a0615 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Thu, 25 Feb 2021 11:06:54 +0100 Subject: 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? --- FL/Fl_Device.H | 4 +++- FL/Fl_Graphics_Driver.H | 4 ++++ FL/fl_draw.H | 5 +++++ src/Fl_Graphics_Driver.cxx | 19 +++++++++++++++++++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H | 2 ++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx | 17 +++++++++++++++++ src/fl_draw.cxx | 17 +++++++++++++++++ 7 files changed, 67 insertions(+), 1 deletion(-) diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H index c03219b70..e1b80adab 100644 --- a/FL/Fl_Device.H +++ b/FL/Fl_Device.H @@ -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(); }; diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 8a7a93b6f..fdebd1d50 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -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 diff --git a/FL/fl_draw.H b/FL/fl_draw.H index 4b9796acf..58168a0d7 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -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. diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index 2f687e151..00eaf5a15 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -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 diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index b61761d6f..7e4aab962 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -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 { diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx index 9d82d5c73..acabf6e73 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx @@ -17,6 +17,7 @@ #include #include "Fl_Quartz_Graphics_Driver.H" #include "../Darwin/Fl_Darwin_System_Driver.H" +#include "../../Fl_Screen_Driver.H" #include #include #include @@ -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); + } +} diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index 72a117df0..538e63f2a 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -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); +} -- cgit v1.2.3