diff options
| author | Eli Zaretskii | 2015-06-06 15:55:15 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2015-06-06 16:10:19 +0300 |
| commit | f1baa156503f089d6627171e0e9ad73bbdbb7268 (patch) | |
| tree | 30f6860253e0cbd4c463cc163e24627e8dfc9bb6 /src | |
| parent | 6f10a3f90fb94506031712140246f1a5dbee71eb (diff) | |
| parent | 957cbfd7650e6ebd1afc62daeb5f6923730112c9 (diff) | |
| download | emacs-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.c | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 8 | ||||
| -rw-r--r-- | src/font.c | 7 | ||||
| -rw-r--r-- | src/nsterm.m | 9 | ||||
| -rw-r--r-- | src/w32font.c | 25 | ||||
| -rw-r--r-- | src/w32term.c | 12 | ||||
| -rw-r--r-- | src/xdisp.c | 210 | ||||
| -rw-r--r-- | src/xftfont.c | 22 | ||||
| -rw-r--r-- | src/xterm.c | 10 |
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, | |||
| 3240 | extern void produce_stretch_glyph (struct it *); | 3246 | extern void produce_stretch_glyph (struct it *); |
| 3241 | extern int merge_glyphless_glyph_face (struct it *); | 3247 | extern int merge_glyphless_glyph_face (struct it *); |
| 3242 | 3248 | ||
| 3249 | extern 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 | |||
| 5827 | x_new_font (struct frame *f, Lisp_Object font_object, int fontset) | 5832 | x_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); | |||
| 833 | static void notice_overwritten_cursor (struct window *, | 833 | static 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); |
| 836 | static int normal_char_height (struct font *, int); | ||
| 837 | static void normal_char_ascent_descent (struct font *, int, int *, int *); | ||
| 838 | |||
| 836 | static void append_stretch_glyph (struct it *, Lisp_Object, | 839 | static 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 | ||
| 24068 | void | ||
| 24069 | get_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. */ | ||
| 24589 | static void | ||
| 24590 | normal_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. */ | ||
| 24622 | static int | ||
| 24623 | normal_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 | |||
| 9405 | x_new_font (struct frame *f, Lisp_Object font_object, int fontset) | 9410 | x_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); |