changeset 32720:8530cd0a7455

(w32_per_char_metric): Remove HDC argument. Use cached information in emulated XFontStruct to handle common cases quickly. Do not allocate XCharStruct for return. (w32_native_per_char_metric): New function. (w32_bdf_per_char_metric): Fill in supplied XCharStruct instead of allocating one. (x_produce_glyphs): Don't get an HDC. Change calls to w32_per_char_metric to match arg change above. Remove calls to free results. (w32_get_glyph_overhangs): Ditto. (w32_cache_char_metrics): New function.
author Andrew Innes <andrewi@gnu.org>
date Sat, 21 Oct 2000 13:26:41 +0000
parents e6e8694bf692
children 0574ffc14f77
files src/w32term.c
diffstat 1 files changed, 130 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32term.c	Sat Oct 21 13:24:14 2000 +0000
+++ b/src/w32term.c	Sat Oct 21 13:26:41 2000 +0000
@@ -79,15 +79,6 @@
   ZV_LINE_BITMAP
 };
 
-enum w32_char_font_type
-{
-  UNKNOWN_FONT,
-  ANSI_FONT,
-  UNICODE_FONT,
-  BDF_1D_FONT,
-  BDF_2D_FONT
-};
-
 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
    be Word aligned.  For some reason they are horizontally reflected
    compared to how they appear on X, so changes in xterm.c should be
@@ -189,6 +180,8 @@
 
 extern int w32_codepage_for_font (char *fontname);
 
+extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
+					unsigned char *text, int dim);
 extern Lisp_Object Vwindow_system;
 
 #define x_any_window_to_frame x_window_to_frame
@@ -1101,7 +1094,7 @@
                                                        int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
 						      int, wchar_t *, int));
-static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
+static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
                                              wchar_t *,
                                              enum w32_char_font_type));
 static enum w32_char_font_type
@@ -1130,15 +1123,15 @@
    If CHAR2B is not contained in FONT, the font's default character
    metric is returned. */
 
-static XCharStruct *
-w32_bdf_per_char_metric (font, char2b, dim)
+static int
+w32_bdf_per_char_metric (font, char2b, dim, pcm)
      XFontStruct *font;
      wchar_t *char2b;
      int dim;
+     XCharStruct * pcm;
 {
   glyph_metric * bdf_metric;
   char buf[2];
-  XCharStruct * pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
 
   if (dim == 1)
     buf[0] = (char)char2b;
@@ -1158,42 +1151,32 @@
                     - (bdf_metric->bbox + bdf_metric->bbw);
       pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
       pcm->descent = bdf_metric->bboy;
-    }
-  else
-    {
-      xfree (pcm);
-      return NULL;
-    }
-  return pcm;
-}
-
-
-static XCharStruct *
-w32_per_char_metric (hdc, font, char2b, font_type)
-     HDC hdc;
+
+      return 1;
+    }
+  return 0;
+}
+
+
+static int
+w32_native_per_char_metric (font, char2b, font_type, pcm)
      XFontStruct *font;
      wchar_t *char2b;
      enum w32_char_font_type font_type;
+     XCharStruct * pcm;
 {
   /* NTEMACS_TODO: Use GetGlyphOutline where possible (no Unicode
      version on W9x) */
 
-  /* The result metric information.  */
-  XCharStruct *pcm;
-  BOOL retval;
+  HDC hdc = GetDC (NULL);
+  HFONT old_font;
+  BOOL retval = FALSE;
 
   xassert (font && char2b);
-  xassert (font_type != UNKNOWN_FONT);
-
-  if (font_type == BDF_1D_FONT)
-    return w32_bdf_per_char_metric (font, char2b, 1);
-  else if (font_type == BDF_2D_FONT)
-    return w32_bdf_per_char_metric (font, char2b, 2);
-
-  pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
-
-  if (font->hfont)
-    SelectObject (hdc, font->hfont);
+  xassert (font->hfont);
+  xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
+
+  old_font = SelectObject (hdc, font->hfont);
 
   if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
     {
@@ -1201,7 +1184,7 @@
 
       if (font_type == UNICODE_FONT)
 	retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
-      else if (font_type == ANSI_FONT)
+      else
 	retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
 
       if (retval)
@@ -1209,61 +1192,119 @@
 	  pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
 	  pcm->lbearing = char_widths.abcA;
 	  pcm->rbearing = pcm->width - char_widths.abcC;
+	  pcm->ascent = FONT_BASE (font);
+	  pcm->descent = FONT_DESCENT (font);
 	}
+    }
+
+  if (!retval)
+    {
+      /* Either font is not a True-type font, or GetCharABCWidthsW
+	 failed (it is not supported on Windows 9x for instance), so we
+	 can't determine the full info we would like.  All is not lost
+	 though - we can call GetTextExtentPoint32 to get rbearing and
+	 deduce width based on the font's per-string overhang.  lbearing
+	 is assumed to be zero.  */
+      SIZE sz;
+
+      if (font_type == UNICODE_FONT)
+	retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
       else
+	retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
+
+      if (retval)
 	{
-	  /* Windows 9x does not implement GetCharABCWidthsW, so if that
-	     failed, try GetTextExtentPoint32W, which is implemented and
-	     at least gives us some of the info we are after (total
-	     character width). */
-	  SIZE sz;
-
-	  if (font_type == UNICODE_FONT)
-	    retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
-
-	  if (retval)
-	    {
-	      pcm->width = sz.cx;
-	      pcm->rbearing = sz.cx;
-	      pcm->lbearing = 0;
-	    }
-	  else
-	    {
-	      xfree (pcm);
-	      return NULL;
-	    }
+	  pcm->width = sz.cx - font->tm.tmOverhang;
+	  pcm->rbearing = sz.cx;
+	  pcm->lbearing = 0;
+	  pcm->ascent = FONT_BASE (font);
+	  pcm->descent = FONT_DESCENT (font);
 	}
     }
+
+
+  if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
+    {
+      retval = FALSE;
+    }
+
+  SelectObject (hdc, old_font);
+  ReleaseDC (NULL, hdc);
+
+  return retval;
+}
+
+
+static XCharStruct *
+w32_per_char_metric (font, char2b, font_type)
+     XFontStruct *font;
+     wchar_t *char2b;
+     enum w32_char_font_type font_type;
+{
+  /* The result metric information.  */
+  XCharStruct *pcm;
+  BOOL retval;
+
+  xassert (font && char2b);
+  xassert (font_type != UNKNOWN_FONT);
+
+  /* Handle the common cases quickly.  */
+  if (font->per_char == NULL)
+    /* TODO: determine whether char2b exists in font?  */
+    return &font->max_bounds;
+  else if (*char2b < 128)
+    return &font->per_char[*char2b];
+
+  pcm = &font->scratch;
+
+  if (font_type == BDF_1D_FONT)
+    retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
+  else if (font_type == BDF_2D_FONT)
+    retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
+  else
+    retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
+
+  if (retval)
+    return pcm;
+
+  return NULL;
+}
+
+void
+w32_cache_char_metrics (font)
+     XFontStruct *font;
+{
+  wchar_t char2b = L'x';
+
+  /* Cache char metrics for the common cases.  */
+  if (font->bdf)
+    {
+      /* TODO: determine whether font is fixed-pitch.  */
+      w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds);
+    }
   else
     {
-      /* Do our best to deduce the desired metrics data for non-Truetype
-         fonts (generally, raster fonts).  */
-      INT char_width;
-
-      retval = GetCharWidth (hdc, *char2b, *char2b, &char_width);
-      if (retval)
+      if ((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
 	{
-	  pcm->width = char_width;
-	  pcm->rbearing = char_width;
-	  pcm->lbearing = 0;
+	  /* Font is not fixed pitch, so cache per_char info for the
+             ASCII characters.  It would be much more work, and probably
+             not worth it, to cache other chars, since we may change
+             between using Unicode and ANSI text drawing functions at
+             run-time.  */
+	  int i;
+
+	  font->per_char = xmalloc (128 * sizeof(XCharStruct));
+	  for (i = 0; i < 128; i++)
+	    {
+	      char2b = i;
+	      w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+					  &font->per_char[i]);
+	    }
 	}
       else
-	{
-	  xfree (pcm);
-	  return NULL;
-	}
-    }
-
-  pcm->ascent = FONT_BASE (font);
-  pcm->descent = FONT_DESCENT (font);
-
-  if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
-    {
-      xfree (pcm);
-      return NULL;
-    }
-
-  return pcm;
+	w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+				    &font->max_bounds);
+    }
 }
 
 
@@ -1893,7 +1934,6 @@
       int font_not_found_p;
       struct font_info *font_info;
       int boff;                 /* baseline offset */
-      HDC hdc;
       /* We may change it->multibyte_p upon unibyte<->multibyte
 	 conversion.  So, save the current value now and restore it
 	 later.
@@ -1906,8 +1946,6 @@
       */
       int saved_multibyte_p = it->multibyte_p;
 
-      hdc = get_frame_dc (it->f);
-
       /* Maybe translate single-byte characters to multibyte, or the
          other way.  */
       it->char_to_display = it->c;
@@ -1955,9 +1993,6 @@
 	    boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
 	}
 
-      if (font->hfont)
-        SelectObject (hdc, font->hfont);
-
       if (it->char_to_display >= ' '
 	  && (!it->multibyte_p || it->char_to_display < 128))
 	{
@@ -1966,7 +2001,7 @@
 
 	  it->nglyphs = 1;
 
-          pcm = w32_per_char_metric (hdc, font, &char2b,
+          pcm = w32_per_char_metric (font, &char2b,
                                      font->bdf ? BDF_1D_FONT : ANSI_FONT);
 	  it->ascent = FONT_BASE (font) + boff;
 	  it->descent = FONT_DESCENT (font) - boff;
@@ -2034,8 +2069,6 @@
 		 glyph row.  This is used to optimize X output code.  */
 	      if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
 		it->glyph_row->contains_overlapping_glyphs_p = 1;
-              if (pcm)
-                xfree (pcm);
 	    }
 	}
       else if (it->char_to_display == '\n')
@@ -2094,7 +2127,7 @@
           else
             type = UNICODE_FONT;
 
-          pcm = w32_per_char_metric (hdc, font, &char2b, type);
+          pcm = w32_per_char_metric (font, &char2b, type);
 
 	  if (font_not_found_p || !pcm)
 	    {
@@ -2141,11 +2174,7 @@
   
 	  if (it->glyph_row)
 	    x_append_glyph (it);
-
-          if (pcm)
-            xfree (pcm);
 	}
-      release_frame_dc (it->f, hdc);
       it->multibyte_p = saved_multibyte_p;
     }
   else if (it->what == IT_COMPOSITION)
@@ -2798,14 +2827,13 @@
       font = face->font;
 
       if (font
-          && (pcm = w32_per_char_metric (hdc, font, &char2b,
+          && (pcm = w32_per_char_metric (font, &char2b,
                                          glyph->w32_font_type)))
 	{
 	  if (pcm->rbearing > pcm->width)
 	    *right = pcm->rbearing - pcm->width;
 	  if (pcm->lbearing < 0)
 	    *left = -pcm->lbearing;
-          xfree (pcm);
 	}
     }
 }