diff options
author | Eli Zaretskii <eliz@gnu.org> | 2015-05-28 20:23:41 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2015-05-28 20:23:41 +0300 |
commit | c76605faa1f597e67df1e5c6cfae5230ff3a6a76 (patch) | |
tree | 8d5100ba36931d2e06b9e61b34028d9620cdbcd0 | |
parent | 1d87cb3cfa08086be96f78ab09d99f3e7ba8ca60 (diff) |
Fix display of glyphless characters with problematic fonts
* src/w32term.c (x_draw_glyph_string_background): Force redraw of
glyph string background also when the font in use claims
preposterously large global height value. Helps to remove
artifacts left from previous displays when glyphless characters
are displayed as hex code in a box.
* src/xterm.c (x_draw_glyph_string_background): Force redraw of
glyph string background also when the font in use claims
preposterously large global height value. Helps to remove
artifacts left from previous displays when glyphless characters
are displayed as hex code in a box.
* src/w32font.c (w32font_draw): Fix background drawing for
glyphless characters that display as acronyms or hex codes in a
box.
* src/xftfont.c (xftfont_draw): Fix background drawing for
glyphless characters that display as acronyms or hex codes in a
box.
* src/xdisp.c (produce_glyphless_glyph): Compute reasonable values
for it->ascent and it->descent when the font claims preposterously
large global values.
(FONT_TOO_HIGH): Move from here...
* src/dispextern.h (FONT_TOO_HIGH): ...to here.
-rw-r--r-- | src/dispextern.h | 6 | ||||
-rw-r--r-- | src/w32font.c | 25 | ||||
-rw-r--r-- | src/w32term.c | 7 | ||||
-rw-r--r-- | src/xdisp.c | 30 | ||||
-rw-r--r-- | src/xftfont.c | 22 | ||||
-rw-r--r-- | src/xterm.c | 5 |
6 files changed, 81 insertions, 14 deletions
diff --git a/src/dispextern.h b/src/dispextern.h index d9d4d2300f..1537d44330 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1526,6 +1526,12 @@ struct glyph_string + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \ - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F))) +/* 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) + /*********************************************************************** Faces diff --git a/src/w32font.c b/src/w32font.c index 6306a8460e..1c2f966503 100644 --- a/src/w32font.c +++ b/src/w32font.c @@ -650,12 +650,31 @@ w32font_draw (struct glyph_string *s, int from, int to, HBRUSH brush; RECT rect; struct font *font = s->font; - + int ascent = font->ascent, descent = font->descent; + + /* Font's global ascent and descent values might be + preposterously large for some fonts. We fix here the case + when those fonts are used for display of glyphless + characters, because drawing background with font dimensions + in those cases makes the display illegible. There's only one + more call to the draw method with with_background set to + true, and that's in x_draw_glyph_string_foreground, when + drawing the cursor, where we have no such heuristics + available. FIXME. */ + if (s->first_glyph->type == GLYPHLESS_GLYPH + && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE + || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)) + { + ascent = + s->first_glyph->slice.glyphless.lower_yoff + - s->first_glyph->slice.glyphless.upper_yoff; + descent = 0; + } brush = CreateSolidBrush (s->gc->background); rect.left = x; - rect.top = y - font->ascent; + rect.top = y - ascent; rect.right = x + s->width; - rect.bottom = y + font->descent; + rect.bottom = y + descent; FillRect (s->hdc, &rect, brush); DeleteObject (brush); } diff --git a/src/w32term.c b/src/w32term.c index 0bc2e98021..9c4f28fa2d 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1218,7 +1218,12 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) } else #endif - if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width + if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width + /* When xdisp.c ignores FONT_HEIGHT, we cannot trust + font dimensions, since the actual glyphs might be + much smaller. So in that case we always clear the + rectangle with background color. */ + || FONT_TOO_HIGH (s->font) || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) diff --git a/src/xdisp.c b/src/xdisp.c index a1b7cf1438..ed430a424a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25296,12 +25296,6 @@ 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. */ @@ -26230,8 +26224,28 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym) ASCII face. */ face = FACE_FROM_ID (it->f, it->face_id)->ascii_face; font = face->font ? face->font : FRAME_FONT (it->f); - it->ascent = FONT_BASE (font) + font->baseline_offset; - it->descent = FONT_DESCENT (font) - font->baseline_offset; + it->ascent = FONT_BASE (font); + it->descent = FONT_DESCENT (font); + /* Attempt to fix box height for fonts that claim preposterously + large height. */ + if (FONT_TOO_HIGH (font)) + { + XChar2b char2b; + + /* Get metrics of a reasonably sized ASCII character. */ + if (get_char_glyph_code ('{', font, &char2b)) + { + struct font_metrics *pcm = get_per_char_metric (font, &char2b); + + if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0)) + { + it->ascent = pcm->ascent; + it->descent = pcm->descent; + } + } + } + it->ascent += font->baseline_offset; + it->descent -= font->baseline_offset; base_height = it->ascent + it->descent; base_width = font->average_width; diff --git a/src/xftfont.c b/src/xftfont.c index 0e8b876f1d..a1846e8d46 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -617,8 +617,26 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, XftDrawSetClip (xft_draw, NULL); if (with_background) - XftDrawRect (xft_draw, &bg, - x, y - s->font->ascent, s->width, s->font->height); + { + int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font); + + /* Font's global height and ascent values might be + preposterously large for some fonts. We fix here the case + when those fonts are used for display of glyphless + characters, because drawing background with font dimensions + in those cases makes the display illegible. There's only one + more call to the draw method with with_background set to + true, and that's in x_draw_glyph_string_foreground, when + drawing the cursor, where we have no such heuristics + available. FIXME. */ + if (s->first_glyph->type == GLYPHLESS_GLYPH + && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE + || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)) + height = ascent = + s->first_glyph->slice.glyphless.lower_yoff + - s->first_glyph->slice.glyphless.upper_yoff; + XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height); + } code = alloca (sizeof (FT_UInt) * len); for (i = 0; i < len; i++) code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) diff --git a/src/xterm.c b/src/xterm.c index 4f5dfed9ae..58563ff35d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1724,6 +1724,11 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) s->background_filled_p = true; } else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width + /* When xdisp.c ignores FONT_HEIGHT, we cannot trust + font dimensions, since the actual glyphs might be + much smaller. So in that case we always clear the + rectangle with background color. */ + || FONT_TOO_HIGH (s->font) || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) |