From 1d87cb3cfa08086be96f78ab09d99f3e7ba8ca60 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 27 May 2015 17:56:16 +0300 Subject: [PATCH] Avoid very high screen lines with some fonts * src/xdisp.c (get_phys_cursor_geometry): Adjust the height of the cursor to avoid weird-looking hollow cursor with fonts that have large ascent values for some glyphs. This avoids having the hollow cursor start too low. (append_space_for_newline): Adjust the ascent value of the newline glyph, so that the hollow cursor at end of line displays correctly. (FONT_TOO_HIGH): New macro. (x_produce_glyphs): Use it to detect fonts that claim a preposterously large height, in which case we use per-glyph ascent and descent values. (Bug#20628) --- src/xdisp.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index 87f110e667d..a1b7cf1438f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2150,7 +2150,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row, struct glyph *glyph, int *xp, int *yp, int *heightp) { struct frame *f = XFRAME (WINDOW_FRAME (w)); - int x, y, wd, h, h0, y0; + int x, y, wd, h, h0, y0, ascent; /* Compute the width of the rectangle to draw. If on a stretch glyph, and `x-stretch-block-cursor' is nil, don't draw a @@ -2170,13 +2170,21 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row, wd = min (FRAME_COLUMN_WIDTH (f), wd); w->phys_cursor_width = wd; - y = w->phys_cursor.y + row->ascent - glyph->ascent; + /* Don't let the hollow cursor glyph descend below the glyph row's + ascent value, lest the hollow cursor looks funny. */ + y = w->phys_cursor.y; + ascent = row->ascent; + if (row->ascent < glyph->ascent) + { + y =- glyph->ascent - row->ascent; + ascent = glyph->ascent; + } /* If y is below window bottom, ensure that we still see a cursor. */ h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height); - h = max (h0, glyph->ascent + glyph->descent); - h0 = min (h0, glyph->ascent + glyph->descent); + h = max (h0, ascent + glyph->descent); + h0 = min (h0, ascent + glyph->descent); y0 = WINDOW_HEADER_LINE_HEIGHT (w); if (y < y0) @@ -19171,6 +19179,7 @@ append_space_for_newline (struct it *it, bool default_face_p) struct text_pos saved_pos; Lisp_Object saved_object; struct face *face; + struct glyph *g; saved_object = it->object; saved_pos = it->position; @@ -19202,6 +19211,11 @@ append_space_for_newline (struct it *it, bool default_face_p) PRODUCE_GLYPHS (it); + /* Make sure this space glyph has the right ascent value, or + else hollow cursor at end of line will look funny. */ + g = it->glyph_row->glyphs[TEXT_AREA] + n; + g->ascent = it->glyph_row->ascent; + it->override_ascent = -1; it->constrain_row_ascent_descent_p = false; it->current_x = saved_x; @@ -25282,6 +25296,12 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, } \ } +/* A heuristic test for fonts that claim they need a preposterously + large vertical space. The heuristics is in the factor of 3. We + ignore the ascent and descent values reported by such fonts, and + instead go by the values reported for individual glyphs. */ +#define FONT_TOO_HIGH(ft) ((ft)->ascent + (ft)->descent > 3*(ft)->pixel_size) + /* Store one glyph for IT->char_to_display in IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ @@ -26398,6 +26418,22 @@ x_produce_glyphs (struct it *it) it->phys_ascent = pcm->ascent + boff; it->phys_descent = pcm->descent - boff; it->pixel_width = pcm->width; + /* Don't use font-global values for ascent and descent + if they result in an exceedingly large line height. */ + if (it->override_ascent < 0) + { + if (FONT_TOO_HIGH (font)) + { + it->ascent = it->phys_ascent; + it->descent = it->phys_descent; + /* These limitations are enforced by an + assertion near the end of this function. */ + if (it->ascent < 0) + it->ascent = 0; + if (it->descent < 0) + it->descent = 0; + } + } } else { @@ -26525,8 +26561,18 @@ x_produce_glyphs (struct it *it) } else { - it->ascent = FONT_BASE (font) + boff; - it->descent = FONT_DESCENT (font) - boff; + if (FONT_TOO_HIGH (font)) + { + it->ascent = font->pixel_size + boff - 1; + it->descent = -boff + 1; + if (it->descent < 0) + it->descent = 0; + } + else + { + it->ascent = FONT_BASE (font) + boff; + it->descent = FONT_DESCENT (font) - boff; + } } if (EQ (height, Qt)) @@ -26597,8 +26643,38 @@ x_produce_glyphs (struct it *it) it->pixel_width = next_tab_x - x; it->nglyphs = 1; - it->ascent = it->phys_ascent = FONT_BASE (font) + boff; - it->descent = it->phys_descent = FONT_DESCENT (font) - boff; + if (FONT_TOO_HIGH (font)) + { + if (get_char_glyph_code (' ', font, &char2b)) + { + pcm = get_per_char_metric (font, &char2b); + if (pcm->width == 0 + && pcm->rbearing == 0 && pcm->lbearing == 0) + pcm = NULL; + } + + if (pcm) + { + it->ascent = pcm->ascent + boff; + it->descent = pcm->descent - boff; + } + else + { + it->ascent = font->pixel_size + boff - 1; + it->descent = -boff + 1; + } + if (it->ascent < 0) + it->ascent = 0; + if (it->descent < 0) + it->descent = 0; + } + else + { + it->ascent = FONT_BASE (font) + boff; + it->descent = FONT_DESCENT (font) - boff; + } + it->phys_ascent = it->ascent; + it->phys_descent = it->descent; if (it->glyph_row) { -- 2.39.2