From eae5dcd57d1a73688ccb576decbf90fa711105e7 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 6 Mar 2017 18:22:53 +0200 Subject: [PATCH] A better fix for bug#25845 * src/xdisp.c (font_for_underline_metrics): New function. * src/dispextern.h: Add its prototype. * src/xterm.c (x_draw_glyph_string): * src/w32term.c (x_draw_glyph_string): * src/nsterm.m (ns_draw_text_decoration): Call it. This avoids having identical code 3 times in 3 different files. --- src/dispextern.h | 1 + src/nsterm.m | 23 +---------------------- src/w32term.c | 22 +--------------------- src/xdisp.c | 30 ++++++++++++++++++++++++++++++ src/xterm.c | 22 +--------------------- 5 files changed, 34 insertions(+), 64 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index e030618a9b7..679820d5063 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3293,6 +3293,7 @@ extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE; extern void x_get_glyph_overhangs (struct glyph *, struct frame *, int *, int *); +extern struct font *font_for_underline_metrics (struct glyph_string *); extern void x_produce_glyphs (struct it *); extern void x_write_glyphs (struct window *, struct glyph_row *, diff --git a/src/nsterm.m b/src/nsterm.m index bc89925b0ef..08ee0cdf6fd 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3043,28 +3043,7 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, } 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); - + struct font *font = font_for_underline_metrics (s); unsigned long descent = s->y + s->height - s->ybase; /* Use underline thickness of font, defaulting to 1. */ diff --git a/src/w32term.c b/src/w32term.c index 6a98fc721cd..81666f5bc47 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -2433,27 +2433,7 @@ 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); + struct font *font = font_for_underline_metrics (s); /* Get the underline thickness. Default is 1 pixel. */ if (font && font->underline_thickness > 0) diff --git a/src/xdisp.c b/src/xdisp.c index 82c4c775c16..1e7cb4ec665 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25948,6 +25948,36 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, return x_reached; } +/* Find the first glyph in the run of underlined glyphs preceding the + beginning of glyph string S, and return its font (which could be + NULL). This is needed because that font determines the underline + position and thickness for the entire run of the underlined glyphs. + This function is called from the draw_glyph_string method of GUI + frame's redisplay interface (RIF) when it needs to draw in an + underlined face. */ +struct font * +font_for_underline_metrics (struct glyph_string *s) +{ + 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; + } + + /* If preceding glyphs are not underlined, use the font of S. */ + if (g == s->first_glyph - 1) + return s->font; + else + { + /* Otherwise use the font of the last glyph we saw in the above + loop whose face had the underline_p flag set. */ + return FACE_FROM_ID (s->f, g[1].face_id)->font; + } +} + /* Expand row matrix if too narrow. Don't expand if area is not present. */ diff --git a/src/xterm.c b/src/xterm.c index 57e64c48887..28faea14a3a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3636,27 +3636,7 @@ 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); + struct font *font = font_for_underline_metrics (s); /* Get the underline thickness. Default is 1 pixel. */ if (font && font->underline_thickness > 0) -- 2.39.5