unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#35468: [PATCH] Refactor draw_glyph_string on X and w32
@ 2019-04-28  1:29 Alex Gramiak
  2019-04-28 17:11 ` Eli Zaretskii
  2021-05-12 14:43 ` Lars Ingebrigtsen
  0 siblings, 2 replies; 26+ messages in thread
From: Alex Gramiak @ 2019-04-28  1:29 UTC (permalink / raw)
  To: 35468

[-- Attachment #1: Type: text/plain, Size: 192 bytes --]

This merges x_draw_glyph_string and w32_draw_glyph_string together to
remove duplicated code.

I wanted to do it for NS as well, but it seems just a bit too different
to make it easily work.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Refactor-draw_glyph_string-on-X-and-w32.patch --]
[-- Type: text/x-patch, Size: 48961 bytes --]

From 1cd69c3bcfb79f8df61d1cacf75effb1947d869f Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Sat, 27 Apr 2019 18:45:59 -0600
Subject: [PATCH] Refactor draw_glyph_string on X and w32

* src/dispextern.h (draw_glyph_string_interface): New interface for
system-dependent functions for draw_glyph_string.
(redisplay_interface): Add draw_glyph_string_interface.

* src/xdisp.c (gui_draw_glyph_string): New function implementing the
common behaviour of x_draw_glyph_string and w32_draw_glyph_string.

* src/w32term.c (w32_draw_glyph_string): Remove in favour of
gui_draw_glyph_string.
(w32_draw_underwave): Rename to w32_draw_underwave_1.
(w32_draw_underwave, w32_draw_underline, w32_draw_overline)
(w32_draw_strike_through, w32_reset_glyph_string_clipping): Define
extracted functions out of w32_draw_glyph_string.

* src/xterm.c (x_draw_glyph_string): Remove in favour of
gui_draw_glyph_string.
(x_draw_underwave): Rename to x_draw_underwave_1.
(x_draw_underwave, x_draw_underline, x_draw_overline)
(x_draw_strike_through, x_reset_glyph_string_clipping): Define
extracted functions out of x_draw_glyph_string.
---
 src/dispextern.h |  98 +++++++++++
 src/nsterm.m     |  14 +-
 src/w32term.c    | 414 +++++++++++------------------------------------
 src/xdisp.c      | 292 +++++++++++++++++++++++++++++++++
 src/xterm.c      | 405 ++++++++++------------------------------------
 5 files changed, 568 insertions(+), 655 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 827eed86f1..20124be817 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1389,6 +1389,98 @@ struct glyph_string
   struct glyph_string *next, *prev;
 };
 
+/* Structure holding system-dependent interface functions needed
+   for drawing glyph strings as used by `gui_draw_glyph_string'.
+
+   * If gui_draw_glyph_string is used as the RIF draw_glyph_string,
+   then all of the following must be defined with the possible
+   exception of draw_xwidget.  */
+
+struct draw_glyph_string_interface
+{
+  /* Set S->gc of glyph string S for drawing that glyph string.  */
+
+  void (*set_gc) (struct glyph_string *s);
+
+  /* Set clipping for output of glyph string S.  */
+
+  void (*set_clipping) (struct glyph_string *s);
+
+  /* Set SRC's clipping for output of glyph string DST.  This is
+     called when we are drawing DST's left_overhang or right_overhang
+     only in the area of SRC.  */
+
+  void (*set_clipping_exactly) (struct glyph_string *src,
+                                struct glyph_string *dst);
+
+  /* Reset clipping for output of glyph string S.  */
+
+  void (*reset_clipping) (struct glyph_string *s);
+
+  /* Draw the background of glyph_string S.  If S->background_filled_p
+   is non-zero don't draw it.  FORCE_P non-zero means draw the
+   background even if it wouldn't be drawn normally.  This is used
+   when a string preceding S draws into the background of S, or S
+   contains the first component of a composition.  */
+
+  void (*draw_background) (struct glyph_string *s, bool force_p);
+
+  /* Draw the foreground of glyph string S.  */
+
+  void (*draw_foreground) (struct glyph_string *s);
+
+  /* Draw a box around glyph string S.  */
+
+  void (*draw_box) (struct glyph_string *s);
+
+  /* Draw image glyph string S.
+
+            s->y
+   s->x      +-------------------------
+	     |   s->face->box
+	     |
+	     |     +-------------------------
+	     |     |  s->img->margin
+	     |     |
+	     |     |       +-------------------
+	     |     |       |  the image
+
+  */
+
+  void (*draw_image) (struct glyph_string *s);
+
+  /* Draw stretch glyph string S.  */
+
+  void (*draw_stretch) (struct glyph_string *s);
+
+  /* Draw xwidget stretch glyph string S.  */
+
+  void (*draw_xwidget) (struct glyph_string *s);
+
+  /* Draw the foreground of composite glyph string S.  */
+
+  void (*draw_composite_foreground) (struct glyph_string *s);
+
+  /* Draw the foreground of glyph string S for glyphless characters.  */
+
+  void (*draw_glyphless_foreground) (struct glyph_string *s);
+
+  /* Draw underwave glyph string S.  */
+
+  void (*draw_underwave) (struct glyph_string *s);
+
+  /* Draw underline glyph string S.  */
+
+  void (*draw_underline) (struct glyph_string *s);
+
+  /* Draw overline glyph string S.  */
+
+  void (*draw_overline) (struct glyph_string *s);
+
+  /* Draw strike-through glyph string S.  */
+
+  void (*draw_strike_through) (struct glyph_string *s, int y, int height);
+};
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -2890,6 +2982,10 @@ struct redisplay_interface
   /* Draw a glyph string S.  */
   void (*draw_glyph_string) (struct glyph_string *s);
 
+  /* Interface for drawing glyph strings used by
+     gui_draw_glyph_string.  */
+  struct draw_glyph_string_interface *gsif;
+
   /* Define cursor CURSOR on frame F.  */
   void (*define_frame_cursor) (struct frame *f, Cursor cursor);
 
@@ -3288,6 +3384,8 @@ extern void gui_write_glyphs (struct window *, struct glyph_row *,
                               struct glyph *, enum glyph_row_area, int);
 extern void gui_insert_glyphs (struct window *, struct glyph_row *,
                                struct glyph *, enum glyph_row_area, int);
+extern void gui_draw_glyph_string (struct glyph_string *);
+
 extern void gui_clear_end_of_line (struct window *, struct glyph_row *,
                                    enum glyph_row_area, int);
 extern void gui_fix_overlapping_area (struct window *, struct glyph_row *,
diff --git a/src/nsterm.m b/src/nsterm.m
index 2a2b8cbaba..e7b3ab4ebf 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5107,6 +5107,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
   0, /* destroy_fringe_bitmap */
   ns_compute_glyph_string_overhangs,
   ns_draw_glyph_string,
+  NULL, /* draw_glyph_string_interface */
   ns_define_frame_cursor,
   ns_clear_frame_area,
   0, /* clear_under_internal_border */
@@ -9507,19 +9508,6 @@ Nil means use fullscreen the old (< 10.7) way.  The old way works better with
 	       doc: /* SKIP: real doc in xterm.c.  */);
   Vx_toolkit_scroll_bars = Qt;
 
-  DEFVAR_BOOL ("x-use-underline-position-properties",
-	       x_use_underline_position_properties,
-     doc: /* SKIP: real doc in xterm.c.  */);
-  x_use_underline_position_properties = 0;
-  DEFSYM (Qx_use_underline_position_properties,
-	  "x-use-underline-position-properties");
-
-  DEFVAR_BOOL ("x-underline-at-descent-line",
-	       x_underline_at_descent_line,
-     doc: /* SKIP: real doc in xterm.c.  */);
-  x_underline_at_descent_line = 0;
-  DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
-
   /* Tell Emacs about this window system.  */
   Fprovide (Qns, Qnil);
 
diff --git a/src/w32term.c b/src/w32term.c
index 8d5f57836c..947c67abb3 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -328,7 +328,7 @@ 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)
+w32_draw_underwave_1 (struct glyph_string *s, COLORREF color)
 {
   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
 
@@ -394,6 +394,71 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color)
   DeleteObject (hp);
 }
 
+static void
+w32_draw_underwave (struct glyph_string *s)
+{
+  COLORREF color;
+
+  if (s->face->underline_defaulted_p)
+    color = s->gc->foreground;
+  else
+    color = s->face->underline_color;
+
+  w32_draw_underwave_1 (s, color);
+}
+
+static void
+w32_draw_underline (struct glyph_string *s)
+{
+  const int y = s->ybase + s->underline_position;
+
+  if (s->face->underline_defaulted_p)
+    {
+      w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                     y, s->width, 1);
+    }
+  else
+    {
+      w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+                     y, s->width, 1);
+    }
+}
+
+static void
+w32_draw_overline (struct glyph_string *s)
+{
+  unsigned long dy = 0, h = 1;
+
+  if (s->face->overline_color_defaulted_p)
+    {
+      w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                     s->y + dy, s->width, h);
+    }
+  else
+    {
+      w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
+                     s->y + dy, s->width, h);
+    }
+}
+
+static void
+w32_draw_strike_through (struct glyph_string *s, int y, int height)
+{
+  if (!FONT_TEXTMETRIC (s->font).tmStruckOut)
+    {
+      if (s->face->strike_through_color_defaulted_p)
+        {
+          w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                         y, s->width, height);
+        }
+      else
+        {
+          w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
+                         y, s->width, height);
+        }
+    }
+}
+
 /* Draw a hollow rectangle at the specified position.  */
 static void
 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
@@ -1132,6 +1197,13 @@ w32_set_glyph_string_clipping_exactly (struct glyph_string *src,
   w32_set_clip_rectangle (dst->hdc, &r);
 }
 
+static void
+w32_reset_glyph_string_clipping (struct glyph_string *s)
+{
+  w32_set_clip_rectangle (s->hdc, NULL);
+  s->num_clips = 0;
+}
+
 /* RIF:
    Compute left and right overhang of glyph string S.  */
 
@@ -2384,308 +2456,6 @@ w32_draw_stretch_glyph_string (struct glyph_string *s)
 }
 
 
-/* Draw glyph string S.  */
-
-static void
-w32_draw_glyph_string (struct glyph_string *s)
-{
-  bool relief_drawn_p = 0;
-
-  /* If S draws into the background of its successor, draw the
-     background of the successor first so that S can draw into it.
-     This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps)
-    {
-      int width;
-      struct glyph_string *next;
-      for (width = 0, next = s->next;
-	   next && width < s->right_overhang;
-           width += next->width, next = next->next)
-        if (next->first_glyph->type != IMAGE_GLYPH)
-          {
-            w32_set_glyph_string_gc (next);
-            w32_set_glyph_string_clipping (next);
-	    if (next->first_glyph->type == STRETCH_GLYPH)
-	      w32_draw_stretch_glyph_string (next);
-	    else
-	      w32_draw_glyph_string_background (next, true);
-            next->num_clips = 0;
-          }
-    }
-
-  /* Set up S->gc, set clipping and draw S.  */
-  w32_set_glyph_string_gc (s);
-
-  /* Draw relief (if any) in advance for char/composition so that the
-     glyph string can be drawn over it.  */
-  if (!s->for_overlaps
-      && s->face->box != FACE_NO_BOX
-      && (s->first_glyph->type == CHAR_GLYPH
-	  || s->first_glyph->type == COMPOSITE_GLYPH))
-
-    {
-      w32_set_glyph_string_clipping (s);
-      w32_draw_glyph_string_background (s, true);
-      w32_draw_glyph_string_box (s);
-      w32_set_glyph_string_clipping (s);
-      relief_drawn_p = 1;
-    }
-  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask.  */
-           && !s->clip_tail
-           && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
-               || (s->next && s->next->hl != s->hl && s->right_overhang)))
-    /* We must clip just this glyph.  left_overhang part has already
-       drawn when s->prev was drawn, and right_overhang part will be
-       drawn later when s->next is drawn. */
-    w32_set_glyph_string_clipping_exactly (s, s);
-  else
-    w32_set_glyph_string_clipping (s);
-
-  switch (s->first_glyph->type)
-    {
-    case IMAGE_GLYPH:
-      w32_draw_image_glyph_string (s);
-      break;
-
-    case STRETCH_GLYPH:
-      w32_draw_stretch_glyph_string (s);
-      break;
-
-    case CHAR_GLYPH:
-      if (s->for_overlaps)
-	s->background_filled_p = true;
-      else
-        w32_draw_glyph_string_background (s, false);
-      w32_draw_glyph_string_foreground (s);
-      break;
-
-    case COMPOSITE_GLYPH:
-      if (s->for_overlaps || (s->cmp_from > 0
-			      && ! s->first_glyph->u.cmp.automatic))
-	s->background_filled_p = true;
-      else
-	w32_draw_glyph_string_background (s, true);
-      w32_draw_composite_glyph_string_foreground (s);
-      break;
-
-    case GLYPHLESS_GLYPH:
-      if (s->for_overlaps)
-	s->background_filled_p = true;
-      else
-	w32_draw_glyph_string_background (s, false);
-      w32_draw_glyphless_glyph_string_foreground (s);
-      break;
-
-    default:
-      emacs_abort ();
-    }
-
-  if (!s->for_overlaps)
-    {
-      /* Draw underline.  */
-      if (s->face->underline_p)
-        {
-          if (s->face->underline_type == FACE_UNDER_WAVE)
-            {
-              COLORREF color;
-
-              if (s->face->underline_defaulted_p)
-                color = s->gc->foreground;
-              else
-                color = s->face->underline_color;
-
-              w32_draw_underwave (s, color);
-            }
-          else if (s->face->underline_type == FACE_UNDER_LINE)
-            {
-              unsigned long thickness, position;
-              int y;
-
-              if (s->prev && s->prev->face->underline_p
-		  && s->prev->face->underline_type == FACE_UNDER_LINE)
-                {
-                  /* We use the same underline style as the previous one.  */
-                  thickness = s->prev->underline_thickness;
-                  position = s->prev->underline_position;
-                }
-              else
-                {
-		  struct font *font = font_for_underline_metrics (s);
-		  unsigned long minimum_offset;
-		  BOOL underline_at_descent_line;
-		  BOOL use_underline_position_properties;
-		  Lisp_Object val
-		    = buffer_local_value (Qunderline_minimum_offset,
-					s->w->contents);
-		  if (FIXNUMP (val))
-		    minimum_offset = XFIXNAT (val);
-		  else
-		    minimum_offset = 1;
-		  val = buffer_local_value (Qx_underline_at_descent_line,
-					    s->w->contents);
-		  underline_at_descent_line
-		    = !(NILP (val) || EQ (val, Qunbound));
-		  val
-		    = buffer_local_value (Qx_use_underline_position_properties,
-					  s->w->contents);
-		  use_underline_position_properties
-		    = !(NILP (val) || EQ (val, Qunbound));
-
-                  /* Get the underline thickness.  Default is 1 pixel.  */
-                  if (font && font->underline_thickness > 0)
-                    thickness = font->underline_thickness;
-                  else
-                    thickness = 1;
-                  if (underline_at_descent_line
-                      || !font)
-                    position = (s->height - thickness) - (s->ybase - s->y);
-                  else
-                    {
-                      /* Get the underline position.  This is the
-                         recommended vertical offset in pixels from
-                         the baseline to the top of the underline.
-                         This is a signed value according to the
-                         specs, and its default is
-
-                         ROUND ((maximum_descent) / 2), with
-                         ROUND (x) = floor (x + 0.5)  */
-
-                      if (use_underline_position_properties
-                          && font->underline_position >= 0)
-                        position = font->underline_position;
-                      else
-                        position = (font->descent + 1) / 2;
-                    }
-                  position = max (position, minimum_offset);
-                }
-              /* Check the sanity of thickness and position.  We should
-                 avoid drawing underline out of the current line area.  */
-              if (s->y + s->height <= s->ybase + position)
-                position = (s->height - 1) - (s->ybase - s->y);
-              if (s->y + s->height < s->ybase + position + thickness)
-                thickness = (s->y + s->height) - (s->ybase + position);
-              s->underline_thickness = thickness;
-              s->underline_position =  position;
-              y = s->ybase + position;
-              if (s->face->underline_defaulted_p)
-                {
-                  w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                                 y, s->width, 1);
-                }
-              else
-                {
-                  w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
-                                 y, s->width, 1);
-                }
-            }
-        }
-      /* Draw overline.  */
-      if (s->face->overline_p)
-        {
-          unsigned long dy = 0, h = 1;
-
-          if (s->face->overline_color_defaulted_p)
-            {
-              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                             s->y + dy, s->width, h);
-            }
-          else
-            {
-              w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
-                             s->y + dy, s->width, h);
-            }
-        }
-
-      /* Draw strike-through.  */
-      if (s->face->strike_through_p
-          && !FONT_TEXTMETRIC (s->font).tmStruckOut)
-        {
-	  /* Y-coordinate and height of the glyph string's first
-	     glyph.  We cannot use s->y and s->height because those
-	     could be larger if there are taller display elements
-	     (e.g., characters displayed with a larger font) in the
-	     same glyph row.  */
-	  int glyph_y = s->ybase - s->first_glyph->ascent;
-	  int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
-	  /* Strike-through width and offset from the glyph string's
-	     top edge.  */
-          unsigned long h = 1;
-          unsigned long dy = (glyph_height - h) / 2;
-
-          if (s->face->strike_through_color_defaulted_p)
-            {
-              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-			     glyph_y + dy, s->width, h);
-            }
-          else
-            {
-              w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
-                             glyph_y + dy, s->width, h);
-            }
-        }
-
-      /* Draw relief if not yet drawn.  */
-      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-        w32_draw_glyph_string_box (s);
-
-      if (s->prev)
-        {
-          struct glyph_string *prev;
-
-          for (prev = s->prev; prev; prev = prev->prev)
-            if (prev->hl != s->hl
-                && prev->x + prev->width + prev->right_overhang > s->x)
-              {
-                /* As prev was drawn while clipped to its own area, we
-                   must draw the right_overhang part using s->hl now.  */
-		enum draw_glyphs_face save = prev->hl;
-
-		prev->hl = s->hl;
-		w32_set_glyph_string_gc (prev);
-		w32_set_glyph_string_clipping_exactly (s, prev);
-		if (prev->first_glyph->type == CHAR_GLYPH)
-		  w32_draw_glyph_string_foreground (prev);
-		else
-		  w32_draw_composite_glyph_string_foreground (prev);
-                w32_set_clip_rectangle (prev->hdc, NULL);
-		prev->hl = save;
-		prev->num_clips = 0;
-	      }
-	}
-
-      if (s->next)
-	{
-	  struct glyph_string *next;
-
-	  for (next = s->next; next; next = next->next)
-	    if (next->hl != s->hl
-		&& next->x - next->left_overhang < s->x + s->width)
-	      {
-		/* As next will be drawn while clipped to its own area,
-		   we must draw the left_overhang part using s->hl now.  */
-		enum draw_glyphs_face save = next->hl;
-
-		next->hl = s->hl;
-		w32_set_glyph_string_gc (next);
-		w32_set_glyph_string_clipping_exactly (s, next);
-		if (next->first_glyph->type == CHAR_GLYPH)
-		  w32_draw_glyph_string_foreground (next);
-		else
-		  w32_draw_composite_glyph_string_foreground (next);
-                w32_set_clip_rectangle (next->hdc, NULL);
-		next->hl = save;
-		next->num_clips = 0;
-		next->clip_head = s->next;
-	      }
-	}
-    }
-
-  /* Reset clipping.  */
-  w32_set_clip_rectangle (s->hdc, NULL);
-  s->num_clips = 0;
-}
-
-
 /* Shift display to make room for inserted glyphs.   */
 
 static void
@@ -7077,6 +6847,26 @@ w32_make_rdb (char *xrm_option)
 
 extern frame_parm_handler w32_frame_parm_handlers[];
 
+static struct draw_glyph_string_interface w32_draw_glyph_string_interface =
+{
+  w32_set_glyph_string_gc,
+  w32_set_glyph_string_clipping,
+  w32_set_glyph_string_clipping_exactly,
+  w32_reset_glyph_string_clipping,
+  w32_draw_glyph_string_background,
+  w32_draw_glyph_string_foreground,
+  w32_draw_glyph_string_box,
+  w32_draw_image_glyph_string,
+  w32_draw_stretch_glyph_string,
+  NULL, /* draw_xwidget_glyph_string  */
+  w32_draw_composite_glyph_string_foreground,
+  w32_draw_glyphless_glyph_string_foreground,
+  w32_draw_underwave,
+  w32_draw_underline,
+  w32_draw_overline,
+  w32_draw_strike_through
+};
+
 static struct redisplay_interface w32_redisplay_interface =
 {
   w32_frame_parm_handlers,
@@ -7096,7 +6886,8 @@ static struct redisplay_interface w32_redisplay_interface =
   w32_define_fringe_bitmap,
   w32_destroy_fringe_bitmap,
   w32_compute_glyph_string_overhangs,
-  w32_draw_glyph_string,
+  gui_draw_glyph_string,
+  &w32_draw_glyph_string_interface,
   w32_define_frame_cursor,
   w32_clear_frame_area,
   w32_clear_under_internal_border,
@@ -7471,21 +7262,6 @@ the cursor have no effect.  */);
 
   w32_use_visible_system_caret = 0;
 
-  /* We don't yet support this, but defining this here avoids whining
-     from cus-start.el and other places, like "M-x set-variable".  */
-  DEFVAR_BOOL ("x-use-underline-position-properties",
-	       x_use_underline_position_properties,
-     doc: /* SKIP: real doc in xterm.c.  */);
-  x_use_underline_position_properties = 0;
-  DEFSYM (Qx_use_underline_position_properties,
-	  "x-use-underline-position-properties");
-
-  DEFVAR_BOOL ("x-underline-at-descent-line",
-	       x_underline_at_descent_line,
-     doc: /* SKIP: real doc in xterm.c.  */);
-  x_underline_at_descent_line = 0;
-  DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
-
   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
 	       doc: /* SKIP: real doc in xterm.c.  */);
   Vx_toolkit_scroll_bars = Qt;
diff --git a/src/xdisp.c b/src/xdisp.c
index a3dddfa8a5..2f5aaf6aff 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -29099,6 +29099,269 @@ gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
   unblock_input ();
 }
 
+/* EXPORT for RIF:
+   Draw glyph string S.  */
+
+void
+gui_draw_glyph_string (struct glyph_string *s)
+{
+  bool relief_drawn_p = false;
+  struct draw_glyph_string_interface *gsif = FRAME_RIF (s->f)->gsif;
+
+  if (!gsif)
+    emacs_abort ();
+
+  /* If S draws into the background of its successors, draw the
+     background of the successors first so that S can draw into it.  */
+  if (s->next && s->right_overhang && !s->for_overlaps)
+    {
+      int width;
+      struct glyph_string *next;
+
+      for (width = 0, next = s->next;
+	   next && width < s->right_overhang;
+	   width += next->width, next = next->next)
+	if (next->first_glyph->type != IMAGE_GLYPH)
+	  {
+	    gsif->set_gc (next);
+	    gsif->set_clipping (next);
+	    if (next->first_glyph->type == STRETCH_GLYPH)
+	      gsif->draw_stretch (next);
+	    else
+	      gsif->draw_background (next, true);
+	    next->num_clips = 0;
+	  }
+    }
+
+  /* Set up S->gc, set clipping and draw S.  */
+  gsif->set_gc (s);
+
+  /* Draw relief (if any) in advance for char/composition so that the
+     glyph string can be drawn over it.  */
+  if (!s->for_overlaps
+      && s->face->box != FACE_NO_BOX
+      && (s->first_glyph->type == CHAR_GLYPH
+	  || s->first_glyph->type == COMPOSITE_GLYPH))
+
+    {
+      gsif->set_clipping (s);
+      gsif->draw_background (s, true);
+      gsif->draw_box (s);
+      gsif->set_clipping (s);
+      relief_drawn_p = true;
+    }
+  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
+	   && !s->clip_tail
+	   && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+	       || (s->next && s->next->hl != s->hl && s->right_overhang)))
+    /* We must clip just this glyph.  left_overhang part has already
+       drawn when s->prev was drawn, and right_overhang part will be
+       drawn later when s->next is drawn. */
+    gsif->set_clipping_exactly (s, s);
+  else
+    gsif->set_clipping (s);
+
+  switch (s->first_glyph->type)
+    {
+    case IMAGE_GLYPH:
+      gsif->draw_image (s);
+      break;
+
+    case STRETCH_GLYPH:
+      gsif->draw_stretch (s);
+      break;
+
+    case CHAR_GLYPH:
+      if (s->for_overlaps)
+	s->background_filled_p = true;
+      else
+	gsif->draw_background (s, false);
+      gsif->draw_foreground (s);
+      break;
+
+    case COMPOSITE_GLYPH:
+      if (s->for_overlaps || (s->cmp_from > 0
+			      && ! s->first_glyph->u.cmp.automatic))
+	s->background_filled_p = true;
+      else
+	gsif->draw_background (s, true);
+      gsif->draw_composite_foreground (s);
+      break;
+
+    case XWIDGET_GLYPH:
+      if (gsif->draw_xwidget)
+        gsif->draw_xwidget (s);
+      break;
+
+    case GLYPHLESS_GLYPH:
+      if (s->for_overlaps)
+	s->background_filled_p = true;
+      else
+	gsif->draw_background (s, true);
+      gsif->draw_glyphless_foreground (s);
+      break;
+
+    default:
+      emacs_abort ();
+    }
+
+  if (!s->for_overlaps)
+    {
+      /* Draw underline.  */
+      if (s->face->underline_p)
+        {
+          if (s->face->underline_type == FACE_UNDER_WAVE)
+            gsif->draw_underwave (s);
+          else if (s->face->underline_type == FACE_UNDER_LINE)
+            {
+              unsigned long thickness, position;
+
+              if (s->prev && s->prev->face->underline_p
+		  && s->prev->face->underline_type == FACE_UNDER_LINE)
+                {
+                  /* We use the same underline style as the previous one.  */
+                  thickness = s->prev->underline_thickness;
+                  position = s->prev->underline_position;
+                }
+              else
+                {
+		  struct font *font = font_for_underline_metrics (s);
+		  unsigned long minimum_offset;
+		  bool underline_at_descent_line;
+		  bool use_underline_position_properties;
+		  Lisp_Object val
+		    = buffer_local_value (Qunderline_minimum_offset,
+					  s->w->contents);
+		  if (FIXNUMP (val))
+		    minimum_offset = XFIXNAT (val);
+		  else
+		    minimum_offset = 1;
+		  val = buffer_local_value (Qx_underline_at_descent_line,
+					    s->w->contents);
+		  underline_at_descent_line
+		    = !(NILP (val) || EQ (val, Qunbound));
+		  val
+		    = buffer_local_value (Qx_use_underline_position_properties,
+					  s->w->contents);
+		  use_underline_position_properties
+		    = !(NILP (val) || EQ (val, Qunbound));
+
+                  /* Get the underline thickness.  Default is 1 pixel.  */
+                  if (font && font->underline_thickness > 0)
+                    thickness = font->underline_thickness;
+                  else
+                    thickness = 1;
+                  if (underline_at_descent_line)
+                    position = (s->height - thickness) - (s->ybase - s->y);
+                  else
+                    {
+                      /* Get the underline position.  This is the
+                         recommended vertical offset in pixels from
+                         the baseline to the top of the underline.
+                         This is a signed value according to the
+                         specs, and its default is
+
+                         ROUND ((maximum descent) / 2), with
+                         ROUND(x) = floor (x + 0.5)  */
+
+                      if (use_underline_position_properties
+                          && font && font->underline_position >= 0)
+                        position = font->underline_position;
+                      else if (font)
+                        position = (font->descent + 1) / 2;
+                      else
+                        position = minimum_offset;
+                    }
+                  position = max (position, minimum_offset);
+                }
+              /* Check the sanity of thickness and position.  We should
+                 avoid drawing underline out of the current line area.  */
+              if (s->y + s->height <= s->ybase + position)
+                position = (s->height - 1) - (s->ybase - s->y);
+              if (s->y + s->height < s->ybase + position + thickness)
+                thickness = (s->y + s->height) - (s->ybase + position);
+              s->underline_thickness = thickness;
+              s->underline_position = position;
+              gsif->draw_underline (s);
+            }
+        }
+      /* Draw overline.  */
+      if (s->face->overline_p)
+        gsif->draw_overline (s);
+
+      /* Draw strike-through.  */
+      if (s->face->strike_through_p)
+        {
+          /* Y-coordinate and height of the glyph string's first
+	     glyph.  We cannot use s->y and s->height because those
+	     could be larger if there are taller display elements
+	     (e.g., characters displayed with a larger font) in the
+	     same glyph row.  */
+	  int glyph_y = s->ybase - s->first_glyph->ascent;
+	  int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
+	  /* Strike-through width and offset from the glyph string's
+	     top edge.  */
+          unsigned long dy = (glyph_height - 1) / 2;
+          gsif->draw_strike_through (s, glyph_y + dy, 1);
+        }
+
+      /* Draw relief if not yet drawn.  */
+      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
+	gsif->draw_box (s);
+
+      if (s->prev)
+	{
+	  struct glyph_string *prev;
+
+	  for (prev = s->prev; prev; prev = prev->prev)
+	    if (prev->hl != s->hl
+		&& prev->x + prev->width + prev->right_overhang > s->x)
+	      {
+		/* As prev was drawn while clipped to its own area, we
+		   must draw the right_overhang part using s->hl now.  */
+		enum draw_glyphs_face save = prev->hl;
+
+		prev->hl = s->hl;
+		gsif->set_gc (prev);
+		gsif->set_clipping_exactly (s, prev);
+		if (prev->first_glyph->type == CHAR_GLYPH)
+		  gsif->draw_foreground (prev);
+		else
+		  gsif->draw_composite_foreground (prev);
+		gsif->reset_clipping (prev);
+		prev->hl = save;
+	      }
+	}
+
+      if (s->next)
+	{
+	  struct glyph_string *next;
+
+	  for (next = s->next; next; next = next->next)
+	    if (next->hl != s->hl
+		&& next->x - next->left_overhang < s->x + s->width)
+	      {
+		/* As next will be drawn while clipped to its own area,
+		   we must draw the left_overhang part using s->hl now.  */
+		enum draw_glyphs_face save = next->hl;
+
+		next->hl = s->hl;
+		gsif->set_gc (next);
+		gsif->set_clipping_exactly (s, next);
+		if (next->first_glyph->type == CHAR_GLYPH)
+		  gsif->draw_foreground (next);
+		else
+		  gsif->draw_composite_foreground (next);
+		gsif->reset_clipping (next);
+		next->hl = save;
+		next->clip_head = s->next;
+	      }
+	}
+    }
+
+  /* Reset clipping.  */
+  gsif->reset_clipping (s);
+}
 
 /* EXPORT for RIF:
    Erase the current text line from the nominal cursor position
@@ -33344,6 +33607,35 @@ baseline.  The default value is 1.  */);
   underline_minimum_offset = 1;
   DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
 
+#ifdef HAVE_WINDOW_SYSTEM
+  DEFVAR_BOOL ("x-use-underline-position-properties",
+	       x_use_underline_position_properties,
+     doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
+A value of nil means ignore them.  If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, set this to nil.  You can also use
+`underline-minimum-offset' to override the font's UNDERLINE_POSITION for
+small font display sizes.  */);
+# ifdef HAVE_X_WINDOWS
+  x_use_underline_position_properties = true;
+# else
+  /* Other terms don't support this (yet?).  */
+  x_use_underline_position_properties = false;
+# endif
+  DEFSYM (Qx_use_underline_position_properties,
+	  "x-use-underline-position-properties");
+
+  DEFVAR_BOOL ("x-underline-at-descent-line",
+	       x_underline_at_descent_line,
+     doc: /* Non-nil means to draw the underline at the same place as the descent line.
+(If `line-spacing' is in effect, that moves the underline lower by
+that many pixels.)
+A value of nil means to draw the underline according to the value of the
+variable `x-use-underline-position-properties', which is usually at the
+baseline level.  The default value is nil.  */);
+  x_underline_at_descent_line = false;
+  DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
+#endif
+
   DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
 	       doc: /* Non-nil means show an hourglass pointer, when Emacs is busy.
 This feature only works when on a window system that can change
diff --git a/src/xterm.c b/src/xterm.c
index b08f5f6a62..5fe4491f7e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1626,6 +1626,12 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_stri
   x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
 }
 
+static void
+x_reset_glyph_string_clipping (struct glyph_string *s)
+{
+  x_reset_clip_rectangles (s->f, s->gc);
+  s->num_clips = 0;
+}
 
 /* RIF:
    Compute left and right overhang of glyph string S.  */
@@ -3468,7 +3474,7 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y)
 
 */
 static void
-x_draw_underwave (struct glyph_string *s)
+x_draw_underwave_1 (struct glyph_string *s)
 {
   /* Adjust for scale/HiDPI.  */
   int scale_x, scale_y;
@@ -3535,319 +3541,73 @@ x_draw_underwave (struct glyph_string *s)
 #endif	/* not USE_CAIRO */
 }
 
-
-/* Draw glyph string S.  */
-
 static void
-x_draw_glyph_string (struct glyph_string *s)
+x_draw_underwave (struct glyph_string *s)
 {
-  bool relief_drawn_p = false;
-
-  /* If S draws into the background of its successors, draw the
-     background of the successors first so that S can draw into it.
-     This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps)
+  if (s->face->underline_defaulted_p)
+    x_draw_underwave_1 (s);
+  else
     {
-      int width;
-      struct glyph_string *next;
-
-      for (width = 0, next = s->next;
-	   next && width < s->right_overhang;
-	   width += next->width, next = next->next)
-	if (next->first_glyph->type != IMAGE_GLYPH)
-	  {
-	    x_set_glyph_string_gc (next);
-	    x_set_glyph_string_clipping (next);
-	    if (next->first_glyph->type == STRETCH_GLYPH)
-	      x_draw_stretch_glyph_string (next);
-	    else
-	      x_draw_glyph_string_background (next, true);
-	    next->num_clips = 0;
-	  }
+      XGCValues xgcv;
+      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+      XSetForeground (s->display, s->gc, s->face->underline_color);
+      x_draw_underwave_1 (s);
+      XSetForeground (s->display, s->gc, xgcv.foreground);
     }
+}
 
-  /* Set up S->gc, set clipping and draw S.  */
-  x_set_glyph_string_gc (s);
-
-  /* Draw relief (if any) in advance for char/composition so that the
-     glyph string can be drawn over it.  */
-  if (!s->for_overlaps
-      && s->face->box != FACE_NO_BOX
-      && (s->first_glyph->type == CHAR_GLYPH
-	  || s->first_glyph->type == COMPOSITE_GLYPH))
+static void
+x_draw_underline (struct glyph_string *s)
+{
+  const int y = s->ybase + s->underline_position;
+  const int thickness = s->underline_thickness;
 
-    {
-      x_set_glyph_string_clipping (s);
-      x_draw_glyph_string_background (s, true);
-      x_draw_glyph_string_box (s);
-      x_set_glyph_string_clipping (s);
-      relief_drawn_p = true;
-    }
-  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
-	   && !s->clip_tail
-	   && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
-	       || (s->next && s->next->hl != s->hl && s->right_overhang)))
-    /* We must clip just this glyph.  left_overhang part has already
-       drawn when s->prev was drawn, and right_overhang part will be
-       drawn later when s->next is drawn. */
-    x_set_glyph_string_clipping_exactly (s, s);
+  if (s->face->underline_defaulted_p)
+    x_fill_rectangle (s->f, s->gc,
+                      s->x, y, s->width, thickness);
   else
-    x_set_glyph_string_clipping (s);
-
-  switch (s->first_glyph->type)
     {
-    case IMAGE_GLYPH:
-      x_draw_image_glyph_string (s);
-      break;
-
-    case XWIDGET_GLYPH:
-      x_draw_xwidget_glyph_string (s);
-      break;
-
-    case STRETCH_GLYPH:
-      x_draw_stretch_glyph_string (s);
-      break;
-
-    case CHAR_GLYPH:
-      if (s->for_overlaps)
-	s->background_filled_p = true;
-      else
-	x_draw_glyph_string_background (s, false);
-      x_draw_glyph_string_foreground (s);
-      break;
-
-    case COMPOSITE_GLYPH:
-      if (s->for_overlaps || (s->cmp_from > 0
-			      && ! s->first_glyph->u.cmp.automatic))
-	s->background_filled_p = true;
-      else
-	x_draw_glyph_string_background (s, true);
-      x_draw_composite_glyph_string_foreground (s);
-      break;
+      XGCValues xgcv;
+      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+      XSetForeground (s->display, s->gc, s->face->underline_color);
+      x_fill_rectangle (s->f, s->gc,
+                        s->x, y, s->width, thickness);
+      XSetForeground (s->display, s->gc, xgcv.foreground);
+    }
+}
 
-    case GLYPHLESS_GLYPH:
-      if (s->for_overlaps)
-	s->background_filled_p = true;
-      else
-	x_draw_glyph_string_background (s, true);
-      x_draw_glyphless_glyph_string_foreground (s);
-      break;
+static void
+x_draw_overline (struct glyph_string *s)
+{
+  unsigned long dy = 0, h = 1;
 
-    default:
-      emacs_abort ();
+  if (s->face->overline_color_defaulted_p)
+    x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                      s->width, h);
+  else
+    {
+      XGCValues xgcv;
+      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+      XSetForeground (s->display, s->gc, s->face->overline_color);
+      x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
+                        s->width, h);
+      XSetForeground (s->display, s->gc, xgcv.foreground);
     }
+}
 
-  if (!s->for_overlaps)
+static void
+x_draw_strike_through (struct glyph_string *s, int y, int height)
+{
+  if (s->face->strike_through_color_defaulted_p)
+    x_fill_rectangle (s->f, s->gc, s->x, y, s->width, height);
+  else
     {
-      /* Draw underline.  */
-      if (s->face->underline_p)
-        {
-          if (s->face->underline_type == FACE_UNDER_WAVE)
-            {
-              if (s->face->underline_defaulted_p)
-                x_draw_underwave (s);
-              else
-                {
-                  XGCValues xgcv;
-                  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-                  XSetForeground (s->display, s->gc, s->face->underline_color);
-                  x_draw_underwave (s);
-                  XSetForeground (s->display, s->gc, xgcv.foreground);
-                }
-            }
-          else if (s->face->underline_type == FACE_UNDER_LINE)
-            {
-              unsigned long thickness, position;
-              int y;
-
-              if (s->prev && s->prev->face->underline_p
-		  && s->prev->face->underline_type == FACE_UNDER_LINE)
-                {
-                  /* We use the same underline style as the previous one.  */
-                  thickness = s->prev->underline_thickness;
-                  position = s->prev->underline_position;
-                }
-              else
-                {
-		  struct font *font = font_for_underline_metrics (s);
-		  unsigned long minimum_offset;
-		  bool underline_at_descent_line;
-		  bool use_underline_position_properties;
-		  Lisp_Object val
-		    = buffer_local_value (Qunderline_minimum_offset,
-					  s->w->contents);
-		  if (FIXNUMP (val))
-		    minimum_offset = XFIXNAT (val);
-		  else
-		    minimum_offset = 1;
-		  val = buffer_local_value (Qx_underline_at_descent_line,
-					    s->w->contents);
-		  underline_at_descent_line
-		    = !(NILP (val) || EQ (val, Qunbound));
-		  val
-		    = buffer_local_value (Qx_use_underline_position_properties,
-					  s->w->contents);
-		  use_underline_position_properties
-		    = !(NILP (val) || EQ (val, Qunbound));
-
-                  /* Get the underline thickness.  Default is 1 pixel.  */
-                  if (font && font->underline_thickness > 0)
-                    thickness = font->underline_thickness;
-                  else
-                    thickness = 1;
-                  if (underline_at_descent_line)
-                    position = (s->height - thickness) - (s->ybase - s->y);
-                  else
-                    {
-                      /* Get the underline position.  This is the
-                         recommended vertical offset in pixels from
-                         the baseline to the top of the underline.
-                         This is a signed value according to the
-                         specs, and its default is
-
-                         ROUND ((maximum descent) / 2), with
-                         ROUND(x) = floor (x + 0.5)  */
-
-                      if (use_underline_position_properties
-                          && font && font->underline_position >= 0)
-                        position = font->underline_position;
-                      else if (font)
-                        position = (font->descent + 1) / 2;
-                      else
-                        position = minimum_offset;
-                    }
-                  position = max (position, minimum_offset);
-                }
-              /* Check the sanity of thickness and position.  We should
-                 avoid drawing underline out of the current line area.  */
-              if (s->y + s->height <= s->ybase + position)
-                position = (s->height - 1) - (s->ybase - s->y);
-              if (s->y + s->height < s->ybase + position + thickness)
-                thickness = (s->y + s->height) - (s->ybase + position);
-              s->underline_thickness = thickness;
-              s->underline_position = position;
-              y = s->ybase + position;
-              if (s->face->underline_defaulted_p)
-                x_fill_rectangle (s->f, s->gc,
-                                s->x, y, s->width, thickness);
-              else
-                {
-                  XGCValues xgcv;
-                  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-                  XSetForeground (s->display, s->gc, s->face->underline_color);
-                  x_fill_rectangle (s->f, s->gc,
-                                  s->x, y, s->width, thickness);
-                  XSetForeground (s->display, s->gc, xgcv.foreground);
-                }
-            }
-        }
-      /* Draw overline.  */
-      if (s->face->overline_p)
-	{
-	  unsigned long dy = 0, h = 1;
-
-	  if (s->face->overline_color_defaulted_p)
-	    x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-			    s->width, h);
-	  else
-	    {
-	      XGCValues xgcv;
-	      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-	      XSetForeground (s->display, s->gc, s->face->overline_color);
-	      x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
-			      s->width, h);
-	      XSetForeground (s->display, s->gc, xgcv.foreground);
-	    }
-	}
-
-      /* Draw strike-through.  */
-      if (s->face->strike_through_p)
-	{
-	  /* Y-coordinate and height of the glyph string's first
-	     glyph.  We cannot use s->y and s->height because those
-	     could be larger if there are taller display elements
-	     (e.g., characters displayed with a larger font) in the
-	     same glyph row.  */
-	  int glyph_y = s->ybase - s->first_glyph->ascent;
-	  int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
-	  /* Strike-through width and offset from the glyph string's
-	     top edge.  */
-          unsigned long h = 1;
-          unsigned long dy = (glyph_height - h) / 2;
-
-	  if (s->face->strike_through_color_defaulted_p)
-	    x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
-			    s->width, h);
-	  else
-	    {
-	      XGCValues xgcv;
-	      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-	      XSetForeground (s->display, s->gc, s->face->strike_through_color);
-	      x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy,
-			      s->width, h);
-	      XSetForeground (s->display, s->gc, xgcv.foreground);
-	    }
-	}
-
-      /* Draw relief if not yet drawn.  */
-      if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
-	x_draw_glyph_string_box (s);
-
-      if (s->prev)
-	{
-	  struct glyph_string *prev;
-
-	  for (prev = s->prev; prev; prev = prev->prev)
-	    if (prev->hl != s->hl
-		&& prev->x + prev->width + prev->right_overhang > s->x)
-	      {
-		/* As prev was drawn while clipped to its own area, we
-		   must draw the right_overhang part using s->hl now.  */
-		enum draw_glyphs_face save = prev->hl;
-
-		prev->hl = s->hl;
-		x_set_glyph_string_gc (prev);
-		x_set_glyph_string_clipping_exactly (s, prev);
-		if (prev->first_glyph->type == CHAR_GLYPH)
-		  x_draw_glyph_string_foreground (prev);
-		else
-		  x_draw_composite_glyph_string_foreground (prev);
-		x_reset_clip_rectangles (prev->f, prev->gc);
-		prev->hl = save;
-		prev->num_clips = 0;
-	      }
-	}
-
-      if (s->next)
-	{
-	  struct glyph_string *next;
-
-	  for (next = s->next; next; next = next->next)
-	    if (next->hl != s->hl
-		&& next->x - next->left_overhang < s->x + s->width)
-	      {
-		/* As next will be drawn while clipped to its own area,
-		   we must draw the left_overhang part using s->hl now.  */
-		enum draw_glyphs_face save = next->hl;
-
-		next->hl = s->hl;
-		x_set_glyph_string_gc (next);
-		x_set_glyph_string_clipping_exactly (s, next);
-		if (next->first_glyph->type == CHAR_GLYPH)
-		  x_draw_glyph_string_foreground (next);
-		else
-		  x_draw_composite_glyph_string_foreground (next);
-		x_reset_clip_rectangles (next->f, next->gc);
-		next->hl = save;
-		next->num_clips = 0;
-		next->clip_head = s->next;
-	      }
-	}
+      XGCValues xgcv;
+      XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+      XSetForeground (s->display, s->gc, s->face->strike_through_color);
+      x_fill_rectangle (s->f, s->gc, s->x, y, s->width, height);
+      XSetForeground (s->display, s->gc, xgcv.foreground);
     }
-
-  /* Reset clipping.  */
-  x_reset_clip_rectangles (s->f, s->gc);
-  s->num_clips = 0;
 }
 
 /* Shift display to make room for inserted glyphs.   */
@@ -13060,6 +12820,26 @@ x_activate_timeout_atimer (void)
 
 extern frame_parm_handler x_frame_parm_handlers[];
 
+static struct draw_glyph_string_interface x_draw_glyph_string_interface =
+  {
+   x_set_glyph_string_gc,
+   x_set_glyph_string_clipping,
+   x_set_glyph_string_clipping_exactly,
+   x_reset_glyph_string_clipping,
+   x_draw_glyph_string_background,
+   x_draw_glyph_string_foreground,
+   x_draw_glyph_string_box,
+   x_draw_image_glyph_string,
+   x_draw_stretch_glyph_string,
+   x_draw_xwidget_glyph_string,
+   x_draw_composite_glyph_string_foreground,
+   x_draw_glyphless_glyph_string_foreground,
+   x_draw_underwave,
+   x_draw_underline,
+   x_draw_overline,
+   x_draw_strike_through
+  };
+
 static struct redisplay_interface x_redisplay_interface =
   {
     x_frame_parm_handlers,
@@ -13084,7 +12864,8 @@ static struct redisplay_interface x_redisplay_interface =
     0, /* destroy_fringe_bitmap */
 #endif
     x_compute_glyph_string_overhangs,
-    x_draw_glyph_string,
+    gui_draw_glyph_string,
+    &x_draw_glyph_string_interface,
     x_define_frame_cursor,
     x_clear_frame_area,
     x_clear_under_internal_border,
@@ -13327,28 +13108,6 @@ syms_of_xterm (void)
   DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
 #endif
 
-  DEFVAR_BOOL ("x-use-underline-position-properties",
-	       x_use_underline_position_properties,
-     doc: /* Non-nil means make use of UNDERLINE_POSITION font properties.
-A value of nil means ignore them.  If you encounter fonts with bogus
-UNDERLINE_POSITION font properties, set this to nil.  You can also use
-`underline-minimum-offset' to override the font's UNDERLINE_POSITION for
-small font display sizes.  */);
-  x_use_underline_position_properties = true;
-  DEFSYM (Qx_use_underline_position_properties,
-	  "x-use-underline-position-properties");
-
-  DEFVAR_BOOL ("x-underline-at-descent-line",
-	       x_underline_at_descent_line,
-     doc: /* Non-nil means to draw the underline at the same place as the descent line.
-(If `line-spacing' is in effect, that moves the underline lower by
-that many pixels.)
-A value of nil means to draw the underline according to the value of the
-variable `x-use-underline-position-properties', which is usually at the
-baseline level.  The default value is nil.  */);
-  x_underline_at_descent_line = false;
-  DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
-
   DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
 	       x_mouse_click_focus_ignore_position,
     doc: /* Non-nil means that a mouse click to focus a frame does not move point.
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2021-07-22 12:55 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-04-28  1:29 bug#35468: [PATCH] Refactor draw_glyph_string on X and w32 Alex Gramiak
2019-04-28 17:11 ` Eli Zaretskii
2019-04-28 19:46   ` Alex Gramiak
2019-04-29 17:43     ` Alex Gramiak
2019-04-30  4:59       ` Eli Zaretskii
2019-04-30 18:00         ` Alex Gramiak
2019-05-01  0:14           ` mituharu
2019-05-03 19:01             ` Alex Gramiak
2019-05-03 21:33               ` mituharu
2019-05-04  4:00                 ` mituharu
2019-05-01 18:19           ` Eli Zaretskii
2019-05-02 19:41             ` Alex Gramiak
2019-05-02 20:14               ` Eli Zaretskii
2019-05-03 15:26                 ` Basil L. Contovounesios
2019-05-04  8:17               ` Eli Zaretskii
2019-05-04 19:29                 ` Alex Gramiak
2019-05-05  0:10                   ` mituharu
2019-05-05 16:00                     ` Eli Zaretskii
2019-05-05  2:34                   ` Eli Zaretskii
2019-04-30 20:11         ` Alan Third
2019-05-01 17:38           ` Eli Zaretskii
2019-05-01 21:08             ` Alan Third
2019-05-02 18:14               ` Alex Gramiak
2019-05-03 21:12                 ` Alan Third
2021-05-12 14:43 ` Lars Ingebrigtsen
2021-07-22 12:55   ` Lars Ingebrigtsen

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).