aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-01-10 19:26:46 +0800
committerPo Lu2022-01-10 19:26:46 +0800
commit4f50d964e51bbe5219f40df4353f4314c7ade985 (patch)
tree8c68be6ee5b0b9999bb61ed7dd3553b456828b7b /src
parente36f076eb7681e32b3b0cc61c4fd33e448e3bc74 (diff)
downloademacs-4f50d964e51bbe5219f40df4353f4314c7ade985.tar.gz
emacs-4f50d964e51bbe5219f40df4353f4314c7ade985.zip
Allow controlling the underline position of faces
* doc/lispref/display.texi (Face Attributes): Document new `:position' property of the `:underline' attribute. * etc/NEWS: Announce new property. * lisp/cus-face.el (custom-face-attributes): Implement customization for new face attribute. * src/dispextern.h (struct face): New fields `underline_pixels_above_descent_line' and `underline_at_descent_line_p'. * src/haikuterm.c (haiku_draw_text_decoration): * src/nsterm.m (ns_draw_text_decoration): * src/w32term.c (w32_draw_glyph_string): * src/xterm.c (x_draw_glyph_string): Respect new face fields. * src/xfaces.c (realize_gui_face): Handle new `:position' keyword. (syms_of_xfaces): New symbol `:position'.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h9
-rw-r--r--src/haikuterm.c14
-rw-r--r--src/nsterm.m15
-rw-r--r--src/w32term.c20
-rw-r--r--src/xfaces.c16
-rw-r--r--src/xterm.c25
6 files changed, 81 insertions, 18 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 954992a0ec2..368507732ce 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1720,6 +1720,12 @@ struct face
1720 int box_vertical_line_width; 1720 int box_vertical_line_width;
1721 int box_horizontal_line_width; 1721 int box_horizontal_line_width;
1722 1722
1723
1724 /* The amount of pixels above the descent line the underline should
1725 be displayed. It does not take effect unless
1726 `underline_at_descent_line_p` is t. */
1727 int underline_pixels_above_descent_line;
1728
1723 /* Type of box drawn. A value of FACE_NO_BOX means no box is drawn 1729 /* Type of box drawn. A value of FACE_NO_BOX means no box is drawn
1724 around text in this face. A value of FACE_SIMPLE_BOX means a box 1730 around text in this face. A value of FACE_SIMPLE_BOX means a box
1725 of width box_line_width is drawn in color box_color. A value of 1731 of width box_line_width is drawn in color box_color. A value of
@@ -1753,6 +1759,9 @@ struct face
1753 bool_bf strike_through_color_defaulted_p : 1; 1759 bool_bf strike_through_color_defaulted_p : 1;
1754 bool_bf box_color_defaulted_p : 1; 1760 bool_bf box_color_defaulted_p : 1;
1755 1761
1762 /* True means the underline should be drawn at the descent line. */
1763 bool_bf underline_at_descent_line_p : 1;
1764
1756 /* TTY appearances. Colors are found in `lface' with empty color 1765 /* TTY appearances. Colors are found in `lface' with empty color
1757 string meaning the default color of the TTY. */ 1766 string meaning the default color of the TTY. */
1758 bool_bf tty_bold_p : 1; 1767 bool_bf tty_bold_p : 1;
diff --git a/src/haikuterm.c b/src/haikuterm.c
index b6d105bf2b6..2304f718c31 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -613,7 +613,12 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
613 unsigned long thickness, position; 613 unsigned long thickness, position;
614 int y; 614 int y;
615 615
616 if (s->prev && s->prev && s->prev->hl == DRAW_MOUSE_FACE) 616 if (s->prev
617 && s->prev->face->underline == FACE_UNDER_LINE
618 && (s->prev->face->underline_at_descent_line_p
619 == s->face->underline_at_descent_line_p)
620 && (s->prev->face->underline_pixels_above_descent_line
621 == s->face->underline_pixels_above_descent_line))
617 { 622 {
618 struct face *prev_face = s->prev->face; 623 struct face *prev_face = s->prev->face;
619 624
@@ -644,7 +649,8 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
644 val = (WINDOW_BUFFER_LOCAL_VALUE 649 val = (WINDOW_BUFFER_LOCAL_VALUE
645 (Qx_underline_at_descent_line, s->w)); 650 (Qx_underline_at_descent_line, s->w));
646 underline_at_descent_line 651 underline_at_descent_line
647 = !(NILP (val) || EQ (val, Qunbound)); 652 = (!(NILP (val) || EQ (val, Qunbound))
653 || s->face->underline_at_descent_line_p);
648 654
649 val = (WINDOW_BUFFER_LOCAL_VALUE 655 val = (WINDOW_BUFFER_LOCAL_VALUE
650 (Qx_use_underline_position_properties, s->w)); 656 (Qx_use_underline_position_properties, s->w));
@@ -657,7 +663,9 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face,
657 else 663 else
658 thickness = 1; 664 thickness = 1;
659 if (underline_at_descent_line) 665 if (underline_at_descent_line)
660 position = (s->height - thickness) - (s->ybase - s->y); 666 position = ((s->height - thickness)
667 - (s->ybase - s->y)
668 - s->face->underline_pixels_above_descent_line);
661 else 669 else
662 { 670 {
663 /* Get the underline position. This is the 671 /* Get the underline position. This is the
diff --git a/src/nsterm.m b/src/nsterm.m
index a15dc47a226..4f60cc737da 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3265,7 +3265,11 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
3265 /* If the prev was underlined, match its appearance. */ 3265 /* If the prev was underlined, match its appearance. */
3266 if (s->prev 3266 if (s->prev
3267 && s->prev->face->underline == FACE_UNDER_LINE 3267 && s->prev->face->underline == FACE_UNDER_LINE
3268 && s->prev->underline_thickness > 0) 3268 && s->prev->underline_thickness > 0
3269 && (s->prev->face->underline_at_descent_line_p
3270 == s->face->underline_at_descent_line_p)
3271 && (s->prev->face->underline_pixels_above_descent_line
3272 == s->face->underline_pixels_above_descent_line))
3269 { 3273 {
3270 thickness = s->prev->underline_thickness; 3274 thickness = s->prev->underline_thickness;
3271 position = s->prev->underline_position; 3275 position = s->prev->underline_position;
@@ -3286,7 +3290,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
3286 3290
3287 val = (WINDOW_BUFFER_LOCAL_VALUE 3291 val = (WINDOW_BUFFER_LOCAL_VALUE
3288 (Qx_underline_at_descent_line, s->w)); 3292 (Qx_underline_at_descent_line, s->w));
3289 underline_at_descent_line = !(NILP (val) || EQ (val, Qunbound)); 3293 underline_at_descent_line = (!(NILP (val) || EQ (val, Qunbound))
3294 || s->face->underline_at_descent_line_p);
3290 3295
3291 val = (WINDOW_BUFFER_LOCAL_VALUE 3296 val = (WINDOW_BUFFER_LOCAL_VALUE
3292 (Qx_use_underline_position_properties, s->w)); 3297 (Qx_use_underline_position_properties, s->w));
@@ -3299,7 +3304,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
3299 3304
3300 /* Determine the offset of underlining from the baseline. */ 3305 /* Determine the offset of underlining from the baseline. */
3301 if (underline_at_descent_line) 3306 if (underline_at_descent_line)
3302 position = descent - thickness; 3307 position = (descent - thickness
3308 - s->face->underline_pixels_above_descent_line);
3303 else if (use_underline_position_properties 3309 else if (use_underline_position_properties
3304 && font && font->underline_position >= 0) 3310 && font && font->underline_position >= 0)
3305 position = font->underline_position; 3311 position = font->underline_position;
@@ -3308,7 +3314,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
3308 else 3314 else
3309 position = minimum_offset; 3315 position = minimum_offset;
3310 3316
3311 position = max (position, minimum_offset); 3317 if (!s->face->underline_pixels_above_descent_line)
3318 position = max (position, minimum_offset);
3312 3319
3313 /* Ensure underlining is not cropped. */ 3320 /* Ensure underlining is not cropped. */
3314 if (descent <= position) 3321 if (descent <= position)
diff --git a/src/w32term.c b/src/w32term.c
index 700c492cc37..78777f153c0 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -2564,7 +2564,11 @@ w32_draw_glyph_string (struct glyph_string *s)
2564 int y; 2564 int y;
2565 2565
2566 if (s->prev 2566 if (s->prev
2567 && s->prev->face->underline == FACE_UNDER_LINE) 2567 && s->prev->face->underline == FACE_UNDER_LINE
2568 && (s->prev->face->underline_at_descent_line_p
2569 == s->face->underline_at_descent_line_p)
2570 && (s->prev->face->underline_pixels_above_descent_line
2571 == s->face->underline_pixels_above_descent_line))
2568 { 2572 {
2569 /* We use the same underline style as the previous one. */ 2573 /* We use the same underline style as the previous one. */
2570 thickness = s->prev->underline_thickness; 2574 thickness = s->prev->underline_thickness;
@@ -2587,7 +2591,8 @@ w32_draw_glyph_string (struct glyph_string *s)
2587 val = (WINDOW_BUFFER_LOCAL_VALUE 2591 val = (WINDOW_BUFFER_LOCAL_VALUE
2588 (Qx_underline_at_descent_line, s->w)); 2592 (Qx_underline_at_descent_line, s->w));
2589 underline_at_descent_line 2593 underline_at_descent_line
2590 = !(NILP (val) || EQ (val, Qunbound)); 2594 = (!(NILP (val) || EQ (val, Qunbound))
2595 || s->face->underline_at_descent_line_p);
2591 2596
2592 val = (WINDOW_BUFFER_LOCAL_VALUE 2597 val = (WINDOW_BUFFER_LOCAL_VALUE
2593 (Qx_use_underline_position_properties, s->w)); 2598 (Qx_use_underline_position_properties, s->w));
@@ -2601,7 +2606,9 @@ w32_draw_glyph_string (struct glyph_string *s)
2601 thickness = 1; 2606 thickness = 1;
2602 if (underline_at_descent_line 2607 if (underline_at_descent_line
2603 || !font) 2608 || !font)
2604 position = (s->height - thickness) - (s->ybase - s->y); 2609 position = ((s->height - thickness)
2610 - (s->ybase - s->y)
2611 - s->face->underline_pixels_above_descent_line);
2605 else 2612 else
2606 { 2613 {
2607 /* Get the underline position. This is the 2614 /* Get the underline position. This is the
@@ -2619,7 +2626,12 @@ w32_draw_glyph_string (struct glyph_string *s)
2619 else 2626 else
2620 position = (font->descent + 1) / 2; 2627 position = (font->descent + 1) / 2;
2621 } 2628 }
2622 position = max (position, minimum_offset); 2629
2630 if (!(s->face->underline_at_descent_line_p
2631 /* Ignore minimum_offset if the amount of pixels
2632 was explictly specified. */
2633 && s->face->underline_pixels_above_descent_line))
2634 position = max (position, minimum_offset);
2623 } 2635 }
2624 /* Check the sanity of thickness and position. We should 2636 /* Check the sanity of thickness and position. We should
2625 avoid drawing underline out of the current line area. */ 2637 avoid drawing underline out of the current line area. */
diff --git a/src/xfaces.c b/src/xfaces.c
index 3fd31b7f225..8064d47c947 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6041,6 +6041,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6041 face->underline = FACE_UNDER_LINE; 6041 face->underline = FACE_UNDER_LINE;
6042 face->underline_defaulted_p = true; 6042 face->underline_defaulted_p = true;
6043 face->underline_color = 0; 6043 face->underline_color = 0;
6044 face->underline_at_descent_line_p = false;
6045 face->underline_pixels_above_descent_line = 0;
6044 } 6046 }
6045 else if (STRINGP (underline)) 6047 else if (STRINGP (underline))
6046 { 6048 {
@@ -6050,12 +6052,16 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6050 face->underline_color 6052 face->underline_color
6051 = load_color (f, face, underline, 6053 = load_color (f, face, underline,
6052 LFACE_UNDERLINE_INDEX); 6054 LFACE_UNDERLINE_INDEX);
6055 face->underline_at_descent_line_p = false;
6056 face->underline_pixels_above_descent_line = 0;
6053 } 6057 }
6054 else if (NILP (underline)) 6058 else if (NILP (underline))
6055 { 6059 {
6056 face->underline = FACE_NO_UNDERLINE; 6060 face->underline = FACE_NO_UNDERLINE;
6057 face->underline_defaulted_p = false; 6061 face->underline_defaulted_p = false;
6058 face->underline_color = 0; 6062 face->underline_color = 0;
6063 face->underline_at_descent_line_p = false;
6064 face->underline_pixels_above_descent_line = 0;
6059 } 6065 }
6060 else if (CONSP (underline)) 6066 else if (CONSP (underline))
6061 { 6067 {
@@ -6064,6 +6070,8 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6064 face->underline = FACE_UNDER_LINE; 6070 face->underline = FACE_UNDER_LINE;
6065 face->underline_color = 0; 6071 face->underline_color = 0;
6066 face->underline_defaulted_p = true; 6072 face->underline_defaulted_p = true;
6073 face->underline_at_descent_line_p = false;
6074 face->underline_pixels_above_descent_line = 0;
6067 6075
6068 /* FIXME? This is also not robust about checking the precise form. 6076 /* FIXME? This is also not robust about checking the precise form.
6069 See comments in Finternal_set_lisp_face_attribute. */ 6077 See comments in Finternal_set_lisp_face_attribute. */
@@ -6100,6 +6108,13 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6100 else if (EQ (value, Qwave)) 6108 else if (EQ (value, Qwave))
6101 face->underline = FACE_UNDER_WAVE; 6109 face->underline = FACE_UNDER_WAVE;
6102 } 6110 }
6111 else if (EQ (keyword, QCposition))
6112 {
6113 face->underline_at_descent_line_p = !NILP (value);
6114
6115 if (FIXNATP (value))
6116 face->underline_pixels_above_descent_line = XFIXNAT (value);
6117 }
6103 } 6118 }
6104 } 6119 }
6105 6120
@@ -6915,6 +6930,7 @@ syms_of_xfaces (void)
6915 DEFSYM (QCcolor, ":color"); 6930 DEFSYM (QCcolor, ":color");
6916 DEFSYM (QCline_width, ":line-width"); 6931 DEFSYM (QCline_width, ":line-width");
6917 DEFSYM (QCstyle, ":style"); 6932 DEFSYM (QCstyle, ":style");
6933 DEFSYM (QCposition, ":position");
6918 DEFSYM (Qline, "line"); 6934 DEFSYM (Qline, "line");
6919 DEFSYM (Qwave, "wave"); 6935 DEFSYM (Qwave, "wave");
6920 DEFSYM (Qreleased_button, "released-button"); 6936 DEFSYM (Qreleased_button, "released-button");
diff --git a/src/xterm.c b/src/xterm.c
index 321b4c5ab66..e2b09938a27 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4144,8 +4144,12 @@ x_draw_glyph_string (struct glyph_string *s)
4144 unsigned long thickness, position; 4144 unsigned long thickness, position;
4145 int y; 4145 int y;
4146 4146
4147 if (s->prev && 4147 if (s->prev
4148 s->prev->face->underline == FACE_UNDER_LINE) 4148 && s->prev->face->underline == FACE_UNDER_LINE
4149 && (s->prev->face->underline_at_descent_line_p
4150 == s->face->underline_at_descent_line_p)
4151 && (s->prev->face->underline_pixels_above_descent_line
4152 == s->face->underline_pixels_above_descent_line))
4149 { 4153 {
4150 /* We use the same underline style as the previous one. */ 4154 /* We use the same underline style as the previous one. */
4151 thickness = s->prev->underline_thickness; 4155 thickness = s->prev->underline_thickness;
@@ -4168,7 +4172,8 @@ x_draw_glyph_string (struct glyph_string *s)
4168 val = (WINDOW_BUFFER_LOCAL_VALUE 4172 val = (WINDOW_BUFFER_LOCAL_VALUE
4169 (Qx_underline_at_descent_line, s->w)); 4173 (Qx_underline_at_descent_line, s->w));
4170 underline_at_descent_line 4174 underline_at_descent_line
4171 = !(NILP (val) || EQ (val, Qunbound)); 4175 = (!(NILP (val) || EQ (val, Qunbound))
4176 || s->face->underline_at_descent_line_p);
4172 4177
4173 val = (WINDOW_BUFFER_LOCAL_VALUE 4178 val = (WINDOW_BUFFER_LOCAL_VALUE
4174 (Qx_use_underline_position_properties, s->w)); 4179 (Qx_use_underline_position_properties, s->w));
@@ -4181,7 +4186,9 @@ x_draw_glyph_string (struct glyph_string *s)
4181 else 4186 else
4182 thickness = 1; 4187 thickness = 1;
4183 if (underline_at_descent_line) 4188 if (underline_at_descent_line)
4184 position = (s->height - thickness) - (s->ybase - s->y); 4189 position = ((s->height - thickness)
4190 - (s->ybase - s->y)
4191 - s->face->underline_pixels_above_descent_line);
4185 else 4192 else
4186 { 4193 {
4187 /* Get the underline position. This is the 4194 /* Get the underline position. This is the
@@ -4201,12 +4208,16 @@ x_draw_glyph_string (struct glyph_string *s)
4201 else 4208 else
4202 position = minimum_offset; 4209 position = minimum_offset;
4203 } 4210 }
4204 position = max (position, minimum_offset); 4211
4212 /* Ignore minimum_offset if the amount of pixels was
4213 explictly specified. */
4214 if (!s->face->underline_pixels_above_descent_line)
4215 position = max (position, minimum_offset);
4205 } 4216 }
4206 /* Check the sanity of thickness and position. We should 4217 /* Check the sanity of thickness and position. We should
4207 avoid drawing underline out of the current line area. */ 4218 avoid drawing underline out of the current line area. */
4208 if (s->y + s->height <= s->ybase + position) 4219 if (s->y + s->height <= s->ybase + position)
4209 position = (s->height - 1) - (s->ybase - s->y); 4220 position = (s->height - 1) - (s->ybase - s->y);
4210 if (s->y + s->height < s->ybase + position + thickness) 4221 if (s->y + s->height < s->ybase + position + thickness)
4211 thickness = (s->y + s->height) - (s->ybase + position); 4222 thickness = (s->y + s->height) - (s->ybase + position);
4212 s->underline_thickness = thickness; 4223 s->underline_thickness = thickness;