aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2015-06-06 15:55:15 +0300
committerEli Zaretskii2015-06-06 16:10:19 +0300
commitf1baa156503f089d6627171e0e9ad73bbdbb7268 (patch)
tree30f6860253e0cbd4c463cc163e24627e8dfc9bb6 /src
parent6f10a3f90fb94506031712140246f1a5dbee71eb (diff)
parent957cbfd7650e6ebd1afc62daeb5f6923730112c9 (diff)
downloademacs-f1baa156503f089d6627171e0e9ad73bbdbb7268.tar.gz
emacs-f1baa156503f089d6627171e0e9ad73bbdbb7268.zip
Fix display when a font claims large values of ascent and descent
This fixes bug#20628. * src/xdisp.c (get_phys_cursor_geometry): Correct the Y coordinate of a hollow cursor glyph when the original glyph's ascent is too small. (get_font_ascent_descent, normal_char_ascent_descent) (normal_char_height): New functions. (handle_single_display_spec, append_space_for_newline) (calc_pixel_width_or_height, produce_stretch_glyph) (calc_line_height_property): Use normal_char_ascent_descent and normal_char_height. (x_produce_glyphs): When font-global values of ascent and descent are too large, use per-character glyph metrics instead, if possible. But don't allow the glyph row's ascent and descent values become smaller than the values from the metrics of the font's "normal" character. * src/xftfont.c (xftfont_draw): * src/w32font.c (w32font_draw): Correct the values of ascent and descent used to draw glyphless characters' hex code in a box. * src/xterm.c (x_draw_glyph_string_background): * src/xdisp.c (x_produce_glyphs): * src/w32term.c (x_draw_glyph_string_background): * src/nsterm.m (ns_maybe_dumpglyphs_background): Use FONT_TOO_HIGH to detect fonts whose global ascent and descent values are too large to be used in layout decision, and redraw the background when that happens. * src/dispextern.h (FONT_TOO_HIGH): New macro. (get_font_ascent_descent): Add prototype. * src/xterm.c (x_new_font): * src/w32term.c (x_new_font): * src/nsterm.m (x_new_font): * src/font.c (font_open_entity): * src/composite.c (composition_gstring_width): Use get_font_ascent_descent to obtain reasonable values for ascent and descent of a font.
Diffstat (limited to 'src')
-rw-r--r--src/composite.c6
-rw-r--r--src/dispextern.h8
-rw-r--r--src/font.c7
-rw-r--r--src/nsterm.m9
-rw-r--r--src/w32font.c25
-rw-r--r--src/w32term.c12
-rw-r--r--src/xdisp.c210
-rw-r--r--src/xftfont.c22
-rw-r--r--src/xterm.c10
9 files changed, 274 insertions, 35 deletions
diff --git a/src/composite.c b/src/composite.c
index 1c9c62bf910..1c18165599d 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -732,9 +732,11 @@ composition_gstring_width (Lisp_Object gstring, ptrdiff_t from, ptrdiff_t to,
732 if (FONT_OBJECT_P (font_object)) 732 if (FONT_OBJECT_P (font_object))
733 { 733 {
734 struct font *font = XFONT_OBJECT (font_object); 734 struct font *font = XFONT_OBJECT (font_object);
735 int font_ascent, font_descent;
735 736
736 metrics->ascent = font->ascent; 737 get_font_ascent_descent (font, &font_ascent, &font_descent);
737 metrics->descent = font->descent; 738 metrics->ascent = font_ascent;
739 metrics->descent = font_descent;
738 } 740 }
739 else 741 else
740 { 742 {
diff --git a/src/dispextern.h b/src/dispextern.h
index d9d4d2300fa..5202142313a 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1526,6 +1526,12 @@ struct glyph_string
1526 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \ 1526 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1527 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F))) 1527 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1528 1528
1529/* A heuristic test for fonts that claim they need a preposterously
1530 large vertical space. The heuristics is in the factor of 3. We
1531 ignore the ascent and descent values reported by such fonts, and
1532 instead go by the values reported for individual glyphs. */
1533#define FONT_TOO_HIGH(ft) ((ft)->ascent + (ft)->descent > 3*(ft)->pixel_size)
1534
1529 1535
1530/*********************************************************************** 1536/***********************************************************************
1531 Faces 1537 Faces
@@ -3240,6 +3246,8 @@ extern ptrdiff_t compute_display_string_end (ptrdiff_t,
3240extern void produce_stretch_glyph (struct it *); 3246extern void produce_stretch_glyph (struct it *);
3241extern int merge_glyphless_glyph_face (struct it *); 3247extern int merge_glyphless_glyph_face (struct it *);
3242 3248
3249extern void get_font_ascent_descent (struct font *, int *, int *);
3250
3243#ifdef HAVE_WINDOW_SYSTEM 3251#ifdef HAVE_WINDOW_SYSTEM
3244 3252
3245#ifdef GLYPH_DEBUG 3253#ifdef GLYPH_DEBUG
diff --git a/src/font.c b/src/font.c
index 1405d437241..556f32bb432 100644
--- a/src/font.c
+++ b/src/font.c
@@ -2908,7 +2908,12 @@ font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
2908 : font->average_width ? font->average_width 2908 : font->average_width ? font->average_width
2909 : font->space_width ? font->space_width 2909 : font->space_width ? font->space_width
2910 : 1); 2910 : 1);
2911 height = (font->height ? font->height : 1); 2911
2912 int font_ascent, font_descent;
2913 get_font_ascent_descent (font, &font_ascent, &font_descent);
2914 height = font_ascent + font_descent;
2915 if (height <= 0)
2916 height = 1;
2912#ifdef HAVE_WINDOW_SYSTEM 2917#ifdef HAVE_WINDOW_SYSTEM
2913 FRAME_DISPLAY_INFO (f)->n_fonts++; 2918 FRAME_DISPLAY_INFO (f)->n_fonts++;
2914 if (FRAME_DISPLAY_INFO (f)->n_fonts == 1) 2919 if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
diff --git a/src/nsterm.m b/src/nsterm.m
index 67a03898d13..2806f31155d 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2928,6 +2928,11 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
2928 { 2928 {
2929 int box_line_width = max (s->face->box_line_width, 0); 2929 int box_line_width = max (s->face->box_line_width, 0);
2930 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 2930 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2931 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
2932 dimensions, since the actual glyphs might be much
2933 smaller. So in that case we always clear the rectangle
2934 with background color. */
2935 || FONT_TOO_HIGH (s->font)
2931 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) 2936 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
2932 { 2937 {
2933 struct face *face; 2938 struct face *face;
@@ -7687,6 +7692,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7687{ 7692{
7688 struct font *font = XFONT_OBJECT (font_object); 7693 struct font *font = XFONT_OBJECT (font_object);
7689 EmacsView *view = FRAME_NS_VIEW (f); 7694 EmacsView *view = FRAME_NS_VIEW (f);
7695 int font_ascent, font_descent;
7690 7696
7691 if (fontset < 0) 7697 if (fontset < 0)
7692 fontset = fontset_from_font (font_object); 7698 fontset = fontset_from_font (font_object);
@@ -7701,7 +7707,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
7701 7707
7702 FRAME_BASELINE_OFFSET (f) = font->baseline_offset; 7708 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
7703 FRAME_COLUMN_WIDTH (f) = font->average_width; 7709 FRAME_COLUMN_WIDTH (f) = font->average_width;
7704 FRAME_LINE_HEIGHT (f) = font->height; 7710 get_font_ascent_descent (font, &font_ascent, &font_descent);
7711 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
7705 7712
7706 /* Compute the scroll bar width in character columns. */ 7713 /* Compute the scroll bar width in character columns. */
7707 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) 7714 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
diff --git a/src/w32font.c b/src/w32font.c
index 6306a8460e7..1c2f9665037 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -650,12 +650,31 @@ w32font_draw (struct glyph_string *s, int from, int to,
650 HBRUSH brush; 650 HBRUSH brush;
651 RECT rect; 651 RECT rect;
652 struct font *font = s->font; 652 struct font *font = s->font;
653 653 int ascent = font->ascent, descent = font->descent;
654
655 /* Font's global ascent and descent values might be
656 preposterously large for some fonts. We fix here the case
657 when those fonts are used for display of glyphless
658 characters, because drawing background with font dimensions
659 in those cases makes the display illegible. There's only one
660 more call to the draw method with with_background set to
661 true, and that's in x_draw_glyph_string_foreground, when
662 drawing the cursor, where we have no such heuristics
663 available. FIXME. */
664 if (s->first_glyph->type == GLYPHLESS_GLYPH
665 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
666 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
667 {
668 ascent =
669 s->first_glyph->slice.glyphless.lower_yoff
670 - s->first_glyph->slice.glyphless.upper_yoff;
671 descent = 0;
672 }
654 brush = CreateSolidBrush (s->gc->background); 673 brush = CreateSolidBrush (s->gc->background);
655 rect.left = x; 674 rect.left = x;
656 rect.top = y - font->ascent; 675 rect.top = y - ascent;
657 rect.right = x + s->width; 676 rect.right = x + s->width;
658 rect.bottom = y + font->descent; 677 rect.bottom = y + descent;
659 FillRect (s->hdc, &rect, brush); 678 FillRect (s->hdc, &rect, brush);
660 DeleteObject (brush); 679 DeleteObject (brush);
661 } 680 }
diff --git a/src/w32term.c b/src/w32term.c
index 0bc2e980214..b7c6e13c8a8 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)
1218 } 1218 }
1219 else 1219 else
1220#endif 1220#endif
1221 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 1221 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1222 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1223 font dimensions, since the actual glyphs might be
1224 much smaller. So in that case we always clear the
1225 rectangle with background color. */
1226 || FONT_TOO_HIGH (s->font)
1222 || s->font_not_found_p 1227 || s->font_not_found_p
1223 || s->extends_to_end_of_line_p 1228 || s->extends_to_end_of_line_p
1224 || force_p) 1229 || force_p)
@@ -5827,7 +5832,7 @@ Lisp_Object
5827x_new_font (struct frame *f, Lisp_Object font_object, int fontset) 5832x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
5828{ 5833{
5829 struct font *font = XFONT_OBJECT (font_object); 5834 struct font *font = XFONT_OBJECT (font_object);
5830 int unit; 5835 int unit, font_ascent, font_descent;
5831 5836
5832 if (fontset < 0) 5837 if (fontset < 0)
5833 fontset = fontset_from_font (font_object); 5838 fontset = fontset_from_font (font_object);
@@ -5840,7 +5845,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
5840 FRAME_FONT (f) = font; 5845 FRAME_FONT (f) = font;
5841 FRAME_BASELINE_OFFSET (f) = font->baseline_offset; 5846 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
5842 FRAME_COLUMN_WIDTH (f) = unit = font->average_width; 5847 FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
5843 FRAME_LINE_HEIGHT (f) = font->height; 5848 get_font_ascent_descent (font, &font_ascent, &font_descent);
5849 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
5844 5850
5845 /* Compute number of scrollbar columns. */ 5851 /* Compute number of scrollbar columns. */
5846 unit = FRAME_COLUMN_WIDTH (f); 5852 unit = FRAME_COLUMN_WIDTH (f);
diff --git a/src/xdisp.c b/src/xdisp.c
index 05862d276ef..14385fa8421 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -833,6 +833,9 @@ static void x_draw_bottom_divider (struct window *w);
833static void notice_overwritten_cursor (struct window *, 833static void notice_overwritten_cursor (struct window *,
834 enum glyph_row_area, 834 enum glyph_row_area,
835 int, int, int, int); 835 int, int, int, int);
836static int normal_char_height (struct font *, int);
837static void normal_char_ascent_descent (struct font *, int, int *, int *);
838
836static void append_stretch_glyph (struct it *, Lisp_Object, 839static void append_stretch_glyph (struct it *, Lisp_Object,
837 int, int, int); 840 int, int, int);
838 841
@@ -1761,7 +1764,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
1761 if (face) 1764 if (face)
1762 { 1765 {
1763 if (face->font) 1766 if (face->font)
1764 height = FONT_HEIGHT (face->font); 1767 height = normal_char_height (face->font, -1);
1765 if (face->box_line_width > 0) 1768 if (face->box_line_width > 0)
1766 height += 2 * face->box_line_width; 1769 height += 2 * face->box_line_width;
1767 } 1770 }
@@ -2150,7 +2153,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2150 struct glyph *glyph, int *xp, int *yp, int *heightp) 2153 struct glyph *glyph, int *xp, int *yp, int *heightp)
2151{ 2154{
2152 struct frame *f = XFRAME (WINDOW_FRAME (w)); 2155 struct frame *f = XFRAME (WINDOW_FRAME (w));
2153 int x, y, wd, h, h0, y0; 2156 int x, y, wd, h, h0, y0, ascent;
2154 2157
2155 /* Compute the width of the rectangle to draw. If on a stretch 2158 /* Compute the width of the rectangle to draw. If on a stretch
2156 glyph, and `x-stretch-block-cursor' is nil, don't draw a 2159 glyph, and `x-stretch-block-cursor' is nil, don't draw a
@@ -2170,13 +2173,21 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2170 wd = min (FRAME_COLUMN_WIDTH (f), wd); 2173 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2171 w->phys_cursor_width = wd; 2174 w->phys_cursor_width = wd;
2172 2175
2173 y = w->phys_cursor.y + row->ascent - glyph->ascent; 2176 /* Don't let the hollow cursor glyph descend below the glyph row's
2177 ascent value, lest the hollow cursor looks funny. */
2178 y = w->phys_cursor.y;
2179 ascent = row->ascent;
2180 if (row->ascent < glyph->ascent)
2181 {
2182 y =- glyph->ascent - row->ascent;
2183 ascent = glyph->ascent;
2184 }
2174 2185
2175 /* If y is below window bottom, ensure that we still see a cursor. */ 2186 /* If y is below window bottom, ensure that we still see a cursor. */
2176 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height); 2187 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2177 2188
2178 h = max (h0, glyph->ascent + glyph->descent); 2189 h = max (h0, ascent + glyph->descent);
2179 h0 = min (h0, glyph->ascent + glyph->descent); 2190 h0 = min (h0, ascent + glyph->descent);
2180 2191
2181 y0 = WINDOW_HEADER_LINE_HEIGHT (w); 2192 y0 = WINDOW_HEADER_LINE_HEIGHT (w);
2182 if (y < y0) 2193 if (y < y0)
@@ -4880,7 +4891,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4880 { 4891 {
4881 struct face *face = FACE_FROM_ID (it->f, it->face_id); 4892 struct face *face = FACE_FROM_ID (it->f, it->face_id);
4882 it->voffset = - (XFLOATINT (value) 4893 it->voffset = - (XFLOATINT (value)
4883 * (FONT_HEIGHT (face->font))); 4894 * (normal_char_height (face->font, -1)));
4884 } 4895 }
4885#endif /* HAVE_WINDOW_SYSTEM */ 4896#endif /* HAVE_WINDOW_SYSTEM */
4886 } 4897 }
@@ -19157,6 +19168,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
19157 struct text_pos saved_pos; 19168 struct text_pos saved_pos;
19158 Lisp_Object saved_object; 19169 Lisp_Object saved_object;
19159 struct face *face; 19170 struct face *face;
19171 struct glyph *g;
19160 19172
19161 saved_object = it->object; 19173 saved_object = it->object;
19162 saved_pos = it->position; 19174 saved_pos = it->position;
@@ -19188,6 +19200,23 @@ append_space_for_newline (struct it *it, bool default_face_p)
19188 19200
19189 PRODUCE_GLYPHS (it); 19201 PRODUCE_GLYPHS (it);
19190 19202
19203 /* Make sure this space glyph has the right ascent and
19204 descent values, or else cursor at end of line will look
19205 funny. */
19206 g = it->glyph_row->glyphs[TEXT_AREA] + n;
19207 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
19208 if (n == 0 || it->glyph_row->height < font->pixel_size)
19209 {
19210 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
19211 it->max_ascent = it->ascent;
19212 it->max_descent = it->descent;
19213 /* Make sure compute_line_metrics recomputes the row height. */
19214 it->glyph_row->height = 0;
19215 }
19216
19217 g->ascent = it->max_ascent;
19218 g->descent = it->max_descent;
19219
19191 it->override_ascent = -1; 19220 it->override_ascent = -1;
19192 it->constrain_row_ascent_descent_p = false; 19221 it->constrain_row_ascent_descent_p = false;
19193 it->current_x = saved_x; 19222 it->current_x = saved_x;
@@ -23900,9 +23929,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
23900 23929
23901#ifdef HAVE_WINDOW_SYSTEM 23930#ifdef HAVE_WINDOW_SYSTEM
23902 if (EQ (prop, Qheight)) 23931 if (EQ (prop, Qheight))
23903 return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f)); 23932 return OK_PIXELS (font
23933 ? normal_char_height (font, -1)
23934 : FRAME_LINE_HEIGHT (it->f));
23904 if (EQ (prop, Qwidth)) 23935 if (EQ (prop, Qwidth))
23905 return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f)); 23936 return OK_PIXELS (font
23937 ? FONT_WIDTH (font)
23938 : FRAME_COLUMN_WIDTH (it->f));
23906#else 23939#else
23907 if (EQ (prop, Qheight) || EQ (prop, Qwidth)) 23940 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
23908 return OK_PIXELS (1); 23941 return OK_PIXELS (1);
@@ -24032,6 +24065,17 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
24032 return false; 24065 return false;
24033} 24066}
24034 24067
24068void
24069get_font_ascent_descent (struct font *font, int *ascent, int *descent)
24070{
24071#ifdef HAVE_WINDOW_SYSTEM
24072 normal_char_ascent_descent (font, -1, ascent, descent);
24073#else
24074 *ascent = 1;
24075 *descent = 0;
24076#endif
24077}
24078
24035 24079
24036/*********************************************************************** 24080/***********************************************************************
24037 Glyph Display 24081 Glyph Display
@@ -24536,6 +24580,55 @@ get_per_char_metric (struct font *font, XChar2b *char2b)
24536 return &metrics; 24580 return &metrics;
24537} 24581}
24538 24582
24583/* A subroutine that computes "normal" values of ASCENT and DESCENT
24584 for FONT. Values are taken from font-global ones, except for fonts
24585 that claim preposterously large values, but whose glyphs actually
24586 have reasonable dimensions. C is the character to use for metrics
24587 if the font-global values are too large; if C is negative, the
24588 function selects a default character. */
24589static void
24590normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
24591{
24592 *ascent = FONT_BASE (font);
24593 *descent = FONT_DESCENT (font);
24594
24595 if (FONT_TOO_HIGH (font))
24596 {
24597 XChar2b char2b;
24598
24599 /* Get metrics of C, defaulting to a reasonably sized ASCII
24600 character. */
24601 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
24602 {
24603 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
24604
24605 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
24606 {
24607 /* We add 1 pixel to character dimensions as heuristics
24608 that produces nicer display, e.g. when the face has
24609 the box attribute. */
24610 *ascent = pcm->ascent + 1;
24611 *descent = pcm->descent + 1;
24612 }
24613 }
24614 }
24615}
24616
24617/* A subroutine that computes a reasonable "normal character height"
24618 for fonts that claim preposterously large vertical dimensions, but
24619 whose glyphs are actually reasonably sized. C is the charcater
24620 whose metrics to use for those fonts, or -1 for default
24621 character. */
24622static int
24623normal_char_height (struct font *font, int c)
24624{
24625 int ascent, descent;
24626
24627 normal_char_ascent_descent (font, c, &ascent, &descent);
24628
24629 return ascent + descent;
24630}
24631
24539/* EXPORT for RIF: 24632/* EXPORT for RIF:
24540 Set *LEFT and *RIGHT to the left and right overhang of GLYPH on 24633 Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
24541 frame F. Overhangs of glyphs other than type CHAR_GLYPH are 24634 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
@@ -25835,6 +25928,8 @@ produce_stretch_glyph (struct it *it)
25835 /* Compute height. */ 25928 /* Compute height. */
25836 if (FRAME_WINDOW_P (it->f)) 25929 if (FRAME_WINDOW_P (it->f))
25837 { 25930 {
25931 int default_height = normal_char_height (font, ' ');
25932
25838 if ((prop = Fplist_get (plist, QCheight), !NILP (prop)) 25933 if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
25839 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0)) 25934 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
25840 { 25935 {
@@ -25843,9 +25938,9 @@ produce_stretch_glyph (struct it *it)
25843 } 25938 }
25844 else if (prop = Fplist_get (plist, QCrelative_height), 25939 else if (prop = Fplist_get (plist, QCrelative_height),
25845 NUMVAL (prop) > 0) 25940 NUMVAL (prop) > 0)
25846 height = FONT_HEIGHT (font) * NUMVAL (prop); 25941 height = default_height * NUMVAL (prop);
25847 else 25942 else
25848 height = FONT_HEIGHT (font); 25943 height = default_height;
25849 25944
25850 if (height <= 0 && (height < 0 || !zero_height_ok_p)) 25945 if (height <= 0 && (height < 0 || !zero_height_ok_p))
25851 height = 1; 25946 height = 1;
@@ -26069,8 +26164,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
26069 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; 26164 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
26070 } 26165 }
26071 26166
26072 ascent = FONT_BASE (font) + boff; 26167 normal_char_ascent_descent (font, -1, &ascent, &descent);
26073 descent = FONT_DESCENT (font) - boff;
26074 26168
26075 if (override) 26169 if (override)
26076 { 26170 {
@@ -26196,8 +26290,9 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
26196 ASCII face. */ 26290 ASCII face. */
26197 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face; 26291 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
26198 font = face->font ? face->font : FRAME_FONT (it->f); 26292 font = face->font ? face->font : FRAME_FONT (it->f);
26199 it->ascent = FONT_BASE (font) + font->baseline_offset; 26293 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
26200 it->descent = FONT_DESCENT (font) - font->baseline_offset; 26294 it->ascent += font->baseline_offset;
26295 it->descent -= font->baseline_offset;
26201 base_height = it->ascent + it->descent; 26296 base_height = it->ascent + it->descent;
26202 base_width = font->average_width; 26297 base_width = font->average_width;
26203 26298
@@ -26384,6 +26479,22 @@ x_produce_glyphs (struct it *it)
26384 it->phys_ascent = pcm->ascent + boff; 26479 it->phys_ascent = pcm->ascent + boff;
26385 it->phys_descent = pcm->descent - boff; 26480 it->phys_descent = pcm->descent - boff;
26386 it->pixel_width = pcm->width; 26481 it->pixel_width = pcm->width;
26482 /* Don't use font-global values for ascent and descent
26483 if they result in an exceedingly large line height. */
26484 if (it->override_ascent < 0)
26485 {
26486 if (FONT_TOO_HIGH (font))
26487 {
26488 it->ascent = it->phys_ascent;
26489 it->descent = it->phys_descent;
26490 /* These limitations are enforced by an
26491 assertion near the end of this function. */
26492 if (it->ascent < 0)
26493 it->ascent = 0;
26494 if (it->descent < 0)
26495 it->descent = 0;
26496 }
26497 }
26387 } 26498 }
26388 else 26499 else
26389 { 26500 {
@@ -26511,8 +26622,18 @@ x_produce_glyphs (struct it *it)
26511 } 26622 }
26512 else 26623 else
26513 { 26624 {
26514 it->ascent = FONT_BASE (font) + boff; 26625 if (FONT_TOO_HIGH (font))
26515 it->descent = FONT_DESCENT (font) - boff; 26626 {
26627 it->ascent = font->pixel_size + boff - 1;
26628 it->descent = -boff + 1;
26629 if (it->descent < 0)
26630 it->descent = 0;
26631 }
26632 else
26633 {
26634 it->ascent = FONT_BASE (font) + boff;
26635 it->descent = FONT_DESCENT (font) - boff;
26636 }
26516 } 26637 }
26517 26638
26518 if (EQ (height, Qt)) 26639 if (EQ (height, Qt))
@@ -26583,8 +26704,38 @@ x_produce_glyphs (struct it *it)
26583 26704
26584 it->pixel_width = next_tab_x - x; 26705 it->pixel_width = next_tab_x - x;
26585 it->nglyphs = 1; 26706 it->nglyphs = 1;
26586 it->ascent = it->phys_ascent = FONT_BASE (font) + boff; 26707 if (FONT_TOO_HIGH (font))
26587 it->descent = it->phys_descent = FONT_DESCENT (font) - boff; 26708 {
26709 if (get_char_glyph_code (' ', font, &char2b))
26710 {
26711 pcm = get_per_char_metric (font, &char2b);
26712 if (pcm->width == 0
26713 && pcm->rbearing == 0 && pcm->lbearing == 0)
26714 pcm = NULL;
26715 }
26716
26717 if (pcm)
26718 {
26719 it->ascent = pcm->ascent + boff;
26720 it->descent = pcm->descent - boff;
26721 }
26722 else
26723 {
26724 it->ascent = font->pixel_size + boff - 1;
26725 it->descent = -boff + 1;
26726 }
26727 if (it->ascent < 0)
26728 it->ascent = 0;
26729 if (it->descent < 0)
26730 it->descent = 0;
26731 }
26732 else
26733 {
26734 it->ascent = FONT_BASE (font) + boff;
26735 it->descent = FONT_DESCENT (font) - boff;
26736 }
26737 it->phys_ascent = it->ascent;
26738 it->phys_descent = it->descent;
26588 26739
26589 if (it->glyph_row) 26740 if (it->glyph_row)
26590 { 26741 {
@@ -26598,6 +26749,22 @@ x_produce_glyphs (struct it *it)
26598 it->nglyphs = 1; 26749 it->nglyphs = 1;
26599 } 26750 }
26600 } 26751 }
26752
26753 if (FONT_TOO_HIGH (font))
26754 {
26755 int font_ascent, font_descent;
26756
26757 /* For very large fonts, where we ignore the declared font
26758 dimensions, and go by per-character metrics instead,
26759 don't let the row ascent and descent values (and the row
26760 height computed from them) be smaller than the "normal"
26761 character metrics. This avoids unpleasant effects
26762 whereby lines on display would change their heigh
26763 depending on which characters are shown. */
26764 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
26765 it->max_ascent = max (it->max_ascent, font_ascent);
26766 it->max_descent = max (it->max_descent, font_descent);
26767 }
26601 } 26768 }
26602 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0) 26769 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
26603 { 26770 {
@@ -26664,9 +26831,10 @@ x_produce_glyphs (struct it *it)
26664 boff = font->baseline_offset; 26831 boff = font->baseline_offset;
26665 if (font->vertical_centering) 26832 if (font->vertical_centering)
26666 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; 26833 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
26667 font_ascent = FONT_BASE (font) + boff; 26834 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
26668 font_descent = FONT_DESCENT (font) - boff; 26835 font_ascent += boff;
26669 font_height = FONT_HEIGHT (font); 26836 font_descent -= boff;
26837 font_height = font_ascent + font_descent;
26670 26838
26671 cmp->font = font; 26839 cmp->font = font;
26672 26840
diff --git a/src/xftfont.c b/src/xftfont.c
index 0e8b876f1d3..a1846e8d461 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,
617 XftDrawSetClip (xft_draw, NULL); 617 XftDrawSetClip (xft_draw, NULL);
618 618
619 if (with_background) 619 if (with_background)
620 XftDrawRect (xft_draw, &bg, 620 {
621 x, y - s->font->ascent, s->width, s->font->height); 621 int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
622
623 /* Font's global height and ascent values might be
624 preposterously large for some fonts. We fix here the case
625 when those fonts are used for display of glyphless
626 characters, because drawing background with font dimensions
627 in those cases makes the display illegible. There's only one
628 more call to the draw method with with_background set to
629 true, and that's in x_draw_glyph_string_foreground, when
630 drawing the cursor, where we have no such heuristics
631 available. FIXME. */
632 if (s->first_glyph->type == GLYPHLESS_GLYPH
633 && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
634 || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
635 height = ascent =
636 s->first_glyph->slice.glyphless.lower_yoff
637 - s->first_glyph->slice.glyphless.upper_yoff;
638 XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
639 }
622 code = alloca (sizeof (FT_UInt) * len); 640 code = alloca (sizeof (FT_UInt) * len);
623 for (i = 0; i < len; i++) 641 for (i = 0; i < len; i++)
624 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) 642 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
diff --git a/src/xterm.c b/src/xterm.c
index 691ede58b43..4d7945059fe 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)
1724 s->background_filled_p = true; 1724 s->background_filled_p = true;
1725 } 1725 }
1726 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 1726 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1727 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
1728 font dimensions, since the actual glyphs might be
1729 much smaller. So in that case we always clear the
1730 rectangle with background color. */
1731 || FONT_TOO_HIGH (s->font)
1727 || s->font_not_found_p 1732 || s->font_not_found_p
1728 || s->extends_to_end_of_line_p 1733 || s->extends_to_end_of_line_p
1729 || force_p) 1734 || force_p)
@@ -9405,7 +9410,7 @@ Lisp_Object
9405x_new_font (struct frame *f, Lisp_Object font_object, int fontset) 9410x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
9406{ 9411{
9407 struct font *font = XFONT_OBJECT (font_object); 9412 struct font *font = XFONT_OBJECT (font_object);
9408 int unit; 9413 int unit, font_ascent, font_descent;
9409 9414
9410 if (fontset < 0) 9415 if (fontset < 0)
9411 fontset = fontset_from_font (font_object); 9416 fontset = fontset_from_font (font_object);
@@ -9418,7 +9423,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
9418 FRAME_FONT (f) = font; 9423 FRAME_FONT (f) = font;
9419 FRAME_BASELINE_OFFSET (f) = font->baseline_offset; 9424 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
9420 FRAME_COLUMN_WIDTH (f) = font->average_width; 9425 FRAME_COLUMN_WIDTH (f) = font->average_width;
9421 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font); 9426 get_font_ascent_descent (font, &font_ascent, &font_descent);
9427 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
9422 9428
9423#ifndef USE_X_TOOLKIT 9429#ifndef USE_X_TOOLKIT
9424 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); 9430 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);