Include "language.h".
authorhanda <handa>
Fri, 23 Jun 2006 02:31:55 +0000 (02:31 +0000)
committerhanda <handa>
Fri, 23 Jun 2006 02:31:55 +0000 (02:31 +0000)
(Motf): New variable.
(otf_script_list, load_otf_script_list): Delete it.
(find_script_from_otf_tag): Delete it.
(merge_capability): New function.
(mfont__init): Init Motf.
(mfont__fini): Don't unref otf_script_list.
(free_font_capability): Check cap->script_tag to determine if
OTF-related capability is set.
(mfont__get_capability): Call mscript__from_otf_tag.  Adjusted for
the change of type MFontCapability.
(mfont_put_prop): Call merge_capability for Mlanguage, Mscript,
and Motf properties.
(mfont_list): Call merge_capability for LANGUAGE arg.
(mfont_list_family_names): New function.

src/font.c

index 49a0559..94dcea3 100644 (file)
 #include "symbol.h"
 #include "plist.h"
 #include "charset.h"
+#include "language.h"
 #include "internal-gui.h"
 #include "font.h"
 #include "face.h"
@@ -345,6 +346,8 @@ MPlist *mfont__driver_list;
 
 static MSymbol M_font_capability, M_font_list, M_font_list_len;
 
+static MSymbol Motf;
+
 /** Indices to font properties sorted by their priority.  */
 static int font_score_priority[] =
   { MFONT_SIZE,
@@ -665,53 +668,6 @@ OTF_tag (char *name)
 }
 #endif /* not HAVE_OTF */
 
-static MPlist *otf_script_list;
-
-static int
-load_otf_script_list ()
-{
-  MDatabase *mdb;
-  MPlist *plist, *pl;
-
-  otf_script_list = mplist ();
-  mdb = mdatabase_find (msymbol ("standard"), Mscript, msymbol ("otf"), Mnil);
-  if (! mdb
-      || ! (plist = mdatabase_load (mdb)))
-    MERROR (MERROR_FONT, -1);
-  MPLIST_DO (pl, plist)
-    {
-      MPlist *p;
-      MSymbol script, otf_script;
-      OTF_Tag tag;
-
-      if (! MPLIST_PLIST_P (pl))
-       continue;
-      p = MPLIST_PLIST (pl);
-      if (! MPLIST_SYMBOL_P (p))
-       continue;
-      script = MPLIST_SYMBOL (p);
-      p = MPLIST_NEXT (p);
-      if (! MPLIST_SYMBOL_P (p))
-       continue;
-      otf_script = MPLIST_SYMBOL (p);
-      tag = OTF_tag (MSYMBOL_NAME (otf_script));
-      mplist_push (otf_script_list, script, (void *) tag);
-    }
-  M17N_OBJECT_UNREF (plist);
-  return 0;
-}
-
-static MSymbol
-find_script_from_otf_tag (OTF_Tag tag)
-{
-  MPlist *plist;
-
-  if (! otf_script_list)
-    load_otf_script_list ();
-  plist = mplist_find_by_value (otf_script_list, (void *) tag);
-  return (plist ? MPLIST_KEY (plist) : Mnil);
-}
-
 /* XLFD parser/generator */
 
 /** Indices to each field of split font name.  */
@@ -979,6 +935,82 @@ font_score (MFont *font, MFont *request)
   return score;
 }
 
+static MSymbol
+merge_capability (MSymbol capability, MSymbol key, MSymbol val, int overwrite)
+{
+  MFontCapability *cap = NULL;
+  char *lang = NULL, *script = NULL, *otf = NULL, *buf, *p;
+  int lang_len = 0, script_len = 0, otf_len = 0;
+
+  if (key == Mlanguage)
+    lang = MSYMBOL_NAME (val), lang_len = MSYMBOL_NAMELEN (val) + 6;
+  else if (key == Mscript)
+    script = MSYMBOL_NAME (val), script_len = MSYMBOL_NAMELEN (val) + 7;
+  else if (key == Motf)
+    otf = MSYMBOL_NAME (val), otf_len = MSYMBOL_NAMELEN (val) + 5;
+  else
+    return capability;
+
+  if (capability != Mnil)
+    {
+      cap = mfont__get_capability (capability);
+      if (! overwrite)
+       {
+         if (cap->language)
+           lang = NULL;
+         if (cap->script)
+           script = NULL;
+         if (cap->script_tag)
+           otf = NULL;
+         if (! lang && !script && !otf)
+           return capability;
+       }
+    }
+
+  if (! lang && cap && cap->language)
+    {
+      lang_len = MSYMBOL_NAMELEN (cap->language);
+      lang = MSYMBOL_NAME (cap->language);
+    }
+  if (! script && cap && cap->script != Mnil)
+    {
+      script_len = MSYMBOL_NAMELEN (cap->script);
+      script = MSYMBOL_NAME (cap->script);
+    }
+  if (! otf && cap && cap->script_tag)
+    {
+      int i;
+
+      otf_len = 4;                     /* for script_tag */
+      if (cap->langsys_tag)
+       otf_len += 5;           /* for "/XXXX */
+      for (i = 0; i < MFONT_OTT_MAX; i++)
+       if (cap->features[i].str)
+         otf_len += strlen (cap->features[i].str) + 1; /* for "[=+]..." */
+      otf = p = alloca (otf_len + 1);
+      OTF_tag_name (cap->script_tag, otf);
+      p += 4;
+      if (cap->langsys_tag)
+       {
+         *p++ = '/';
+         OTF_tag_name (cap->langsys_tag, p);
+         p += 4;
+       }
+      if (cap->features[MFONT_OTT_GSUB].str)
+       p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
+      if (cap->features[MFONT_OTT_GPOS].str)
+       p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str);
+    }
+  buf = p = alloca (lang_len + script_len + otf_len + 1);
+  if (lang_len)
+    p += sprintf (p, ":lang=%s", lang);
+  if (script_len)
+    p += sprintf (p, ":script=%s", script);
+  if (otf_len)
+    p += sprintf (p, ":otf=%s", otf);
+  return msymbol (buf);
+}
+
 \f
 /* Internal API */
 
@@ -1029,6 +1061,8 @@ mfont__init ()
   Municode_full = msymbol ("unicode-full");
   Mapple_roman = msymbol ("apple-roman");
 
+  Motf = msymbol ("otf");
+
   /* The first entry of each mfont__property_table must be Mnil so
      that actual properties get positive numeric numbers.  */
   for (i = 0; i <= MFONT_REGISTRY; i++)
@@ -1145,11 +1179,6 @@ mfont__fini ()
       M17N_OBJECT_UNREF (font_encoding_list);
       font_encoding_list = NULL;
     }
-  if (otf_script_list)
-    {
-      M17N_OBJECT_UNREF (otf_script_list);
-      otf_script_list = NULL;
-    }
 
   for (i = 0; i <= MFONT_REGISTRY; i++)
     MLIST_FREE1 (&mfont__property_table[i], names);
@@ -1635,9 +1664,7 @@ free_font_capability (void *object)
 {
   MFontCapability *cap = object;
   
-  if (cap->lang)
-    free (cap->lang);
-  if (cap->script)
+  if (cap->script_tag)
     {
       int i;
       for (i = 0; i < MFONT_OTT_MAX; i++)
@@ -1670,22 +1697,27 @@ mfont__get_capability (MSymbol sym)
     {
       if (*str++ != ':')
        continue;
-      if (str[0] == 'o' && str[1] == 't' && str[2] == 'f' && str[3] == '=')
+      if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0)
        {
+         MSymbol sym;
          int i;
 
          str += 4;
          for (i = 0, p = str; i < 4 && p < endp; i++, p++);
          if (i < 4)
            break;
+         sym = msymbol__with_len (str, 4);
+         cap->script = mscript__from_otf_tag (sym);
+         if (cap->script == Mnil)
+           break;
          cap->script_tag = OTF_tag (str);
-         cap->script = find_script_from_otf_tag (cap->script_tag);
          if (*p == '/')
            {
              for (i = 0, str = ++p; i < 4 && p < endp; i++, p++);
              if (i < 4)
                {
                  cap->script = Mnil;
+                 cap->script_tag = 0;
                  break;
                }
              cap->langsys_tag = OTF_tag (str);
@@ -1752,36 +1784,15 @@ mfont__get_capability (MSymbol sym)
              }
          str = p;
        }
-      else if (str[0] == 'l' && str[1] == 'a' && str[2] == 'n' && str[3] == 'g'
-         && str[4] == '=')
+      else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0)
        {
-         int count;
-
          str += 5;
-         for (p = str, count = 2; p < endp && *p != ':'; p++)
-           if (*p == ',')
-             count++;
-         MTABLE_MALLOC (cap->lang, count, MERROR_FONT);
-         for (p = str, count = 0; p < endp && *p != ':'; p++)
-           if (*p == ',')
-             {
-               MSymbol lang = msymbol__with_len (str, p - str), sym;
-
-               if (msymbol_get (lang, Miso639_2))
-                 cap->lang[count++] = lang;
-               else if ((sym = msymbol_get (lang, Miso639_1)) != Mnil)
-                 cap->lang[count++] = sym;
-               else if (msymbol_get (lang, Mlanguage))
-                 cap->lang[count++] = lang;
-               str = p + 1;
-             }
+         for (p = str; p < endp && *p != ':'; p++);
          if (str < p)
-           cap->lang[count++] = msymbol__with_len (str, p - str);
-         cap->lang[count] = Mnil;
+           cap->language = msymbol__with_len (str, p - str);
          str = p;
        }
-      else if (str[0] == 's' && str[1] == 'c' && str[2] == 'r' && str[3] == 'i'
-              && str[4] == 'p' && str[5] == 't' && str[6] == '=')
+      else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0)
        {
          str += 7;
          for (p = str; p < endp && *p != ':'; p++);
@@ -2393,18 +2404,10 @@ mfont_put_prop (MFont *font, MSymbol key, void *val)
       unsigned resy = (unsigned) val;
       font->property[MFONT_RESY] = resy;
     }
-  else if (key == Mlanguage)
+  else if (key == Mlanguage || key == Mscript || key == Motf)
     {
-      char *langname = MSYMBOL_NAME ((MSymbol) val);
-      int len = MSYMBOL_NAMELEN ((MSymbol) val);
-      
-      if (len <= 3)
-       {
-         char buf[10];
-
-         sprintf (buf, ":lang=%s", langname);
-         font->capability = msymbol (buf);
-       }
+      font->capability = merge_capability (font->capability,
+                                          key, (MSymbol) val, 1);
     }
   else if (key == Mfontfile)
     {
@@ -2785,6 +2788,10 @@ mfont_resize_ratio (MFont *font)
     ones that support $LANGUAGE.  $MAXNUM, if greater than 0, limits
     the number of fonts.
 
+    $LANGUAGE argument exists just for backward compatibility, and the
+    use is deprecated.  Use #Mlanguage font property instead.  If
+    $FONT already has #Mlanguage property, $LANGUAGE is ignored.
+
     @return
     This function returns a plist whose keys are family names and
     values are pointers to the object MFont.  The plist must be freed
@@ -2794,15 +2801,21 @@ mfont_resize_ratio (MFont *font)
 /***ja
     @brief ¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÆÀ¤ë
 
-    ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
-    $FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
-    $LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£
-    $MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
+    ´Ø¿ô mfont_list () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤ÇÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤ò
+    ÊÖ¤¹¡£$FONT ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢$FONT ¤È¹çÃפ¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È
+    ¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$LANGUAGE ¤¬ @c Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤ò¥µ¥Ý¡¼
+    ¥È¤¹¤ëÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤Î¥ê¥¹¥È¤òÊÖ¤¹¡£$MAXNUM ¤Ï¡¢0 ¤è¤êÂ礭¤¤¾ì
+    ¹ç¤Ë¤Ï¡¢ÊÖ¤¹¥Õ¥©¥ó¥È¤Î¿ô¤Î¾å¸Â¤Ç¤¢¤ë¡£
+
+    ¤¿¤À¤·¡¢°ú¿ô $LANGUAGE ¤ÏµìÈǤȤÎÀ°¹çÀ­¤Î¤¿¤á¤À¤±¤Ë¤¢¤ê¡¢¤½¤Î»ÈÍѤÏ
+    ´«¤á¤é¤ì¤Ê¤¤¡£¥Õ¥©¥ó¥È¤Î #Mlanguage ¥×¥í¥Ñ¥Æ¥£¤ò»È¤¦¤Ù¤­¤Ç¤¢¤ë¡£¤â
+    ¤· $FONT ¤¬¤¹¤Ç¤Ë¤³¤Î¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤¿¤é¡¢°ú¿ô $LANGUAGE ¤Ï̵
+
 
     @return 
-    ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Ê
-    plist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () 
-    ¤Ç²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
+    ¤³¤Î´Ø¿ô¤Ï¥­¡¼¤¬¥Õ¥©¥ó¥È¥Õ¥¡¥ß¥ê̾¤Ç¤¢¤êÃͤ¬ MFont ¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î
+    ¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Êplist ¤òÊÖ¤¹¡£plist ¤Ï m17n_object_unref () ¤Ç
+    ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤ÐNULL ¤òÊÖ¤¹¡£  */
 
 MPlist *
 mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
@@ -2825,13 +2838,8 @@ mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
     }
 
   if (language != Mnil)
-    {
-      /* ":lang=XXX" */
-      char *buf = alloca (MSYMBOL_NAMELEN (language) + 7);
-
-      sprintf (buf, ":lang=%s", MSYMBOL_NAME (language));
-      spec.capability = msymbol (buf);
-    }
+    spec.capability = merge_capability (spec.capability, Mlanguage, language,
+                                       0);
 
   font_list = mfont__list (frame, &spec, &spec, 0);
   if (! font_list)
@@ -2854,6 +2862,33 @@ mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum)
   return plist;
 }
 
+/***en
+    @brief Get a list of font famiy names.
+
+    The mfont_list_family_names () functions returns a list of font
+    family names available on frame $FRAME.
+
+    @return
+
+    This function returns a plist whose keys are #Msymbol and values
+    are symbols representing font family names.  The elements are
+    sorted by alphabetical order.  The plist must be freed by
+    m17n_object_unref ().  If not font is found, it returns NULL.  */
+
+MPlist *
+mfont_list_family_names (MFrame *frame)
+{
+  MPlist *plist = mplist (), *p;
+
+  MPLIST_DO (p, frame->font_driver_list)
+    {
+      MFontDriver *driver = MPLIST_VAL (p);
+
+      (driver->list_family_names) (frame, plist);
+    }
+  return plist;
+}
+
 
 /*=*/