]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix display of glyphless characters with problematic fonts
authorEli Zaretskii <eliz@gnu.org>
Thu, 28 May 2015 17:23:41 +0000 (20:23 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 28 May 2015 17:23:41 +0000 (20:23 +0300)
* src/w32term.c (x_draw_glyph_string_background): Force redraw of
glyph string background also when the font in use claims
preposterously large global height value.  Helps to remove
artifacts left from previous displays when glyphless characters
are displayed as hex code in a box.
* src/xterm.c (x_draw_glyph_string_background): Force redraw of
glyph string background also when the font in use claims
preposterously large global height value.  Helps to remove
artifacts left from previous displays when glyphless characters
are displayed as hex code in a box.
* src/w32font.c (w32font_draw): Fix background drawing for
glyphless characters that display as acronyms or hex codes in a
box.
* src/xftfont.c (xftfont_draw): Fix background drawing for
glyphless characters that display as acronyms or hex codes in a
box.
* src/xdisp.c (produce_glyphless_glyph): Compute reasonable values
for it->ascent and it->descent when the font claims preposterously
large global values.
(FONT_TOO_HIGH): Move from here...
* src/dispextern.h (FONT_TOO_HIGH): ...to here.

src/dispextern.h
src/w32font.c
src/w32term.c
src/xdisp.c
src/xftfont.c
src/xterm.c

index d9d4d2300fa9286ab3361a85401d479b2bac0813..1537d44330d8e4384e1bf13ce31bc00a7048399c 100644 (file)
@@ -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)
+
 \f
 /***********************************************************************
                                Faces
index 6306a8460e76efb32cdfee2f4a599376dcdaf0b0..1c2f9665037849322907108d02a4199e057a5455 100644 (file)
@@ -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);
     }
index 0bc2e98021477f2ff39e1d0d562de3e5c29fa36b..9c4f28fa2d466e0cfca46522a6ff6ddb8874690e 100644 (file)
@@ -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)
index a1b7cf1438f3ea116293dd27561d5cc7b1e3e957..ed430a424a1408e93ce993c39101e303808c3b2e 100644 (file)
@@ -25296,12 +25296,6 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
       }                                                        \
   }
 
-/* A heuristic test for fonts that claim they need a preposterously
-   large vertical space.  The heuristics is in the factor of 3.  We
-   ignore the ascent and descent values reported by such fonts, and
-   instead go by the values reported for individual glyphs.  */
-#define FONT_TOO_HIGH(ft)  ((ft)->ascent + (ft)->descent > 3*(ft)->pixel_size)
-
 /* Store one glyph for IT->char_to_display in IT->glyph_row.
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
 
@@ -26230,8 +26224,28 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
      ASCII face.  */
   face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
   font = face->font ? face->font : FRAME_FONT (it->f);
-  it->ascent = FONT_BASE (font) + font->baseline_offset;
-  it->descent = FONT_DESCENT (font) - font->baseline_offset;
+  it->ascent = FONT_BASE (font);
+  it->descent = FONT_DESCENT (font);
+  /* Attempt to fix box height for fonts that claim preposterously
+     large height.  */
+  if (FONT_TOO_HIGH (font))
+    {
+      XChar2b char2b;
+
+      /* Get metrics of a reasonably sized ASCII character.  */
+      if (get_char_glyph_code ('{', font, &char2b))
+       {
+         struct font_metrics *pcm = get_per_char_metric (font, &char2b);
+
+         if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
+           {
+             it->ascent = pcm->ascent;
+             it->descent = pcm->descent;
+           }
+       }
+    }
+  it->ascent += font->baseline_offset;
+  it->descent -= font->baseline_offset;
   base_height = it->ascent + it->descent;
   base_width = font->average_width;
 
index 0e8b876f1d33bd1cb3e90c522532254360a95ba6..a1846e8d4619ac572d2d07b806f05dbfc5e43133 100644 (file)
@@ -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)
index 4f5dfed9ae8f37483deebe6ead4cf78a57893abf..58563ff35d0b645ee425db121b77f1e6f25c293f 100644 (file)
@@ -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)