aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu1970-01-01 00:00:00 +0000
committerPo Lu2024-04-28 11:58:54 +0800
commite844b81c56d74aa2b2efa0ce98ed3de71647e656 (patch)
tree0dd2259e464b4c8bc0c80efbdad27dfa6abfd915 /src
parent77a170a175dfeb17dab23e41668b8497b8b3b9d7 (diff)
downloademacs-e844b81c56d74aa2b2efa0ce98ed3de71647e656.tar.gz
emacs-e844b81c56d74aa2b2efa0ce98ed3de71647e656.zip
Implement dots and dashes on X
* src/dispextern.h (enum face_underline_type): Indent and expand commentary as to the new dependency on the order of its enumerals. * src/xfaces.c (realize_gui_face): Enable dots and dashes on window systems. * src/xterm.c (x_draw_underwave): Don't define unused variable on Cairo builds. (x_draw_dash): New function; implement for X and Cairo. (x_fill_underline): New function. Delegate to x_fill_rectangle or x_draw_dash as appropriate. (x_draw_glyph_string): Call x_fill_underline rather than x_fill_rectangle.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h4
-rw-r--r--src/xfaces.c2
-rw-r--r--src/xterm.c125
3 files changed, 108 insertions, 23 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 1614a044cbf..93cbde6583d 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1697,7 +1697,9 @@ enum face_box_type
1697 1697
1698enum face_underline_type 1698enum face_underline_type
1699{ 1699{
1700 /* Note: Order matches the order of the Smulx terminfo extension. */ 1700 /* Note: order matches the order of the Smulx terminfo extension, and
1701 is also relied on to remain in its present order by
1702 x_draw_glyph_string and company. */
1701 FACE_NO_UNDERLINE = 0, 1703 FACE_NO_UNDERLINE = 0,
1702 FACE_UNDERLINE_SINGLE, 1704 FACE_UNDERLINE_SINGLE,
1703 FACE_UNDERLINE_DOUBLE_LINE, 1705 FACE_UNDERLINE_DOUBLE_LINE,
diff --git a/src/xfaces.c b/src/xfaces.c
index d9ee82c8e7f..56d067ade5b 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6404,12 +6404,10 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6404 face->underline = FACE_UNDERLINE_DOUBLE_LINE; 6404 face->underline = FACE_UNDERLINE_DOUBLE_LINE;
6405 else if (EQ (value, Qwave)) 6405 else if (EQ (value, Qwave))
6406 face->underline = FACE_UNDERLINE_WAVE; 6406 face->underline = FACE_UNDERLINE_WAVE;
6407#if 0
6408 else if (EQ (value, Qdots)) 6407 else if (EQ (value, Qdots))
6409 face->underline = FACE_UNDERLINE_DOTS; 6408 face->underline = FACE_UNDERLINE_DOTS;
6410 else if (EQ (value, Qdashes)) 6409 else if (EQ (value, Qdashes))
6411 face->underline = FACE_UNDERLINE_DASHES; 6410 face->underline = FACE_UNDERLINE_DASHES;
6412#endif /* 0 */
6413 else 6411 else
6414 face->underline = FACE_UNDERLINE_SINGLE; 6412 face->underline = FACE_UNDERLINE_SINGLE;
6415 } 6413 }
diff --git a/src/xterm.c b/src/xterm.c
index 9b014a7d0e4..505a3d9360a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -10764,13 +10764,11 @@ x_get_scale_factor (struct x_display_info *dpyinfo,
10764static void 10764static void
10765x_draw_underwave (struct glyph_string *s, int decoration_width) 10765x_draw_underwave (struct glyph_string *s, int decoration_width)
10766{ 10766{
10767 Display *display;
10768 struct x_display_info *dpyinfo; 10767 struct x_display_info *dpyinfo;
10769 /* Adjust for scale/HiDPI. */ 10768 /* Adjust for scale/HiDPI. */
10770 int scale_x, scale_y; 10769 int scale_x, scale_y;
10771 10770
10772 dpyinfo = FRAME_DISPLAY_INFO (s->f); 10771 dpyinfo = FRAME_DISPLAY_INFO (s->f);
10773 display = dpyinfo->display;
10774 x_get_scale_factor (dpyinfo, &scale_x, &scale_y); 10772 x_get_scale_factor (dpyinfo, &scale_x, &scale_y);
10775 10773
10776 int wave_height = 3 * scale_y, wave_length = 2 * scale_x; 10774 int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
@@ -10779,6 +10777,7 @@ x_draw_underwave (struct glyph_string *s, int decoration_width)
10779 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3, 10777 x_draw_horizontal_wave (s->f, s->gc, s->x, s->ybase - wave_height + 3,
10780 decoration_width, wave_height, wave_length); 10778 decoration_width, wave_height, wave_length);
10781#else /* not USE_CAIRO */ 10779#else /* not USE_CAIRO */
10780 Display *display;
10782 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;; 10781 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;;
10783 bool odd; 10782 bool odd;
10784 XRectangle wave_clip, string_clip, final_clip; 10783 XRectangle wave_clip, string_clip, final_clip;
@@ -10801,6 +10800,7 @@ x_draw_underwave (struct glyph_string *s, int decoration_width)
10801 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) 10800 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
10802 return; 10801 return;
10803 10802
10803 display = dpyinfo->display;
10804 XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted); 10804 XSetClipRectangles (display, s->gc, 0, 0, &final_clip, 1, Unsorted);
10805 10805
10806 /* Draw the waves */ 10806 /* Draw the waves */
@@ -10833,6 +10833,98 @@ x_draw_underwave (struct glyph_string *s, int decoration_width)
10833#endif /* not USE_CAIRO */ 10833#endif /* not USE_CAIRO */
10834} 10834}
10835 10835
10836/* Draw a dashed underline of thickness THICKNESS and width WIDTH onto F
10837 at a vertical offset of OFFSET from the position of the glyph string
10838 S, with each segment SEGMENT pixels in length. */
10839
10840static void
10841x_draw_dash (struct frame *f, struct glyph_string *s, int width,
10842 char segment, int offset, int thickness)
10843{
10844#ifndef USE_CAIRO
10845 GC gc;
10846 Display *display;
10847 XGCValues gcv;
10848 int y_center;
10849
10850 /* Configure the GC, the dash pattern and a suitable offset. */
10851 gc = s->gc;
10852 display = FRAME_X_DISPLAY (f);
10853
10854 XGetGCValues (display, s->gc, GCLineStyle, &gcv);
10855 gcv.line_style = LineOnOffDash;
10856 gcv.line_width = thickness;
10857 XChangeGC (display, s->gc, GCLineStyle | GCLineWidth, &gcv);
10858 XSetDashes (display, s->gc, s->x, &segment, 1);
10859
10860 /* Offset the origin of the line by half the line width. */
10861 y_center = s->ybase + offset + thickness / 2;
10862 XDrawLine (display, FRAME_X_DRAWABLE (f), gc,
10863 s->x, y_center, s->x + width, y_center);
10864
10865 /* Restore the initial line style. */
10866 gcv.line_style = LineSolid;
10867 gcv.line_width = 1;
10868 XChangeGC (display, s->gc, GCLineStyle | GCLineWidth, &gcv);
10869#else /* USE_CAIRO */
10870 cairo_t *cr;
10871 double cr_segment, y_center;
10872
10873 cr = x_begin_cr_clip (f, s->gc);
10874 cr_segment = (double) segment;
10875 y_center = s->ybase + offset + (thickness / 2.0);
10876
10877 x_set_cr_source_with_gc_foreground (f, s->gc, false);
10878 cairo_set_dash (cr, &cr_segment, 1, s->x);
10879 cairo_set_line_width (cr, thickness);
10880 cairo_move_to (cr, s->x, y_center);
10881 cairo_line_to (cr, s->x + width, y_center);
10882 cairo_stroke (cr);
10883 x_end_cr_clip (f);
10884#endif /* USE_CAIRO */
10885}
10886
10887/* Draw an underline of STYLE onto F at an offset of POSITION from the
10888 baseline of the glyph string S, DECORATION_WIDTH in length, and
10889 THICKNESS in height. */
10890
10891static void
10892x_fill_underline (struct frame *f, struct glyph_string *s,
10893 enum face_underline_type style, int position,
10894 int decoration_width, int thickness)
10895{
10896 int segment;
10897 char x_segment;
10898
10899 segment = thickness * 3;
10900
10901 switch (style)
10902 {
10903 /* FACE_UNDERLINE_DOUBLE_LINE is treated identically to SINGLE, as
10904 the second line will be filled by another invocation of this
10905 function. */
10906 case FACE_UNDERLINE_SINGLE:
10907 case FACE_UNDERLINE_DOUBLE_LINE:
10908 x_fill_rectangle (f, s->gc, s->x, s->ybase + position,
10909 decoration_width, thickness, false);
10910 break;
10911
10912 case FACE_UNDERLINE_DOTS:
10913 segment = thickness;
10914 FALLTHROUGH;
10915
10916 case FACE_UNDERLINE_DASHES:
10917 x_segment = min (segment, CHAR_MAX);
10918 x_draw_dash (f, s, decoration_width, x_segment, position,
10919 thickness);
10920 break;
10921
10922 case FACE_NO_UNDERLINE:
10923 case FACE_UNDERLINE_WAVE:
10924 default:
10925 emacs_abort ();
10926 }
10927}
10836 10928
10837/* Draw glyph string S. */ 10929/* Draw glyph string S. */
10838 10930
@@ -10973,16 +11065,13 @@ x_draw_glyph_string (struct glyph_string *s)
10973 XSetForeground (display, s->gc, xgcv.foreground); 11065 XSetForeground (display, s->gc, xgcv.foreground);
10974 } 11066 }
10975 } 11067 }
10976 else if (s->face->underline == FACE_UNDERLINE_SINGLE 11068 else if (s->face->underline >= FACE_UNDERLINE_SINGLE)
10977 || s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
10978 { 11069 {
10979 unsigned long thickness, position; 11070 unsigned long thickness, position;
10980 int y;
10981 11071
10982 if (s->prev 11072 if (s->prev
10983 && ((s->prev->face->underline == FACE_UNDERLINE_SINGLE) 11073 && (s->prev->face->underline != FACE_UNDERLINE_WAVE
10984 || (s->prev->face->underline 11074 && s->prev->face->underline >= FACE_UNDERLINE_SINGLE)
10985 == FACE_UNDERLINE_DOUBLE_LINE))
10986 && (s->prev->face->underline_at_descent_line_p 11075 && (s->prev->face->underline_at_descent_line_p
10987 == s->face->underline_at_descent_line_p) 11076 == s->face->underline_at_descent_line_p)
10988 && (s->prev->face->underline_pixels_above_descent_line 11077 && (s->prev->face->underline_pixels_above_descent_line
@@ -11064,20 +11153,16 @@ x_draw_glyph_string (struct glyph_string *s)
11064 Display *display = FRAME_X_DISPLAY (s->f); 11153 Display *display = FRAME_X_DISPLAY (s->f);
11065 XGCValues xgcv; 11154 XGCValues xgcv;
11066 11155
11067 y = s->ybase + position; 11156 if (!s->face->underline_defaulted_p)
11068 if (s->face->underline_defaulted_p)
11069 x_fill_rectangle (s->f, s->gc,
11070 s->x, y, decoration_width, thickness,
11071 false);
11072 else
11073 { 11157 {
11074 XGetGCValues (display, s->gc, GCForeground, &xgcv); 11158 XGetGCValues (display, s->gc, GCForeground, &xgcv);
11075 XSetForeground (display, s->gc, s->face->underline_color); 11159 XSetForeground (display, s->gc, s->face->underline_color);
11076 x_fill_rectangle (s->f, s->gc,
11077 s->x, y, decoration_width, thickness,
11078 false);
11079 } 11160 }
11080 11161
11162 x_fill_underline (s->f, s, s->face->underline,
11163 position, decoration_width,
11164 thickness);
11165
11081 /* Place a second underline above the first if this was 11166 /* Place a second underline above the first if this was
11082 requested in the face specification. */ 11167 requested in the face specification. */
11083 11168
@@ -11085,9 +11170,9 @@ x_draw_glyph_string (struct glyph_string *s)
11085 { 11170 {
11086 /* Compute the position of the second underline. */ 11171 /* Compute the position of the second underline. */
11087 position = position - thickness - 1; 11172 position = position - thickness - 1;
11088 y = s->ybase + position; 11173 x_fill_underline (s->f, s, s->face->underline,
11089 x_fill_rectangle (s->f, s->gc, s->x, y, decoration_width, 11174 position, decoration_width,
11090 thickness, false); 11175 thickness);
11091 } 11176 }
11092 11177
11093 if (!s->face->underline_defaulted_p) 11178 if (!s->face->underline_defaulted_p)