Subject: bug#37770: closed (Re: bug#37770: [PATCH] Expose scale factor through the redisplay interface)

From: [email-masked] (GNU bug Tracking System)
Date: Thu, 24 Oct 2019 14:35:05 +0000

Your bug report

#37770: [PATCH] Expose scale factor through the redisplay interface

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
37770: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=37770
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#37770: [PATCH] Expose scale factor through the redisplay interface
From: Carlos Pita <[email-masked]>
To: Robert Pluim <[email-masked]>
Cc: Eli Zaretskii <[email-masked]>, [email-masked]
Date: Thu, 24 Oct 2019 11:34:01 -0300
List-Id: <debbugs-submit.debbugs.gnu.org>

>
>
> If emacs used only GTK to draw things to the screen, then indeed there
> would be no need for those conversions, as GTK would handle them.
>

Exactly.

>
> <https://github.com/masm11/emacs> is attempting to implement a 'pure'
> GTK backend. I have no idea how close it is to being ready to merge.
>

That's great. The way towards Wayland also. Sounds like a LOT of work,
though.

I've been working in an alternative to this patch and the one that fixes
the cairo fringe. My goal is to provide a gtk+cairo solution that listen to
gtk scale changes and scales everything (including fonts) accordingly. This
would enable an adaptive multi-monitor multi-dpi emacs using the old
scale-up-gtk then scale-down-xrandr trick, a nice implementation of which,
including GUI and everything,  is going to be part of the next Ubuntu LTS
with high probability.

I'm having a really hard time making the font engine abandon it's idea of
pixel-sized fonts that is very entrenched in its caching mechanism once
everything was first rendered at some initial dpi. The only way I found to
circumvent this is to report a fixed 96dpi resolution and then scale all
cairo rendering (fonts, images, bitmaps) using the platform scaling factor.
This mostly works but I'm still unable to get rid of all previously opened
fonts, even after clearing all ftcrfont caches, so I get a mix of different
sized fonts. It will probably take me some time to figure out what's
happening.

So I'm closing this issue and will open a new one once I have an integral
cairo+gtk solution working in a way that mostly resembles the nsterm
backend.

Best regards
--
Carlos

Subject: [PATCH] Expose scale factor through the redisplay interface
From: Carlos Pita <[email-masked]>
To: [email-masked]
Date: Tue, 15 Oct 2019 19:29:58 -0300
List-Id: <debbugs-submit.debbugs.gnu.org>

I need this in order to move forward #37689.

Besides I did some related changes proposed in #37752, which I'm no
closing in favor of this one.

Here is the commit message:

    * src/dispextern.h: add get_scale_factor API.
    * src/xterm.c:
      - Unify usages of xg_get_scale and x_get_scale_factor into a
        consolidated x_get_scale_factor that is exported by the rif.
      - Simplify scale inferring logic (see note below).
    * src/w32term.c:
      - Simplify w32_get_scale_factor in a similar way (see note).
      - Add it to the rif.
    * src/nsterm.m:
      - Just add NULL to the rif since there are no uses of any scale
        factor here. Clients are expected to interpret a missing API
        as meaning scale factor = 1.

    Note: both x_get_scale_factor and w32_get_scale_factor computed
    distinct scales for x and y by taking the ratio between effective
    resolution in each direction and a standard 96 dpi resolution.  Since
    this ratio is then truncated to an integer (the floor) it seems to me
    that there is no sensible possibility that these two numbers
    diverge. Moreover, modern toolkits report one number as scale factor
    and we need a common interface here. For those reasons I'm arbitrarily
    picking the horizontal scale factor as THE scale factor.

Best regards
--
Carlos
From 494b2864e97d8035365b32079e0949a7633c3338 Mon Sep 17 00:00:00 2001
From: memeplex <[email-masked]>
Date: Tue, 15 Oct 2019 19:14:03 -0300
Subject: [PATCH] Expose scale factor through the redisplay interface

* src/dispextern.h: add get_scale_factor API.
* src/xterm.c:
  - Unify usages of xg_get_scale and x_get_scale_factor into a
    consolidated x_get_scale_factor that is exported by the rif.
  - Simplify scale inferring logic (see note below).
* src/w32term.c:
  - Simplify w32_get_scale_factor in a similar way (see note).
  - Add it to the rif.
* src/nsterm.m:
  - Just add NULL to the rif since there are no uses of any scale
    factor here. Clients are expected to interpret a missing API
    as meaning scale factor = 1.

Note: both x_get_scale_factor and w32_get_scale_factor computed
distinct scales for x and y by taking the ratio between effective
resolution in each direction and a standard 96 dpi resolution.  Since
this ratio is then truncated to an integer (the floor) it seems to me
that there is no sensible possibility that these two numbers
diverge. Moreover, modern toolkits report one number as scale factor
and we need a common interface here. For those reasons I'm arbitrarily
picking the horizontal scale factor as THE scale factor.
---
 src/dispextern.h |  3 +++
 src/nsterm.m     |  1 +
 src/w32term.c    | 29 +++++++++++------------------
 src/xterm.c      | 41 ++++++++++++++++++-----------------------
 4 files changed, 33 insertions(+), 41 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 0615b16..ec3c555 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2942,6 +2942,9 @@ reset_mouse_highlight (Mouse_HLInfo *hlinfo)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+  /* Return the scale factor for the screen containing frame F.  */
+  unsigned (*get_scale_factor) (struct frame *f);
+
   /* Draw a fringe bitmap in window W of row ROW using parameters P.  */
   void (*draw_fringe_bitmap) (struct window *w, struct glyph_row *row,
                               struct draw_fringe_bitmap_params *p);
diff --git a/src/nsterm.m b/src/nsterm.m
index 5583c61..8dddf1e 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5087,6 +5087,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
   gui_clear_window_mouse_face,
   gui_get_glyph_overhangs,
   gui_fix_overlapping_area,
+  0, /* get_scale_factor */
   ns_draw_fringe_bitmap,
   0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
   0, /* destroy_fringe_bitmap */
diff --git a/src/w32term.c b/src/w32term.c
index 9da0845..c898f17 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -304,20 +304,16 @@ w32_restore_glyph_string_clip (struct glyph_string *s)
     }
 }
 
-static void
-w32_get_scale_factor(struct w32_display_info *dpyinfo, int *scale_x, int *scale_y)
+static unsigned
+w32_get_scale_factor(struct frame *f)
 {
+  struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   const int base_res = 96;
 
-  *scale_x = *scale_y = 1;
-
-  if (dpyinfo)
-    {
-      if (dpyinfo->resx > base_res)
-	*scale_x = floor (dpyinfo->resx / base_res);
-      if (dpyinfo->resy > base_res)
-	*scale_y = floor (dpyinfo->resy / base_res);
-    }
+  if (dpyinfo && dpyinfo->resx > base_res)
+    return floor (dpyinfo->resx / base_res);
+  else
+    return 1;
 }
 
 /*
@@ -334,12 +330,8 @@ w32_get_scale_factor(struct w32_display_info *dpyinfo, int *scale_x, int *scale_
 static void
 w32_draw_underwave (struct glyph_string *s, COLORREF color)
 {
-  struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
-
-  int scale_x, scale_y;
-  w32_get_scale_factor (dpyinfo, &scale_x, &scale_y);
-
-  int wave_height = 3 * scale_y, wave_length = 2 * scale_x, thickness = scale_y;
+  int scale = w32_get_scale_factor (s->f);
+  int wave_height = 3 * scale, wave_length = 2 * scale, thickness = scale;
   int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
   Emacs_Rectangle wave_clip, string_clip, final_clip;
   RECT w32_final_clip, w32_string_clip;
@@ -348,7 +340,7 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color)
   dx = wave_length;
   dy = wave_height - 1;
   x0 = s->x;
-  y0 = s->ybase + wave_height / 2 - scale_y;
+  y0 = s->ybase + wave_height / 2 - scale;
   width = s->width;
   xmax = x0 + width;
 
@@ -7192,6 +7184,7 @@ w32_make_rdb (char *xrm_option)
   gui_clear_window_mouse_face,
   gui_get_glyph_overhangs,
   gui_fix_overlapping_area,
+  w32_get_scale_factor,
   w32_draw_fringe_bitmap,
   w32_define_fringe_bitmap,
   w32_destroy_fringe_bitmap,
diff --git a/src/xterm.c b/src/xterm.c
index 5d8b148..6000860 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -3611,21 +3611,21 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
   s->background_filled_p = true;
 }
 
-static void
-x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
+static unsigned
+x_get_scale_factor(struct frame *f)
 {
+#ifdef USE_GTK
+  return xg_get_scale (f);
+#else
+  Display *disp = FRAME_X_DISPLAY (f);
+  struct x_display_info *dpyinfo = x_display_info_for_display (disp);
   const int base_res = 96;
-  struct x_display_info * dpyinfo = x_display_info_for_display (disp);
-
-  *scale_x = *scale_y = 1;
 
-  if (dpyinfo)
-    {
-      if (dpyinfo->resx > base_res)
-	*scale_x = floor (dpyinfo->resx / base_res);
-      if (dpyinfo->resy > base_res)
-	*scale_y = floor (dpyinfo->resy / base_res);
-    }
+  if (dpyinfo && dpyinfo->resx > base_res)
+    return floor (dpyinfo->resx / base_res);
+  else
+    return 1;
+#endif /* USE_GTK */
 }
 
 /*
@@ -3641,27 +3641,21 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
 static void
 x_draw_underwave (struct glyph_string *s)
 {
-  Display *display = FRAME_X_DISPLAY (s->f);
-
   /* Adjust for scale/HiDPI.  */
-  int scale_x, scale_y;
-
-  x_get_scale_factor (display, &scale_x, &scale_y);
-
-  int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
-
+  int scale = x_get_scale_factor (s->f);
+  int wave_height = 3 * scale, wave_length = 2 * scale;
 #ifdef USE_CAIRO
   x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
 			  s->width, wave_height, wave_length);
 #else  /* not USE_CAIRO */
-  int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
+  int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale;
   bool odd;
   XRectangle wave_clip, string_clip, final_clip;
 
   dx = wave_length;
   dy = wave_height - 1;
   x0 = s->x;
-  y0 = s->ybase + wave_height / 2 - scale_y;
+  y0 = s->ybase + wave_height / 2 - scale;
   width = s->width;
   xmax = x0 + width;
 
@@ -10557,7 +10551,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
 {
   int modified_top, modified_left;
 #ifdef USE_GTK
-  int scale = xg_get_scale (f);
+  int scale = x_get_scale_factor (f);
 #endif
 
   if (change_gravity > 0)
@@ -13356,6 +13350,7 @@ x_activate_timeout_atimer (void)
     gui_clear_window_mouse_face,
     gui_get_glyph_overhangs,
     gui_fix_overlapping_area,
+    x_get_scale_factor,
     x_draw_fringe_bitmap,
 #ifdef USE_CAIRO
     x_cr_define_fringe_bitmap,
-- 
2.20.1