emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] Changes to emacs/src/w32font.c,v


From: Jason Rumney
Subject: [Emacs-diffs] Changes to emacs/src/w32font.c,v
Date: Tue, 08 Apr 2008 13:52:21 +0000

CVSROOT:        /sources/emacs
Module name:    emacs
Changes by:     Jason Rumney <jasonr>   08/04/08 13:52:21

Index: w32font.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32font.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- w32font.c   4 Apr 2008 23:05:43 -0000       1.20
+++ w32font.c   8 Apr 2008 13:52:21 -0000       1.21
@@ -59,6 +59,9 @@
 extern Lisp_Object Qnone; /* reuse from w32fns.c  */
 static Lisp_Object Qstandard, Qsubpixel, Qnatural;
 
+/* languages */
+static Lisp_Object Qja, Qko, Qzh;
+
 /* scripts */
 static Lisp_Object Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
 static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
@@ -82,18 +85,18 @@
 /* Font spacing symbols - defined in font.c.  */
 extern Lisp_Object Qc, Qp, Qm;
 
-static void fill_in_logfont P_ ((FRAME_PTR f, LOGFONT *logfont,
-                                 Lisp_Object font_spec));
+static void fill_in_logfont P_ ((FRAME_PTR, LOGFONT *, Lisp_Object));
 
-static BYTE w32_antialias_type P_ ((Lisp_Object type));
-static Lisp_Object lispy_antialias_type P_ ((BYTE type));
+static BYTE w32_antialias_type P_ ((Lisp_Object));
+static Lisp_Object lispy_antialias_type P_ ((BYTE));
 
-static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE * sig));
-static int w32font_full_name P_ ((LOGFONT * font, Lisp_Object font_obj,
-                                  int pixel_size, char *name, int nbytes));
-static void recompute_cached_metrics P_ ((HDC dc, struct w32font_info * font));
+static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE *));
+static int w32font_full_name P_ ((LOGFONT *, Lisp_Object, int, char *, int));
+static void compute_metrics P_ ((HDC, struct w32font_info *, unsigned int,
+                                struct w32_metric_cache *));
+static void clear_cached_metrics P_ ((struct w32font_info *));
 
-static Lisp_Object w32_registry P_ ((LONG w32_charset, DWORD font_type));
+static Lisp_Object w32_registry P_ ((LONG, DWORD));
 
 /* EnumFontFamiliesEx callbacks.  */
 static int CALLBACK add_font_entity_to_list P_ ((ENUMLOGFONTEX *,
@@ -126,10 +129,10 @@
 
 /* Handles the problem that EnumFontFamiliesEx will not return all
    style variations if the font name is not specified.  */
-static void list_all_matching_fonts P_ ((struct font_callback_data *match));
+static void list_all_matching_fonts P_ ((struct font_callback_data *));
 
 /* From old font code in w32fns.c */
-char * w32_to_x_charset P_ ((int charset, char * matching));
+char * w32_to_x_charset P_ ((int, char *));
 
 
 static int
@@ -336,7 +339,8 @@
       /* Mark this font as not supporting glyph indices. This can happen
          on Windows9x, and maybe with non-Truetype fonts on NT etc.  */
       w32_font->glyph_idx = 0;
-      recompute_cached_metrics (dc, w32_font);
+      /* Clear metrics cache.  */
+      clear_cached_metrics (w32_font);
 
       return c;
     }
@@ -359,24 +363,13 @@
   HDC dc = NULL;
   struct frame * f;
   int total_width = 0;
-  WORD *wcode = alloca(nglyphs * sizeof (WORD));
+  WORD *wcode = NULL;
   SIZE size;
 
-  /* TODO: Frames can come and go, and their fonts outlive them. So we
-     can't cache the frame in the font structure.  Use selected_frame
-     until the API is updated to pass in a frame.  */
-  f = XFRAME (selected_frame);
-
   if (metrics)
     {
-      GLYPHMETRICS gm;
-      MAT2 transform;
       struct w32font_info *w32_font = (struct w32font_info *) font;
 
-      /* Set transform to the identity matrix.  */
-      bzero (&transform, sizeof (transform));
-      transform.eM11.value = 1;
-      transform.eM22.value = 1;
       metrics->width = 0;
       metrics->ascent = font->ascent;
       metrics->descent = font->descent;
@@ -384,65 +377,67 @@
 
       for (i = 0; i < nglyphs; i++)
         {
-          if (*(code + i) < 128)
-            {
-              /* Use cached metrics for ASCII.  */
-              struct font_metrics *char_metric
-                = &w32_font->ascii_metrics[*(code+i)];
+         struct w32_metric_cache *char_metric;
+         int block = *(code + i) / CACHE_BLOCKSIZE;
+         int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
 
-              /* If we couldn't get metrics when caching, use fallback.  */
-              if (char_metric->width == 0)
-                break;
+         if (block >= w32_font->n_cache_blocks)
+           {
+             if (!w32_font->cached_metrics)
+               w32_font->cached_metrics
+                 = xmalloc ((block + 1)
+                            * sizeof (struct w32_cached_metric *));
+             else
+               w32_font->cached_metrics
+                 = xrealloc (w32_font->cached_metrics,
+                             (block + 1)
+                             * sizeof (struct w32_cached_metric *));
+             bzero (w32_font->cached_metrics + w32_font->n_cache_blocks,
+                    ((block + 1 - w32_font->n_cache_blocks)
+                     * sizeof (struct w32_cached_metric *)));
+             w32_font->n_cache_blocks = block + 1;
+           }
 
-              metrics->lbearing = min (metrics->lbearing,
-                                       metrics->width + char_metric->lbearing);
-              metrics->rbearing = max (metrics->rbearing,
-                                       metrics->width + char_metric->rbearing);
-              metrics->width += char_metric->width;
+         if (!w32_font->cached_metrics[block])
+           {
+             w32_font->cached_metrics[block]
+               = xmalloc (CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+             bzero (w32_font->cached_metrics[block],
+                    CACHE_BLOCKSIZE * sizeof (struct font_metrics));
             }
-          else
+
+         char_metric = w32_font->cached_metrics[block] + pos_in_block;
+
+         if (char_metric->status == W32METRIC_NO_ATTEMPT)
             {
               if (dc == NULL)
                 {
+                 /* TODO: Frames can come and go, and their fonts
+                    outlive them. So we can't cache the frame in the
+                    font structure.  Use selected_frame until the API
+                    is updated to pass in a frame.  */
+                 f = XFRAME (selected_frame);
+  
                   dc = get_frame_dc (f);
                   old_font = SelectObject (dc, ((W32FontStruct *)
                                                 (font->font.font))->hfont);
                 }
-              if (GetGlyphOutlineW (dc, *(code + i),
-                                    GGO_METRICS
-                                      | w32_font->glyph_idx
-                                        ? GGO_GLYPH_INDEX : 0,
-                                    &gm, 0, NULL, &transform) != GDI_ERROR)
-                {
-                  int new_val = metrics->width + gm.gmBlackBoxX
-                    + gm.gmptGlyphOrigin.x;
-                  metrics->rbearing = max (metrics->rbearing, new_val);
-                  new_val = metrics->width + gm.gmptGlyphOrigin.x;
-                  metrics->lbearing = min (metrics->lbearing, new_val);
-                  metrics->width += gm.gmCellIncX;
+             compute_metrics (dc, w32_font, *(code + i), char_metric);
                 }
-              else
-                {
-                  if (w32_font->glyph_idx)
+
+         if (char_metric->status == W32METRIC_SUCCESS)
                     {
-                      /* Disable glyph indexing for this font, as we can't
-                         handle the metrics.  Abort this run, our recovery
-                         strategies rely on having unicode code points here.
-                         This will cause a glitch in display, but in practice,
-                         any problems should be caught when initialising the
-                         metrics cache.  */
-                      w32_font->glyph_idx = 0;
-                      recompute_cached_metrics (dc, w32_font);
-                      SelectObject (dc, old_font);
-                      release_frame_dc (f, dc);
-                      return 0;
+             metrics->lbearing = min (metrics->lbearing,
+                                      metrics->width + char_metric->lbearing);
+             metrics->rbearing = max (metrics->rbearing,
+                                      metrics->width + char_metric->rbearing);
+             metrics->width += char_metric->width;
                     }
-                  /* Rely on an estimate based on the overall font metrics.  */
+         else
+           /* If we couldn't get metrics for a char,
+              use alternative method.  */
                   break;
                 }
-            }
-        }
-
       /* If we got through everything, return.  */
       if (i == nglyphs)
         {
@@ -460,6 +455,8 @@
   /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
      fallback on other methods that will at least give some of the metric
      information.  */
+  if (!wcode) {
+    wcode = alloca (nglyphs * sizeof (WORD));
   for (i = 0; i < nglyphs; i++)
     {
       if (code[i] < 0x10000)
@@ -470,9 +467,15 @@
           wcode[i] = 0xffff;
         }
     }
-
+  }
   if (dc == NULL)
     {
+      /* TODO: Frames can come and go, and their fonts outlive
+        them. So we can't cache the frame in the font structure.  Use
+        selected_frame until the API is updated to pass in a
+        frame.  */
+      f = XFRAME (selected_frame);
+
       dc = get_frame_dc (f);
       old_font = SelectObject (dc, ((W32FontStruct *)
                                     (font->font.font))->hfont);
@@ -792,8 +795,8 @@
 
   w32_font->glyph_idx = ETO_GLYPH_INDEX;
 
-  /* Cache ASCII metrics.  */
-  recompute_cached_metrics (dc, w32_font);
+  w32_font->cached_metrics = NULL;
+  w32_font->n_cache_blocks = 0;
 
   SelectObject (dc, old_font);
   release_frame_dc (f, dc);
@@ -1226,6 +1229,36 @@
                     return 0;
                 }
             }
+         else if (EQ (key, QClanguage) && SYMBOLP (val))
+           {
+             /* Just handle the CJK languages here, as the language
+                parameter is used to select a font with appropriate
+                glyphs in the cjk unified ideographs block. Other fonts
+                support for a language can be solely determined by
+                its character coverage.  */
+             if (EQ (val, Qja))
+               {
+                 if (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET)
+                   return 0;
+               }
+             else if (EQ (val, Qko))
+               {
+                 if (font->ntmTm.tmCharSet != HANGUL_CHARSET
+                     && font->ntmTm.tmCharSet != JOHAB_CHARSET)
+                   return 0;
+               }
+             else if (EQ (val, Qzh))
+               {
+                 if (font->ntmTm.tmCharSet != GB2312_CHARSET
+                     && font->ntmTm.tmCharSet != CHINESEBIG5_CHARSET)
+               return 0;
+               }
+             else
+               /* Any other language, we don't recognize it. Fontset
+                  spec should have a fallback, as some backends do
+                  not recognize language at all.  */
+               return 0;
+           }
           else if (EQ (key, QCotf) && CONSP (val))
            {
              /* OTF features only supported by the uniscribe backend.  */
@@ -1345,8 +1378,6 @@
     return ANSI_CHARSET;
   else if (SYMBOLP (charset))
     return x_to_w32_charset (SDATA (SYMBOL_NAME (charset)));
-  else if (STRINGP (charset))
-    return x_to_w32_charset (SDATA (charset));
   else
     return DEFAULT_CHARSET;
 }
@@ -1449,8 +1480,6 @@
            user input.  */
       else if (SYMBOLP (tmp))
         strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE);
-      else if (STRINGP (tmp))
-        strncpy (logfont->lfFaceName, SDATA (tmp), LF_FACESIZE);
     }
 
   tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
@@ -1550,10 +1579,10 @@
       families = CDR (families);
       if (NILP (family))
         continue;
-      else if (STRINGP (family))
-        name = SDATA (family);
-      else
+      else if (SYMBOLP (family))
         name = SDATA (SYMBOL_NAME (family)); 
+      else
+       continue;
 
       strncpy (match_data->pattern.lfFaceName, name, LF_FACESIZE);
       match_data->pattern.lfFaceName[LF_FACESIZE - 1] = '\0';
@@ -1807,38 +1836,55 @@
 }
 
 
-static void
-recompute_cached_metrics (dc, w32_font)
+static void compute_metrics (dc, w32_font, code, metrics)
      HDC dc;
      struct w32font_info *w32_font;
+     unsigned int code;
+     struct w32_metric_cache *metrics;
 {
   GLYPHMETRICS gm;
   MAT2 transform;
-  unsigned int i;
+  unsigned int options = GGO_METRICS;
+
+  if (w32_font->glyph_idx)
+    options |= GGO_GLYPH_INDEX;
 
   bzero (&transform, sizeof (transform));
   transform.eM11.value = 1;
   transform.eM22.value = 1;
   
-  for (i = 0; i < 128; i++)
-    {
-      struct font_metrics* char_metric = &w32_font->ascii_metrics[i];
-      unsigned int options = GGO_METRICS;
-      if (w32_font->glyph_idx)
-        options |= GGO_GLYPH_INDEX;
-
-      if (GetGlyphOutlineW (dc, i, options, &gm, 0, NULL, &transform)
+  if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
           != GDI_ERROR)
         {
-          char_metric->lbearing = gm.gmptGlyphOrigin.x;
-          char_metric->rbearing = gm.gmBlackBoxX + gm.gmptGlyphOrigin.x;
-          char_metric->width = gm.gmCellIncX;
+      metrics->lbearing = gm.gmptGlyphOrigin.x;
+      metrics->rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
+      metrics->width = gm.gmCellIncX;
+      metrics->status = W32METRIC_SUCCESS;
         }
       else
-        char_metric->width = 0;
+    {
+      if (w32_font->glyph_idx)
+       {
+         /* Can't use glyph indexes after all.
+            Avoid it in future, and clear any metrics that were based on
+            glyph indexes.  */
+         w32_font->glyph_idx = 0;
+         clear_cached_metrics (w32_font);
+       }
+      metrics->status = W32METRIC_FAIL;
     }
 }
 
+static void
+clear_cached_metrics (w32_font)
+     struct w32font_info *w32_font;
+{
+  int i;
+  for (i = 0; i < w32_font->n_cache_blocks; i++)
+    bzero (w32_font->cached_metrics[i],
+          CACHE_BLOCKSIZE * sizeof (struct font_metrics));
+}
+
 struct font_driver w32font_driver =
   {
     0, /* Qgdi */
@@ -1898,6 +1944,11 @@
   DEFSYM (Qsubpixel, "subpixel");
   DEFSYM (Qnatural, "natural");
 
+  /* Languages  */
+  DEFSYM (Qja, "ja");
+  DEFSYM (Qko, "ko");
+  DEFSYM (Qzh, "zh");
+
   /* Scripts  */
   DEFSYM (Qlatin, "latin");
   DEFSYM (Qgreek, "greek");




reply via email to

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