Commit c76605fa authored by Eli Zaretskii's avatar Eli Zaretskii

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.
parent 1d87cb3c
......@@ -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
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -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;
......
......@@ -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)
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment