]> git.eshelyaron.com Git - emacs.git/commitdiff
Port double-line underlines to GUI systems
authorPo Lu <luangruo@yahoo.com>
Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)
committerEshel Yaron <me@eshelyaron.com>
Mon, 29 Apr 2024 15:05:27 +0000 (17:05 +0200)
* src/xterm.c (x_get_scale_factor): Replace display in first
argument with a pointer to dpyinfo.
(x_draw_underwave): Adjust to match.
(x_draw_glyph_string): Implement double-line underlines.

* src/androidterm.c (android_get_scale_factor)
(android_draw_glyph_string):

* src/haikuterm.c (haiku_draw_text_decoration):

* src/nsterm.m (ns_draw_text_decoration):

* src/pgtkterm.c (pgtk_draw_glyph_string):

* src/w32term.c (w32_draw_glyph_string): Synchronize with X.

* src/xfaces.c (realize_gui_face): Enable `double-line' on
window systems.

(cherry picked from commit 77a170a175dfeb17dab23e41668b8497b8b3b9d7)

src/androidterm.c
src/haikuterm.c
src/nsterm.m
src/pgtkterm.c
src/w32term.c
src/xfaces.c
src/xterm.c

index f5173168785e5cfe1011133fcdd27c45c4f210ac..9f25c507a236e68e4cdef6080ec2b474ab071122 100644 (file)
@@ -3740,19 +3740,15 @@ static void
 android_get_scale_factor (int *scale_x, int *scale_y)
 {
   /* This is 96 everywhere else, but 160 on Android.  */
-  const int base_res = 160;
-  struct android_display_info *dpyinfo;
+  int base_res = 160;
 
-  dpyinfo = x_display_list;
   *scale_x = *scale_y = 1;
+  eassert (x_display_list);
 
-  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 (x_display_list->resx > base_res)
+    *scale_x = floor (x_display_list->resx / base_res);
+  if (x_display_list->resy > base_res)
+    *scale_y = floor (x_display_list->resy / base_res);
 }
 
 static void
@@ -4171,13 +4167,16 @@ android_draw_glyph_string (struct glyph_string *s)
                   android_set_foreground (s->gc, xgcv.foreground);
                 }
             }
-          else if (s->face->underline == FACE_UNDERLINE_SINGLE)
+          else if (s->face->underline == FACE_UNDERLINE_SINGLE
+                  || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
             {
               unsigned long thickness, position;
               int y;
 
               if (s->prev
-                 && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+                 && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
+                     || (s->prev->face->underline
+                         == FACE_UNDERLINE_DOUBLE_LINE))
                  && (s->prev->face->underline_at_descent_line_p
                      == s->face->underline_at_descent_line_p)
                  && (s->prev->face->underline_pixels_above_descent_line
@@ -4254,19 +4253,38 @@ android_draw_glyph_string (struct glyph_string *s)
                 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)
-                android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
-                                       s->x, y, decoration_width, thickness);
-              else
-                {
-                  struct android_gc_values xgcv;
-                  android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
-                  android_set_foreground (s->gc, s->face->underline_color);
-                  android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
+
+             {
+               struct android_gc_values xgcv;
+
+               y = s->ybase + position;
+               if (s->face->underline_defaulted_p)
+                 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
                                          s->x, y, decoration_width, thickness);
-                  android_set_foreground (s->gc, xgcv.foreground);
-                }
+               else
+                 {
+                   android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
+                   android_set_foreground (s->gc, s->face->underline_color);
+                   android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
+                                           s->x, y, decoration_width, thickness);
+                 }
+
+               /* Place a second underline above the first if this was
+                  requested in the face specification.  */
+
+               if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
+                 {
+                   /* Compute the position of the second underline.  */
+                   position = position - thickness - 1;
+                   y        = s->ybase + position;
+                   android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
+                                           s->gc, s->x, y, decoration_width,
+                                           thickness, false);
+                 }
+
+               if (!s->face->underline_defaulted_p)
+                 android_set_foreground (s->gc, xgcv.foreground);
+             }
             }
         }
       /* Draw overline.  */
index c3971bf6fe48a7163b4a1088e7e4ed7ea4a9b050..4a03c4cb2d5a6d5003a3d9b9d322646bf01fd3ad 100644 (file)
@@ -829,13 +829,15 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
 
       if (face->underline == FACE_UNDERLINE_WAVE)
        haiku_draw_underwave (s, width, x);
-      else if (face->underline == FACE_UNDERLINE_SINGLE)
+      else if (face->underline == FACE_UNDERLINE_SINGLE
+              || face->underline == FACE_UNDERLINE_DOUBLE_LINE))
        {
          unsigned long thickness, position;
          int y;
 
          if (s->prev
-             && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+             && (s->prev->face->underline == FACE_UNDERLINE_SINGLE
+                 || s->prev->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
              && (s->prev->face->underline_at_descent_line_p
                  == s->face->underline_at_descent_line_p)
              && (s->prev->face->underline_pixels_above_descent_line
@@ -911,6 +913,17 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
          y = s->ybase + position;
 
          BView_FillRectangle (view, s->x, y, s->width, thickness);
+
+         /* Place a second underline above the first if this was
+            requested in the face specification.  */
+
+         if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
+           {
+             /* Compute the position of the second underline.  */
+             position = position - thickness - 1;
+             y        = s->ybase + position;
+             BView_FillRectangle (view, s->x, y, s->width, thickness);
+           }
        }
     }
 
index 84d94b5be74509d18f23a3181aa14115066525d8..bd4010f28448f0330ecdd52b42b658b85592ee3e 100644 (file)
@@ -3337,7 +3337,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
 
           ns_draw_underwave (s, width, x);
         }
-      else if (s->face->underline == FACE_UNDERLINE_SINGLE)
+      else if (s->face->underline == FACE_UNDERLINE_SINGLE
+              || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
         {
 
           NSRect r;
@@ -3345,7 +3346,9 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
 
           /* If the prev was underlined, match its appearance.  */
           if (s->prev
-             && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+             && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
+                 || (s->prev->face->underline
+                     == FACE_UNDERLINE_DOUBLE_LINE))
               && s->prev->underline_thickness > 0
              && (s->prev->face->underline_at_descent_line_p
                  == s->face->underline_at_descent_line_p)
@@ -3417,6 +3420,17 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
             [[NSColor colorWithUnsignedLong:face->underline_color] set];
 
           NSRectFill (r);
+
+         /* Place a second underline above the first if this was
+            requested in the face specification.  */
+
+         if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
+           {
+             /* Compute the position of the second underline.  */
+             position = position - thickness - 1;
+             r = NSMakeRect (x, s->ybase + position, width, thickness);
+             NSRectFill (r);
+           }
         }
     }
   /* Do overline. We follow other terms in using a thickness of 1
index e08e4b2b230048fd320cd20b1ea1a8e87ae16790..8441189ab8de67a47b64297d89deee218081efdd 100644 (file)
@@ -2553,13 +2553,17 @@ pgtk_draw_glyph_string (struct glyph_string *s)
              else
                pgtk_draw_underwave (s, s->face->underline_color);
            }
-         else if (s->face->underline == FACE_UNDERLINE_SINGLE)
+         else if (s->face->underline == FACE_UNDERLINE_SINGLE
+                  || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
            {
              unsigned long thickness, position;
              int y;
+             unsigned long foreground;
 
              if (s->prev
-                 && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+                 && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
+                     || (s->prev->face->underline
+                         == FACE_UNDERLINE_DOUBLE_LINE))
                  && (s->prev->face->underline_at_descent_line_p
                      == s->face->underline_at_descent_line_p)
                  && (s->prev->face->underline_pixels_above_descent_line
@@ -2616,15 +2620,25 @@ pgtk_draw_glyph_string (struct glyph_string *s)
              s->underline_thickness = thickness;
              s->underline_position = position;
              y = s->ybase + position;
+
              if (s->face->underline_defaulted_p)
-               pgtk_fill_rectangle (s->f, s->xgcv.foreground,
-                                    s->x, y, s->width, thickness,
-                                    false);
+               foreground = s->xgcv.foreground;
              else
+               foreground = s->face->underline_color;
+
+             pgtk_fill_rectangle (s->f, foreground, s->x, y, s->width,
+                                  thickness, false);
+
+             /* Place a second underline above the first if this was
+                requested in the face specification.  */
+
+             if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
                {
-                 pgtk_fill_rectangle (s->f, s->face->underline_color,
-                                      s->x, y, s->width, thickness,
-                                      false);
+                 /* Compute the position of the second underline.  */
+                 position = position - thickness - 1;
+                 y        = s->ybase + position;
+                 pgtk_fill_rectangle (s->f, foreground, s->x, y, s->width,
+                                      thickness, false);
                }
            }
        }
index 20ea346c8aaed5535d055974f298baa2f50edcd6..a0037e6e090c9bcc52d171d1011118a9e98b0ad7 100644 (file)
@@ -2652,13 +2652,16 @@ w32_draw_glyph_string (struct glyph_string *s)
 
               w32_draw_underwave (s, color);
             }
-          else if (s->face->underline == FACE_UNDERLINE_SINGLE)
+          else if (s->face->underline == FACE_UNDERLINE_SINGLE
+                  || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
             {
               unsigned long thickness, position;
               int y;
 
               if (s->prev
-                 && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+                 && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
+                     || (s->prev->face->underline
+                         == FACE_UNDERLINE_DOUBLE_LINE))
                  && (s->prev->face->underline_at_descent_line_p
                      == s->face->underline_at_descent_line_p)
                  && (s->prev->face->underline_pixels_above_descent_line
@@ -2676,6 +2679,7 @@ w32_draw_glyph_string (struct glyph_string *s)
                  BOOL use_underline_position_properties;
                  Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
                                     (Qunderline_minimum_offset, s->w));
+                 COLORREF foreground;
 
                  if (FIXNUMP (val))
                    minimum_offset = max (0, XFIXNUM (val));
@@ -2734,18 +2738,28 @@ w32_draw_glyph_string (struct glyph_string *s)
               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;
+              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);
-                }
+               foreground = s->gc->foreground;
+             else
+               foreground = s->face->underline_color;
+
+             w32_fill_area (s->f, s->hdc, foreground, s->x, y,
+                            s->width, thickness);
+
+             /* Place a second underline above the first if this was
+                requested in the face specification.  */
+
+             if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
+               {
+                 /* Compute the position of the second underline.  */
+                 position = position - thickness - 1;
+                 y        = s->ybase + position;
+                 w32_fill_area (s->f, s->hdc, foreground, s->x, y,
+                                s->width, thickness);
+               }
             }
         }
       /* Draw overline.  */
index 07e198974fa950cb846622d3cc7ab35ae56a0b1a..d9ee82c8e7f25acb6f4c18dbf1a55f20837b0f01 100644 (file)
@@ -6398,13 +6398,21 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
             }
           else if (EQ (keyword, QCstyle))
             {
-              if (EQ (value, Qline))
-                face->underline = FACE_UNDERLINE_SINGLE;
-              else if (EQ (value, Qwave))
-                face->underline = FACE_UNDERLINE_WAVE;
-              else
-                face->underline = FACE_UNDERLINE_SINGLE;
-            }
+             if (EQ (value, Qline))
+               face->underline = FACE_UNDERLINE_SINGLE;
+             else if (EQ (value, Qdouble_line))
+               face->underline = FACE_UNDERLINE_DOUBLE_LINE;
+             else if (EQ (value, Qwave))
+               face->underline = FACE_UNDERLINE_WAVE;
+#if 0
+             else if (EQ (value, Qdots))
+               face->underline = FACE_UNDERLINE_DOTS;
+             else if (EQ (value, Qdashes))
+               face->underline = FACE_UNDERLINE_DASHES;
+#endif /* 0 */
+             else
+               face->underline = FACE_UNDERLINE_SINGLE;
+           }
          else if (EQ (keyword, QCposition))
            {
              face->underline_at_descent_line_p = !NILP (value);
index 360541ac0b9c057fa2f65c7ecb47d16e756acd3c..9b014a7d0e4d1ebd3b97032432e97a8b63f6b380 100644 (file)
@@ -10735,10 +10735,10 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
 }
 
 static void
-x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
+x_get_scale_factor (struct x_display_info *dpyinfo,
+                   int *scale_x, int *scale_y)
 {
-  const int base_res = 96;
-  struct x_display_info * dpyinfo = x_display_info_for_display (disp);
+  int base_res = 96;
 
   *scale_x = *scale_y = 1;
 
@@ -10764,12 +10764,14 @@ x_get_scale_factor (Display *disp, int *scale_x, int *scale_y)
 static void
 x_draw_underwave (struct glyph_string *s, int decoration_width)
 {
-  Display *display = FRAME_X_DISPLAY (s->f);
-
+  Display *display;
+  struct x_display_info *dpyinfo;
   /* Adjust for scale/HiDPI.  */
   int scale_x, scale_y;
 
-  x_get_scale_factor (display, &scale_x, &scale_y);
+  dpyinfo = FRAME_DISPLAY_INFO (s->f);
+  display = dpyinfo->display;
+  x_get_scale_factor (dpyinfo, &scale_x, &scale_y);
 
   int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
 
@@ -10971,13 +10973,16 @@ x_draw_glyph_string (struct glyph_string *s)
                   XSetForeground (display, s->gc, xgcv.foreground);
                 }
             }
-          else if (s->face->underline == FACE_UNDERLINE_SINGLE)
+          else if (s->face->underline == FACE_UNDERLINE_SINGLE
+                  || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
             {
               unsigned long thickness, position;
               int y;
 
               if (s->prev
-                 && s->prev->face->underline == FACE_UNDERLINE_SINGLE
+                 && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
+                     || (s->prev->face->underline
+                         == FACE_UNDERLINE_DOUBLE_LINE))
                  && (s->prev->face->underline_at_descent_line_p
                      == s->face->underline_at_descent_line_p)
                  && (s->prev->face->underline_pixels_above_descent_line
@@ -11054,22 +11059,40 @@ x_draw_glyph_string (struct glyph_string *s)
                 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, decoration_width, thickness,
-                                 false);
-              else
-                {
-                  Display *display = FRAME_X_DISPLAY (s->f);
-                  XGCValues xgcv;
-                  XGetGCValues (display, s->gc, GCForeground, &xgcv);
-                  XSetForeground (display, s->gc, s->face->underline_color);
-                  x_fill_rectangle (s->f, s->gc,
+
+             {
+               Display *display = FRAME_X_DISPLAY (s->f);
+               XGCValues xgcv;
+
+               y = s->ybase + position;
+               if (s->face->underline_defaulted_p)
+                 x_fill_rectangle (s->f, s->gc,
                                    s->x, y, decoration_width, thickness,
                                    false);
-                  XSetForeground (display, s->gc, xgcv.foreground);
-                }
+               else
+                 {
+                   XGetGCValues (display, s->gc, GCForeground, &xgcv);
+                   XSetForeground (display, s->gc, s->face->underline_color);
+                   x_fill_rectangle (s->f, s->gc,
+                                     s->x, y, decoration_width, thickness,
+                                     false);
+                 }
+
+               /* Place a second underline above the first if this was
+                  requested in the face specification.  */
+
+               if (s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
+                 {
+                   /* Compute the position of the second underline.  */
+                   position = position - thickness - 1;
+                   y        = s->ybase + position;
+                   x_fill_rectangle (s->f, s->gc, s->x, y, decoration_width,
+                                     thickness, false);
+                 }
+
+               if (!s->face->underline_defaulted_p)
+                 XSetForeground (display, s->gc, xgcv.foreground);
+             }
             }
         }
       /* Draw overline.  */