changeset 102991:18e317a87f12

(Qja, Qko): Don't make them static. (enum ftfont_cache_for): New enum. (fc_charset_table): Undo the previous change. (ftfont_get_latin1_charset): Delete it. (ftfont_pattern_entity): Check cache by ftfont_lookup_cache. Set FONT_SIZE_INDEX of the entity to 0 for a scalable font. For a non-scarable font, try to get AVERAGE_WIDTH. (ftfont_lookup_cache): Argument FOR-FACE is changed to CACHE_FOR. Change ft_face_cache from a list of a hash-table. Don't check `ja' and `ko' adstyle here. (ftfont_get_fc_charset): Call ftfont_lookup_cache with FTFONT_CACHE_FOR_CHARET. (ftfont_get_charset): Undo the previous change. (ftfont_open): Call ftfont_lookup_cache with FTFONT_CACHE_FOR_FACE. (ftfont_close): Likewise. (ftfont_has_char): Special handling of `ja' and `ko' adstyle.
author Kenichi Handa <handa@m17n.org>
date Thu, 16 Apr 2009 01:38:07 +0000
parents a706504f064e
children 64cdf8a83bdd
files src/ftfont.c
diffstat 1 files changed, 93 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/ftfont.c	Thu Apr 16 01:32:44 2009 +0000
+++ b/src/ftfont.c	Thu Apr 16 01:38:07 2009 +0000
@@ -44,7 +44,7 @@
 static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
 
 /* Special ADSTYLE properties to avoid fonts used for Latin characters.  */
-static Lisp_Object Qja, Qko;
+Lisp_Object Qja, Qko;
 
 /* Flag to tell if FcInit is already called or not.  */
 static int fc_initialized;
@@ -74,11 +74,19 @@
   int index;
 };
 
+enum ftfont_cache_for
+  {
+    FTFONT_CACHE_FOR_FACE,
+    FTFONT_CACHE_FOR_CHARSET,
+    FTFONT_CACHE_FOR_ENTITY
+  };
+
 static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object));
 
 static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
 						      FcPattern *));
-static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object, int));
+static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object,
+					    enum ftfont_cache_for));
 
 Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
 
@@ -95,7 +103,7 @@
   /* set on demand */
   FcCharSet *fc_charset;
 } fc_charset_table[] =
-  { { "iso8859-1", { } },	/* ftfont_get_latin1_charset handles it. */
+  { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
     { "iso8859-2", { 0x00A0, 0x010E }},
     { "iso8859-3", { 0x00A0, 0x0108 }},
     { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
@@ -135,29 +143,6 @@
     { NULL }
   };
 
-/* Return a FcCharSet for iso8859-1 from fc_charset_table[0].  If the
-   charset is not yet ready, create it. */
-static FcCharSet *
-ftfont_get_latin1_charset ()
-{
-  FcCharSet *cs;
-  FcChar32 c;
-
-  if (fc_charset_table[0].fc_charset)
-    return fc_charset_table[0].fc_charset;
-  cs = FcCharSetCreate ();
-  if (! cs)
-    return NULL;
-  for (c = 33; c <= 0xFF; c++)
-    {
-      FcCharSetAddChar (cs, c);
-      if (c == 0x7E)
-	c = 0xA0;
-    }
-  fc_charset_table[0].fc_charset = cs;
-  return cs;
-}
-
 extern Lisp_Object Qc, Qm, Qp, Qd;
 
 /* Dirty hack for handing ADSTYLE property.
@@ -206,7 +191,7 @@
      FcPattern *p;
      Lisp_Object extra;
 {
-  Lisp_Object entity;
+  Lisp_Object key, cache, entity;
   char *file, *str;
   int index;
   int numeric;
@@ -218,7 +203,14 @@
   if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch)
     return Qnil;
 
+  key = Fcons (make_unibyte_string ((char *) file, strlen ((char *) file)),
+	       make_number (index));
+  cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
+  entity = XCAR (cache);
+  if (! NILP (entity))
+    return entity;
   entity = font_make_entity ();
+  XSETCAR (cache, entity);
 
   ASET (entity, FONT_TYPE_INDEX, Qfreetype);
   ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
@@ -244,12 +236,7 @@
     }
   if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
     {
-      Lisp_Object adstyle;
-
       ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
-      /* As this font has PIXEL_SIZE property, parhaps this is a BDF
-	 or PCF font. */ 
-      ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
     }
   else
     ASET (entity, FONT_SIZE_INDEX, make_number (0));
@@ -262,13 +249,31 @@
     }
   if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
       && b == FcTrue)
-    ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
+    {
+      ASET (entity, FONT_SIZE_INDEX, make_number (0));
+      ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
+    }
+  else
+    {
+      /* As this font is not scalable, parhaps this is a BDF or PCF
+	 font. */ 
+      FT_Face ft_face;
+
+      ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
+      if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
+	  && FT_New_Face (ft_library, file, index, &ft_face) == 0)
+	{
+	  BDF_PropertyRec rec;
+
+	  if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
+	      && rec.type == BDF_PROPERTY_TYPE_INTEGER)
+	    ASET (entity, FONT_AVGWIDTH_INDEX, make_number (rec.u.integer));
+	  FT_Done_Face (ft_face);
+	}
+    }
 
   ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
-  font_put_extra (entity, QCfont_entity,
-		  Fcons (make_unibyte_string ((char *) file,
-					      strlen ((char *) file)),
-			 make_number (index)));
+  font_put_extra (entity, QCfont_entity, key);
   return entity;
 }
 
@@ -335,9 +340,9 @@
 };
 
 static Lisp_Object
-ftfont_lookup_cache (key, for_face)
+ftfont_lookup_cache (key, cache_for)
      Lisp_Object key;
-     int for_face;
+     enum ftfont_cache_for cache_for;
 {
   Lisp_Object cache, val, entity;
   struct ftfont_cache_data *cache_data;
@@ -352,29 +357,45 @@
   else
     entity = Qnil;
 
-  cache = assoc_no_quit (key, ft_face_cache);
+  if (NILP (ft_face_cache))
+    cache = Qnil;
+  else
+    cache = Fgethash (key, ft_face_cache, Qnil);
   if (NILP (cache))
     {
+      if (NILP (ft_face_cache))
+	{
+	  Lisp_Object args[2];
+
+	  args[0] = QCtest;
+	  args[1] = Qequal;
+	  ft_face_cache = Fmake_hash_table (2, args);
+	}
       cache_data = xmalloc (sizeof (struct ftfont_cache_data));
       cache_data->ft_face = NULL;
       cache_data->fc_charset = NULL;
       val = make_save_value (NULL, 0);
       XSAVE_VALUE (val)->integer = 0;
       XSAVE_VALUE (val)->pointer = cache_data;
-      cache = Fcons (key, val);
-      ft_face_cache = Fcons (cache, ft_face_cache);
+      cache = Fcons (Qnil, val);
+      Fputhash (key, cache, ft_face_cache);
     }
   else
     {
       val = XCDR (cache);
       cache_data = XSAVE_VALUE (val)->pointer;
     }
-  if (for_face ? ! cache_data->ft_face : ! cache_data->fc_charset)
+
+  if (cache_for == FTFONT_CACHE_FOR_ENTITY)
+    return cache;
+
+  if (cache_for == FTFONT_CACHE_FOR_FACE
+      ? ! cache_data->ft_face : ! cache_data->fc_charset)
     {
       char *filename = (char *) SDATA (XCAR (key));
       int index = XINT (XCDR (key));
 
-      if (for_face)
+      if (cache_for == FTFONT_CACHE_FOR_FACE)
 	{
 	  if (! ft_library
 	      && FT_Init_FreeType (&ft_library) != 0)
@@ -400,31 +421,11 @@
 	  fontset = FcFontList (NULL, pat, objset);
 	  if (! fontset)
 	    goto finish;
-	  if (fontset && fontset->nfont > 0)
-	    {
-	      if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
+	  if (fontset && fontset->nfont > 0
+	      && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
 				       &charset)
-		  == FcResultMatch)
-		{
-		  /* Dirty hack.  Fonts of "ja" and "ko" adstyle are
-		     not suitable for Latin characters.  */
-		  if (! NILP (entity)
-		      && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja)
-			  || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko)))
-		    {
-		      FcCharSet *latin1 = ftfont_get_latin1_charset ();
-
-		      if (! latin1)
-			goto finish;
-		      cache_data->fc_charset = FcCharSetSubtract (charset,
-								  latin1);
-		    }
-		  else
-		    cache_data->fc_charset = FcCharSetCopy (charset);
-		}
-	      else
-		cache_data->fc_charset = FcCharSetCreate ();
-	    }
+		  == FcResultMatch))
+	    cache_data->fc_charset = FcCharSetCopy (charset);
 	  else
 	    cache_data->fc_charset = FcCharSetCreate ();
 
@@ -447,7 +448,7 @@
   Lisp_Object val, cache;
   struct ftfont_cache_data *cache_data;
 
-  cache = ftfont_lookup_cache (entity, 0);
+  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
   val = XCDR (cache);
   cache_data = XSAVE_VALUE (val)->pointer;
   return cache_data->fc_charset;
@@ -582,23 +583,18 @@
     return -1;
   if (! fc_charset_table[i].fc_charset)
     {
-      if (i == 0)
-	ftfont_get_latin1_charset ();
-      else
-	{
-	  FcCharSet *charset = FcCharSetCreate ();
-	  int *uniquifier = fc_charset_table[i].uniquifier;
+      FcCharSet *charset = FcCharSetCreate ();
+      int *uniquifier = fc_charset_table[i].uniquifier;
 
-	  if (! charset)
+      if (! charset)
+	return -1;
+      for (j = 0; uniquifier[j]; j++)
+	if (! FcCharSetAddChar (charset, uniquifier[j]))
+	  {
+	    FcCharSetDestroy (charset);
 	    return -1;
-	  for (j = 0; uniquifier[j]; j++)
-	    if (! FcCharSetAddChar (charset, uniquifier[j]))
-	      {
-		FcCharSetDestroy (charset);
-		return -1;
-	      }
-	  fc_charset_table[i].fc_charset = charset;
-	}
+	  }
+      fc_charset_table[i].fc_charset = charset;
     }
   return i;
 }
@@ -1170,7 +1166,7 @@
   if (! CONSP (val))
     return Qnil;
   val = XCDR (val);
-  cache = ftfont_lookup_cache (entity, 1);
+  cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
   if (NILP (cache))
     return Qnil;
   filename = XCAR (val);
@@ -1297,7 +1293,7 @@
   Lisp_Object val, cache;
 
   val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
-  cache = ftfont_lookup_cache (val, 1);
+  cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
   xassert (CONSP (cache));
   val = XCDR (cache);
   (XSAVE_VALUE (val)->integer)--;
@@ -1321,6 +1317,17 @@
      Lisp_Object font;
      int c;
 {
+  struct charset *cs = NULL;
+
+  if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
+      && charset_jisx0208 >= 0)
+    cs = CHARSET_FROM_ID (charset_jisx0208);
+  else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
+      && charset_ksc5601 >= 0)
+    cs = CHARSET_FROM_ID (charset_ksc5601);
+  if (cs)
+    return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
+
   if (FONT_ENTITY_P (font))
     {
       FcCharSet *charset = ftfont_get_fc_charset (font);