From 8e1ae12c37d373007daabcba51b78163a88e55f4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Mar 2017 17:49:22 +0200 Subject: [PATCH] Fix display of cursor on underlined text * src/nsterm.m (ns_draw_text_decoration): * src/xterm.c (x_draw_glyph_string): * src/w32term.c (x_draw_glyph_string): Compute the position and thickness of the underline by looking for the first glyph of the run of underlined glyphs that includes the glyph string we are drawing. (Bug#25845) --- src/nsterm.m | 26 ++++++++++++++++++++++---- src/w32term.c | 36 +++++++++++++++++++++++++++++------- src/xterm.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/src/nsterm.m b/src/nsterm.m index 80261d6d763..bc89925b0ef 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3043,11 +3043,29 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, } else { - struct font *font; - unsigned long descent; + /* If we are drawing in the middle of a glyph row, find + the first glyph in the run of underlined glyphs + preceding the beginning of glyph string S. This is + because that glyph determines the underline position + and thickness for the entire run of the underlined + glyphs. */ + struct glyph *g0 = s->row->glyphs[s->area], *g; + + for (g = s->first_glyph - 1; g >= g0; g--) + { + struct face *prev_face = FACE_FROM_ID (s->f, g->face_id); + if (!(prev_face && prev_face->underline_p)) + break; + } + + /* Now use the font of the last glyph we saw that + still has the underlined_p flag set. */ + struct face *glyph_face = FACE_FROM_ID (s->f, g[1].face_id); + struct font *font = glyph_face->font; + if (font) + font_prepare_for_face (s->f, glyph_face); - font=s->font; - descent = s->y + s->height - s->ybase; + unsigned long descent = s->y + s->height - s->ybase; /* Use underline thickness of font, defaulting to 1. */ thickness = (font && font->underline_thickness > 0) diff --git a/src/w32term.c b/src/w32term.c index 28bf6fb3d9f..6a98fc721cd 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -2433,9 +2433,31 @@ x_draw_glyph_string (struct glyph_string *s) } else { + /* If we are drawing in the middle of a glyph row, + find the first glyph in the run of underlined + glyphs preceding the beginning of glyph string S. + This is because that glyph determines the + underline position and thickness for the entire + run of the underlined glyphs. */ + struct glyph *g0 = s->row->glyphs[s->area], *g; + + for (g = s->first_glyph - 1; g >= g0; g--) + { + struct face *prev_face = FACE_FROM_ID (s->f, g->face_id); + if (!(prev_face && prev_face->underline_p)) + break; + } + + /* Now use the font of the last glyph we saw that + still has the underlined_p flag set. */ + struct face *glyph_face = FACE_FROM_ID (s->f, g[1].face_id); + struct font *font = glyph_face->font; + if (font) + font_prepare_for_face (s->f, glyph_face); + /* Get the underline thickness. Default is 1 pixel. */ - if (s->font && s->font->underline_thickness > 0) - thickness = s->font->underline_thickness; + if (font && font->underline_thickness > 0) + thickness = font->underline_thickness; else thickness = 1; if (x_underline_at_descent_line) @@ -2451,10 +2473,10 @@ x_draw_glyph_string (struct glyph_string *s) ROUND (x) = floor (x + 0.5) */ if (x_use_underline_position_properties - && s->font && s->font->underline_position >= 0) - position = s->font->underline_position; - else if (s->font) - position = (s->font->descent + 1) / 2; + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = (font->descent + 1) / 2; } position = max (position, underline_minimum_offset); } @@ -2465,7 +2487,7 @@ x_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) { diff --git a/src/xterm.c b/src/xterm.c index 24d1702cec0..57e64c48887 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3636,9 +3636,31 @@ x_draw_glyph_string (struct glyph_string *s) } else { + /* If we are drawing in the middle of a glyph row, + find the first glyph in the run of underlined + glyphs preceding the beginning of glyph string S. + This is because that glyph determines the + underline position and thickness for the entire + run of the underlined glyphs. */ + struct glyph *g0 = s->row->glyphs[s->area], *g; + + for (g = s->first_glyph - 1; g >= g0; g--) + { + struct face *prev_face = FACE_FROM_ID (s->f, g->face_id); + if (!(prev_face && prev_face->underline_p)) + break; + } + + /* Now use the font of the last glyph we saw that + still has the underlined_p flag set. */ + struct face *glyph_face = FACE_FROM_ID (s->f, g[1].face_id); + struct font *font = glyph_face->font; + if (font) + font_prepare_for_face (s->f, glyph_face); + /* Get the underline thickness. Default is 1 pixel. */ - if (s->font && s->font->underline_thickness > 0) - thickness = s->font->underline_thickness; + if (font && font->underline_thickness > 0) + thickness = font->underline_thickness; else thickness = 1; if (x_underline_at_descent_line) @@ -3654,10 +3676,10 @@ x_draw_glyph_string (struct glyph_string *s) ROUND(x) = floor (x + 0.5) */ if (x_use_underline_position_properties - && s->font && s->font->underline_position >= 0) - position = s->font->underline_position; - else if (s->font) - position = (s->font->descent + 1) / 2; + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = (font->descent + 1) / 2; else position = underline_minimum_offset; } -- 2.39.5