emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master f1baa15: Fix display when a font claims large value


From: Eli Zaretskii
Subject: [Emacs-diffs] master f1baa15: Fix display when a font claims large values of ascent and descent
Date: Sat, 06 Jun 2015 13:12:17 +0000

branch: master
commit f1baa156503f089d6627171e0e9ad73bbdbb7268
Merge: 6f10a3f 957cbfd
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    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.
---
 src/composite.c  |    6 +-
 src/dispextern.h |    8 ++
 src/font.c       |    7 ++-
 src/nsterm.m     |    9 ++-
 src/w32font.c    |   25 ++++++-
 src/w32term.c    |   12 +++-
 src/xdisp.c      |  210 ++++++++++++++++++++++++++++++++++++++++++++++++------
 src/xftfont.c    |   22 +++++-
 src/xterm.c      |   10 ++-
 9 files changed, 274 insertions(+), 35 deletions(-)

diff --git a/src/composite.c b/src/composite.c
index 1c9c62b..1c18165 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,
       if (FONT_OBJECT_P (font_object))
        {
          struct font *font = XFONT_OBJECT (font_object);
+         int font_ascent, font_descent;
 
-         metrics->ascent = font->ascent;
-         metrics->descent = font->descent;
+         get_font_ascent_descent (font, &font_ascent, &font_descent);
+         metrics->ascent = font_ascent;
+         metrics->descent = font_descent;
        }
       else
        {
diff --git a/src/dispextern.h b/src/dispextern.h
index d9d4d23..5202142 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
@@ -3240,6 +3246,8 @@ extern ptrdiff_t compute_display_string_end (ptrdiff_t,
 extern void produce_stretch_glyph (struct it *);
 extern int merge_glyphless_glyph_face (struct it *);
 
+extern void get_font_ascent_descent (struct font *, int *, int *);
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 #ifdef GLYPH_DEBUG
diff --git a/src/font.c b/src/font.c
index 1405d43..556f32b 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)
               : font->average_width ? font->average_width
               : font->space_width ? font->space_width
               : 1);
-  height = (font->height ? font->height : 1);
+
+  int font_ascent, font_descent;
+  get_font_ascent_descent (font, &font_ascent, &font_descent);
+  height = font_ascent + font_descent;
+  if (height <= 0)
+    height = 1;
 #ifdef HAVE_WINDOW_SYSTEM
   FRAME_DISPLAY_INFO (f)->n_fonts++;
   if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
diff --git a/src/nsterm.m b/src/nsterm.m
index 67a0389..2806f31 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2928,6 +2928,11 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, 
char force_p)
     {
       int box_line_width = max (s->face->box_line_width, 0);
       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)
        {
           struct face *face;
@@ -7687,6 +7692,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int 
fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
   EmacsView *view = FRAME_NS_VIEW (f);
+  int font_ascent, font_descent;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -7701,7 +7707,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int 
fontset)
 
   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   FRAME_COLUMN_WIDTH (f) = font->average_width;
-  FRAME_LINE_HEIGHT (f) = font->height;
+  get_font_ascent_descent (font, &font_ascent, &font_descent);
+  FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
 
   /* Compute the scroll bar width in character columns.  */
   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
diff --git a/src/w32font.c b/src/w32font.c
index 6306a84..1c2f966 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 0bc2e98..b7c6e13 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)
@@ -5827,7 +5832,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
-  int unit;
+  int unit, font_ascent, font_descent;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -5840,7 +5845,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int 
fontset)
   FRAME_FONT (f) = font;
   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
-  FRAME_LINE_HEIGHT (f) = font->height;
+  get_font_ascent_descent (font, &font_ascent, &font_descent);
+  FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
 
   /* Compute number of scrollbar columns.  */
   unit = FRAME_COLUMN_WIDTH (f);
diff --git a/src/xdisp.c b/src/xdisp.c
index 05862d2..14385fa 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -833,6 +833,9 @@ static void x_draw_bottom_divider (struct window *w);
 static void notice_overwritten_cursor (struct window *,
                                        enum glyph_row_area,
                                        int, int, int, int);
+static int  normal_char_height (struct font *, int);
+static void normal_char_ascent_descent (struct font *, int, int *, int *);
+
 static void append_stretch_glyph (struct it *, Lisp_Object,
                                   int, int, int);
 
@@ -1761,7 +1764,7 @@ estimate_mode_line_height (struct frame *f, enum face_id 
face_id)
          if (face)
            {
              if (face->font)
-               height = FONT_HEIGHT (face->font);
+               height = normal_char_height (face->font, -1);
              if (face->box_line_width > 0)
                height += 2 * face->box_line_width;
            }
@@ -2150,7 +2153,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 +2173,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)
@@ -4880,7 +4891,7 @@ handle_single_display_spec (struct it *it, Lisp_Object 
spec, Lisp_Object object,
            {
              struct face *face = FACE_FROM_ID (it->f, it->face_id);
              it->voffset = - (XFLOATINT (value)
-                              * (FONT_HEIGHT (face->font)));
+                              * (normal_char_height (face->font, -1)));
            }
 #endif /* HAVE_WINDOW_SYSTEM */
        }
@@ -19157,6 +19168,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;
@@ -19188,6 +19200,23 @@ append_space_for_newline (struct it *it, bool 
default_face_p)
 
          PRODUCE_GLYPHS (it);
 
+         /* Make sure this space glyph has the right ascent and
+            descent values, or else cursor at end of line will look
+            funny.  */
+         g = it->glyph_row->glyphs[TEXT_AREA] + n;
+         struct font *font = face->font ? face->font : FRAME_FONT (it->f);
+         if (n == 0 || it->glyph_row->height < font->pixel_size)
+           {
+             normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
+             it->max_ascent = it->ascent;
+             it->max_descent = it->descent;
+             /* Make sure compute_line_metrics recomputes the row height.  */
+             it->glyph_row->height = 0;
+           }
+
+         g->ascent = it->max_ascent;
+         g->descent = it->max_descent;
+
          it->override_ascent = -1;
          it->constrain_row_ascent_descent_p = false;
          it->current_x = saved_x;
@@ -23900,9 +23929,13 @@ calc_pixel_width_or_height (double *res, struct it 
*it, Lisp_Object prop,
 
 #ifdef HAVE_WINDOW_SYSTEM
       if (EQ (prop, Qheight))
-       return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT 
(it->f));
+       return OK_PIXELS (font
+                         ? normal_char_height (font, -1)
+                         : FRAME_LINE_HEIGHT (it->f));
       if (EQ (prop, Qwidth))
-       return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH 
(it->f));
+       return OK_PIXELS (font
+                         ? FONT_WIDTH (font)
+                         : FRAME_COLUMN_WIDTH (it->f));
 #else
       if (EQ (prop, Qheight) || EQ (prop, Qwidth))
        return OK_PIXELS (1);
@@ -24032,6 +24065,17 @@ calc_pixel_width_or_height (double *res, struct it 
*it, Lisp_Object prop,
   return false;
 }
 
+void
+get_font_ascent_descent (struct font *font, int *ascent, int *descent)
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  normal_char_ascent_descent (font, -1, ascent, descent);
+#else
+  *ascent = 1;
+  *descent = 0;
+#endif
+}
+
 
 /***********************************************************************
                             Glyph Display
@@ -24536,6 +24580,55 @@ get_per_char_metric (struct font *font, XChar2b 
*char2b)
   return &metrics;
 }
 
+/* A subroutine that computes "normal" values of ASCENT and DESCENT
+   for FONT.  Values are taken from font-global ones, except for fonts
+   that claim preposterously large values, but whose glyphs actually
+   have reasonable dimensions.  C is the character to use for metrics
+   if the font-global values are too large; if C is negative, the
+   function selects a default character.  */
+static void
+normal_char_ascent_descent (struct font *font, int c, int *ascent, int 
*descent)
+{
+  *ascent = FONT_BASE (font);
+  *descent = FONT_DESCENT (font);
+
+  if (FONT_TOO_HIGH (font))
+    {
+      XChar2b char2b;
+
+      /* Get metrics of C, defaulting to a reasonably sized ASCII
+        character.  */
+      if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
+       {
+         struct font_metrics *pcm = get_per_char_metric (font, &char2b);
+
+         if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
+           {
+             /* We add 1 pixel to character dimensions as heuristics
+                that produces nicer display, e.g. when the face has
+                the box attribute.  */
+             *ascent = pcm->ascent + 1;
+             *descent = pcm->descent + 1;
+           }
+       }
+    }
+}
+
+/* A subroutine that computes a reasonable "normal character height"
+   for fonts that claim preposterously large vertical dimensions, but
+   whose glyphs are actually reasonably sized.  C is the charcater
+   whose metrics to use for those fonts, or -1 for default
+   character.  */
+static int
+normal_char_height (struct font *font, int c)
+{
+  int ascent, descent;
+
+  normal_char_ascent_descent (font, c, &ascent, &descent);
+
+  return ascent + descent;
+}
+
 /* EXPORT for RIF:
    Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
    frame F.  Overhangs of glyphs other than type CHAR_GLYPH are
@@ -25835,6 +25928,8 @@ produce_stretch_glyph (struct it *it)
   /* Compute height.  */
   if (FRAME_WINDOW_P (it->f))
     {
+      int default_height = normal_char_height (font, ' ');
+
       if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
          && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
        {
@@ -25843,9 +25938,9 @@ produce_stretch_glyph (struct it *it)
        }
       else if (prop = Fplist_get (plist, QCrelative_height),
               NUMVAL (prop) > 0)
-       height = FONT_HEIGHT (font) * NUMVAL (prop);
+       height = default_height * NUMVAL (prop);
       else
-       height = FONT_HEIGHT (font);
+       height = default_height;
 
       if (height <= 0 && (height < 0 || !zero_height_ok_p))
        height = 1;
@@ -26069,8 +26164,7 @@ calc_line_height_property (struct it *it, Lisp_Object 
val, struct font *font,
        boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
     }
 
-  ascent = FONT_BASE (font) + boff;
-  descent = FONT_DESCENT (font) - boff;
+  normal_char_ascent_descent (font, -1, &ascent, &descent);
 
   if (override)
     {
@@ -26196,8 +26290,9 @@ 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;
+  normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
+  it->ascent += font->baseline_offset;
+  it->descent -= font->baseline_offset;
   base_height = it->ascent + it->descent;
   base_width = font->average_width;
 
@@ -26384,6 +26479,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
            {
@@ -26511,8 +26622,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))
@@ -26583,8 +26704,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)
                {
@@ -26598,6 +26749,22 @@ x_produce_glyphs (struct it *it)
              it->nglyphs = 1;
            }
        }
+
+      if (FONT_TOO_HIGH (font))
+       {
+         int font_ascent, font_descent;
+
+         /* For very large fonts, where we ignore the declared font
+            dimensions, and go by per-character metrics instead,
+            don't let the row ascent and descent values (and the row
+            height computed from them) be smaller than the "normal"
+            character metrics.  This avoids unpleasant effects
+            whereby lines on display would change their heigh
+            depending on which characters are shown.  */
+         normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
+         it->max_ascent = max (it->max_ascent, font_ascent);
+         it->max_descent = max (it->max_descent, font_descent);
+       }
     }
   else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
     {
@@ -26664,9 +26831,10 @@ x_produce_glyphs (struct it *it)
          boff = font->baseline_offset;
          if (font->vertical_centering)
            boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
-         font_ascent = FONT_BASE (font) + boff;
-         font_descent = FONT_DESCENT (font) - boff;
-         font_height = FONT_HEIGHT (font);
+         normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
+         font_ascent +=  boff;
+         font_descent -= boff;
+         font_height = font_ascent + font_descent;
 
          cmp->font = font;
 
diff --git a/src/xftfont.c b/src/xftfont.c
index 0e8b876..a1846e8 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 691ede5..4d79450 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)
@@ -9405,7 +9410,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
-  int unit;
+  int unit, font_ascent, font_descent;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -9418,7 +9423,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int 
fontset)
   FRAME_FONT (f) = font;
   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   FRAME_COLUMN_WIDTH (f) = font->average_width;
-  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
+  get_font_ascent_descent (font, &font_ascent, &font_descent);
+  FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
 
 #ifndef USE_X_TOOLKIT
   FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]