]> code.delx.au - gnu-emacs/commitdiff
Teach MS-Windows font back-end return per-glyph ascent/descent
authorEli Zaretskii <eliz@gnu.org>
Tue, 26 May 2015 15:29:40 +0000 (18:29 +0300)
committerEli Zaretskii <eliz@gnu.org>
Tue, 26 May 2015 15:29:40 +0000 (18:29 +0300)
* src/w32font.h (struct w32_metric_cache): Add ascent and descent
values.

* src/w32font.c (w32font_text_extents): Compute, cache, and
accumulate per-glyph ascent and descent values, instead of copying
global values from the font.  If the values are not available from
the font data, i.e., non-TTF fonts, fall back on font-global values.
(compute_metrics): Compute and return per-glyph ascent and descent
values, if returned by GetGlyphOutlineW, falling back on
font-global values.  (Bug#20628)

* src/w32term.c (w32_draw_rectangle): Add 1 pixel to width and
height of rectangle to be drawn, to be compatible with
XDrawRectangle.  Fixes glyphless-char display as hex codes in a
box, when per-glyph ascent/descent values are used.

src/w32font.c
src/w32font.h
src/w32term.c

index 77994593c6dbed6b818fe238747fcf93ddac38da..6306a8460e76efb32cdfee2f4a599376dcdaf0b0 100644 (file)
@@ -439,14 +439,13 @@ w32font_text_extents (struct font *font, unsigned *code,
   int total_width = 0;
   WORD *wcode;
   SIZE size;
+  bool first;
 
   struct w32font_info *w32_font = (struct w32font_info *) font;
 
   memset (metrics, 0, sizeof (struct font_metrics));
-  metrics->ascent = font->ascent;
-  metrics->descent = font->descent;
 
-  for (i = 0; i < nglyphs; i++)
+  for (i = 0, first = true; i < nglyphs; i++)
     {
       struct w32_metric_cache *char_metric;
       int block = *(code + i) / CACHE_BLOCKSIZE;
@@ -495,11 +494,24 @@ w32font_text_extents (struct font *font, unsigned *code,
 
       if (char_metric->status == W32METRIC_SUCCESS)
        {
-         metrics->lbearing = min (metrics->lbearing,
-                                  metrics->width + char_metric->lbearing);
-         metrics->rbearing = max (metrics->rbearing,
-                                  metrics->width + char_metric->rbearing);
+         if (first)
+           {
+             metrics->lbearing = char_metric->lbearing;
+             metrics->rbearing = char_metric->rbearing;
+             metrics->width    = 0;
+             metrics->ascent   = char_metric->ascent;
+             metrics->descent  = char_metric->descent;
+             first = false;
+           }
+         if (metrics->lbearing > char_metric->lbearing)
+           metrics->lbearing = char_metric->lbearing;
+         if (metrics->rbearing < char_metric->rbearing)
+           metrics->rbearing = char_metric->rbearing;
          metrics->width += char_metric->width;
+         if (metrics->ascent < char_metric->ascent)
+           metrics->ascent = char_metric->ascent;
+         if (metrics->descent < char_metric->descent)
+           metrics->descent = char_metric->descent;
        }
       else
        /* If we couldn't get metrics for a char,
@@ -574,6 +586,8 @@ w32font_text_extents (struct font *font, unsigned *code,
   metrics->width = total_width - w32_font->metrics.tmOverhang;
   metrics->lbearing = 0;
   metrics->rbearing = total_width;
+  metrics->ascent = font->ascent;
+  metrics->descent = font->descent;
 
   /* Restore state and release DC.  */
   SelectObject (dc, old_font);
@@ -2415,6 +2429,8 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
       metrics->lbearing = gm.gmptGlyphOrigin.x;
       metrics->rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
       metrics->width = gm.gmCellIncX;
+      metrics->ascent = gm.gmptGlyphOrigin.y;
+      metrics->descent = gm.gmBlackBoxY - gm.gmptGlyphOrigin.y;
       metrics->status = W32METRIC_SUCCESS;
     }
   else if (get_char_width_32_w (dc, code, code, &width) != 0)
@@ -2422,6 +2438,8 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
       metrics->lbearing = 0;
       metrics->rbearing = width;
       metrics->width = width;
+      metrics->ascent = w32_font->font.ascent;
+      metrics->descent = w32_font->font.descent;
       metrics->status = W32METRIC_SUCCESS;
     }
   else
index 0ad01254be9d74e009ef630f9e01e28b4c0abc47..6365cb3fa234a58fdcf3bb2ee34b8eabf89d0c5f 100644 (file)
@@ -37,7 +37,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 struct w32_metric_cache
 {
-  short lbearing, rbearing, width;
+  short lbearing, rbearing, width, ascent, descent;
   unsigned char status;
 };
 
index 089c43c8a26d625659fb4f60f52e2433311ecebd..0bc2e98021477f2ff39e1d0d562de3e5c29fa36b 100644 (file)
@@ -401,7 +401,13 @@ w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
   oldhb = SelectObject (hdc, hb);
   oldhp = SelectObject (hdc, hp);
 
-  Rectangle (hdc, x, y, x + width, y + height);
+  /* We enlarge WIDTH and HEIGHT by 1 to be bug-compatible to the
+     brain-dead design of XDrawRectangle, which draws a rectangle that
+     is 1 pixel wider and higher than its arguments WIDTH and HEIGHT.
+     This allows us to keep the code that calls this function similar
+     to the corresponding code in xterm.c.  For the details, see
+     http://lists.gnu.org/archives/html/emacs-devel/2014-10/msg00546.html.  */
+  Rectangle (hdc, x, y, x + width + 1, y + height + 1);
 
   SelectObject (hdc, oldhb);
   SelectObject (hdc, oldhp);