Copyright notice fixed.
authorhanda <handa>
Wed, 20 Dec 2006 08:02:32 +0000 (08:02 +0000)
committerhanda <handa>
Wed, 20 Dec 2006 08:02:32 +0000 (08:02 +0000)
(G_LOG_DOMAIN): Changed to "Pango-M17N-FC".
(fontset): New variable.
(init_module): Delete local variable fontset.
(fini_module): Unref fontset.
(m17n_scripts): Add many scripts.
(m17n_fc_get_family): New function.
(m17n_fc_lookup_fontset): New function.
(m17n_fc_free_font_info): New function.
(m17n_fc_get_font): New function.
(m17n_fc_engine_shape): Fix prototype.
(m17n_fc_engine_shape): use m17n_fc_get_font.  Fix geometry
calculation.
(m17n_fc_engine_covers): Use m17n_fc_get_font and
m17n_fc_lookup_fontset.

m17n-fc.c

index 0ff05ba..b042bfb 100644 (file)
--- a/m17n-fc.c
+++ b/m17n-fc.c
@@ -1,28 +1,26 @@
 /* Pango
  * m17n-fc.c: Generic shaper using the m17n library for FreeType-based backends
 
-   Copyright (C) 2004, 2005
+   Copyright (C) 2004, 2005, 2006
      National Institute of Advanced Industrial Science and Technology (AIST)
-     Registration Number H15PRO112
+     Registration Number H16PRO276
 
-   This file is part of the m17n library.
+   This file is part of the pango-m17n library.
 
-   The m17n library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public License
-   as published by the Free Software Foundation; either version 2.1 of
-   the License, or (at your option) any later version.
+   The pango-m17n library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
-   The m17n library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
+   The pango-m17n library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.  */
-
-#include <config.h>
+   License along with the pango-m17n library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+   MA 02111-1307, USA.  */
 
 #include <string.h>
 #include <stdlib.h>
@@ -37,7 +35,7 @@
 #ifdef G_LOG_DOMAIN
 #undef G_LOG_DOMAIN
 #endif
-#define G_LOG_DOMAIN "M17N-Pango-FC"
+#define G_LOG_DOMAIN "Pango-M17N-FC"
 
 /* Control printing of debug information.  It is initialized from the
    environment variable PANGO_M17N_FC_DEBUG.  Currently, any positive
@@ -47,6 +45,9 @@ static int debug_level;
 /* Commonly used frame on nulldevice.  */
 static MFrame *frame;
 
+/* Commonly used "generic" fontset.  */
+static MFontset *fontset;
+
 /* Initialize this module.  The main task is to open a frame on
    nulldevice.  */
 
@@ -56,7 +57,6 @@ init_module ()
   const char *envvar = g_getenv ("PANGO_M17N_FC_DEBUG");
   MPlist *param;
   MFace *face;
-  MFontset *fontset;
 
   debug_level = envvar ? atoi (envvar) : 0;
 
@@ -68,7 +68,6 @@ init_module ()
   mplist_put (param, Mface, face);
   mplist_put (param, Mdevice, Mnil);
   frame = mframe (param);
-  m17n_object_unref (fontset);
   m17n_object_unref (face);
   m17n_object_unref (param);
 }
@@ -79,6 +78,7 @@ static void
 fini_module ()
 {
   m17n_object_unref (frame);
+  m17n_object_unref (fontset);
 }
 
 /* No extra fields needed for these structures.  */
@@ -90,19 +90,34 @@ typedef PangoEngineShapeClass M17NEngineFcClass;
 
 static PangoEngineScriptInfo m17n_scripts[] = {
   { PANGO_SCRIPT_ARABIC,   "*" },
+  { PANGO_SCRIPT_ARMENIAN, "*" },
   { PANGO_SCRIPT_BENGALI,  "*" },
+  { PANGO_SCRIPT_BOPOMOFO, "*" },
+  { PANGO_SCRIPT_CHEROKEE, "*" },
+  { PANGO_SCRIPT_COPTIC,   "*" },
+  { PANGO_SCRIPT_CYRILLIC, "*" },
+  { PANGO_SCRIPT_DESERET,  "*" },
   { PANGO_SCRIPT_DEVANAGARI, "*" },
   { PANGO_SCRIPT_ETHIOPIC, "*" },
   { PANGO_SCRIPT_GEORGIAN, "*" },
+  { PANGO_SCRIPT_GOTHIC,   "*" },
+  { PANGO_SCRIPT_GREEK,    "*" },
   { PANGO_SCRIPT_GUJARATI, "*" },
   { PANGO_SCRIPT_GURMUKHI, "*" },
+  { PANGO_SCRIPT_HAN,      "*" },
+  { PANGO_SCRIPT_HANGUL,   "*" },
   { PANGO_SCRIPT_HEBREW,   "*" },
+  { PANGO_SCRIPT_HIRAGANA, "*" },
   { PANGO_SCRIPT_KANNADA,  "*" },
+  { PANGO_SCRIPT_KATAKANA, "*" },
   { PANGO_SCRIPT_KHMER,    "*" },
   { PANGO_SCRIPT_LAO,      "*" },
   { PANGO_SCRIPT_MALAYALAM, "*" },
   { PANGO_SCRIPT_MYANMAR,  "*" },
+  { PANGO_SCRIPT_OGHAM,    "*" },
+  { PANGO_SCRIPT_OLD_ITALIC, "*" },
   { PANGO_SCRIPT_ORIYA,     "*" },
+  { PANGO_SCRIPT_RUNIC,     "*" },
   { PANGO_SCRIPT_SINHALA,   "*" },
   { PANGO_SCRIPT_SYRIAC,    "*" },
   { PANGO_SCRIPT_TAMIL,     "*" },
@@ -110,6 +125,31 @@ static PangoEngineScriptInfo m17n_scripts[] = {
   { PANGO_SCRIPT_THAANA,    "*" },
   { PANGO_SCRIPT_THAI,      "*" },
   { PANGO_SCRIPT_TIBETAN,   "*" },
+  { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" },
+  { PANGO_SCRIPT_YI,       "*" },
+
+#ifdef PANGO_SCRIPT_BRAILLE
+  { PANGO_SCRIPT_BRAILLE,  "*" },
+  { PANGO_SCRIPT_CYPRIOT,  "*" },
+  { PANGO_SCRIPT_LIMBU,    "*" },
+  { PANGO_SCRIPT_OSMANYA,  "*" },
+  { PANGO_SCRIPT_SHAVIAN,  "*" },
+  { PANGO_SCRIPT_LINEAR_B, "*" },
+  { PANGO_SCRIPT_TAI_LE,   "*" },
+  { PANGO_SCRIPT_UGARITIC, "*" },
+#endif /* PANGO_SCRIPT_BRAILLE */
+
+#ifdef PANGO_SCRIPT_NEW_TAI_LUE
+  { PANGO_SCRIPT_NEW_TAI_LUE, "*" },
+  { PANGO_SCRIPT_BUGINESE, "*" },
+  { PANGO_SCRIPT_GLAGOLITIC, "*" },
+  { PANGO_SCRIPT_TIFINAGH, "*" },
+  { PANGO_SCRIPT_SYLOTI_NAGRI, "*" },
+  { PANGO_SCRIPT_OLD_PERSIAN, "*" },
+  { PANGO_SCRIPT_KHAROSHTHI, "*" },
+#endif /* PANGO_SCRIPT_NEW_TAI_LUE */
+
+  { PANGO_SCRIPT_COMMON,   "" }
 };
 
 static PangoEngineInfo script_engines[] = {
@@ -121,6 +161,17 @@ static PangoEngineInfo script_engines[] = {
   }
 };
 
+static char *
+m17n_fc_get_family (PangoFont *pango_font)
+{
+  PangoFcFont *pango_fc_font = PANGO_FC_FONT (pango_font);
+  FcChar8 *family;
+
+  if (FcPatternGetString (pango_fc_font->font_pattern, FC_FAMILY, 0, &family)
+      == FcResultMatch)
+    return (char *) family;
+  return "";
+}
 
 /* Convert PANGO_LANGUAGE to m17n-lib's language symbol.  If m17n-lib
    doesn't know about PANGO_LANGUAGE, return Mnil.  */
@@ -156,14 +207,106 @@ m17n_fc_get_language (PangoLanguage *pango_language)
   return language;
 }
 
+
+/* Return a list of FONT-SPECs specified in the current fontset for
+   displaying SCRIPT in LANGUAGE.  Callers must unref the returned
+   plist.  */
+
+MPlist *
+m17n_fc_lookup_fontset (MSymbol script, MSymbol language)
+{
+  MPlist *plist = mfontset_lookup (fontset, script, language, Mnil);
+
+  if (mplist_key (plist) == Mnil)
+    {
+      /* List up languages that have entries for SCRIPT.  */
+      MPlist *ll = mfontset_lookup (fontset, script, Mt, Mnil);  
+
+      if (! ll)
+       {
+         /* No entry for SCRIPT.  Return fallback FONT-SPECs. */
+         m17n_object_unref (plist);
+         plist = mfontset_lookup (fontset, Mnil, Mnil, Mnil);
+       }
+      else
+       {
+         if (mplist_length (ll) == 1)
+           {
+             /* If there's just one language, return FONT-SPECs for it.  */
+             m17n_object_unref (plist);
+             language = mplist_key (ll);
+             if (language == Mt)
+               language = Mnil;
+             plist = mfontset_lookup (fontset, script, mplist_key (ll), Mnil);
+           }
+         else
+           /* Sumup FONT-SPECs for all languages.  */
+           for (; mplist_key (ll) != Mnil; ll = mplist_next (ll))
+             {
+               MPlist *pl;
+
+               language = mplist_key (ll);
+               if (language == Mt)
+                 language = Mnil;
+               for (pl = mfontset_lookup (fontset, script, language, Mnil);
+                    mplist_key (pl) != Mnil; pl = mplist_next (pl))
+                 mplist_add (plist, mplist_key (pl), mplist_value (pl));
+           }
+       }
+    }
+  return plist;
+}
+
+
+typedef struct
+{
+  PangoFcFont *pango_fc_font;
+  MFont *font;
+} M17NFontInfo;
+
+static void
+m17n_fc_free_font_info (gpointer data)
+{
+  M17NFontInfo *font_info = data;
+
+  if (font_info->font)
+    {
+      mfont_close (font_info->font);
+      pango_fc_font_unlock_face (font_info->pango_fc_font);
+    }
+  g_free (data);
+}
+
+static MFont *
+m17n_fc_get_font (PangoFont *pango_font)
+{
+  GQuark info_id = g_quark_from_string ("m17n-font-info");
+  M17NFontInfo *font_info;
+
+  font_info = g_object_get_qdata (G_OBJECT (pango_font), info_id);
+  if (! font_info)
+    {
+      PangoFcFont *pango_fc_font = PANGO_FC_FONT (pango_font);
+      FT_Face ft_face = pango_fc_font_lock_face (pango_fc_font);
+
+      font_info = g_new (M17NFontInfo, 1);
+      font_info->pango_fc_font = pango_fc_font;
+      font_info->font = mfont_encapsulate (frame, Mfreetype, ft_face);
+      g_object_set_qdata_full (G_OBJECT (pango_font), info_id, font_info,
+                              (GDestroyNotify) m17n_fc_free_font_info);
+    }
+  return font_info->font;
+}
+
+
 /* Shaper function.  */
 
 static void 
 m17n_fc_engine_shape (PangoEngineShape *engine,
                      PangoFont        *pango_font,
                      const char       *text,
-                     gint              length,
-                     PangoAnalysis    *analysis,
+                     int              length,
+                     const PangoAnalysis    *analysis,
                      PangoGlyphString *glyphs)
 {
   /* Symbols for character property `category'.  */
@@ -174,8 +317,6 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
   MText *mt;
   MDrawGlyph *m_glyphs;
   int nchars, nglyphs;
-  PangoFcFont *fc_font;
-  char *fontname;
   MFont *font;
   int i;
   const char *p;
@@ -215,23 +356,8 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
   for (i = 0, p = text; i < nchars; i++, p = g_utf8_next_char (p))
     offsets[i] = p - text;
 
-  fc_font = PANGO_FC_FONT (pango_font);
-  fontname = (char *) FcNameUnparse (fc_font->font_pattern);
-  font = mfont_parse_name (fontname, Mfontconfig);
-  free (fontname);
-  {
-    FcChar8 *filename;
-    int size;
-
-    if (FcPatternGetString (fc_font->font_pattern, FC_FILE, 0, &filename)
-       == FcResultMatch)
-      mfont_put_prop (font, Mfontfile, msymbol ((char *) filename));
-    size = (int) mfont_get_prop (font, Msize);
-    if (size)
-      mfont_put_prop (font, Msize, (void *) (size * 256));
-    if (debug_level > 0)
-      g_debug ("  by %s", (char *) filename);
-  }
+  font = m17n_fc_get_font (pango_font);
+  g_return_if_fail (font != NULL);
 
   mtext_put_prop (mt, 0, nchars, Mfont, font);
   if (language != Mnil)
@@ -256,9 +382,9 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
       if (m_glyphs[i].glyph_code >= 0)
        {
          g->glyph = m_glyphs[i].glyph_code;
-         g->geometry.x_offset = m_glyphs[i].x_off * PANGO_SCALE / 256;
-         g->geometry.y_offset = m_glyphs[i].y_off * PANGO_SCALE / 256;
-         g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE / 256;
+         g->geometry.x_offset = m_glyphs[i].x_off * PANGO_SCALE;
+         g->geometry.y_offset = m_glyphs[i].y_off * PANGO_SCALE;
+         g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE;
        }
       else
        {
@@ -269,7 +395,7 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
          if (category == MZs)
            {
              g->glyph = 0;
-             g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE / 256;
+             g->geometry.width = m_glyphs[i].x_advance * PANGO_SCALE;
            }
          else if (category == MCf)
            {
@@ -278,7 +404,8 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
            }
          else
            {
-             g->glyph = pango_fc_font_get_unknown_glyph (fc_font, c);
+             g->glyph = (pango_fc_font_get_unknown_glyph
+                         (PANGO_FC_FONT (pango_font), c));
              pango_font_get_glyph_extents (pango_font, g->glyph, NULL,
                                            &logical_rect);
              g->geometry.width = logical_rect.width;
@@ -293,7 +420,6 @@ m17n_fc_engine_shape (PangoEngineShape *engine,
     }
 
   m17n_object_unref (mt);
-  free (font);
 }
 
 /* Check if PANGO_FONT is suitable for the character WC.  */
@@ -309,11 +435,9 @@ m17n_fc_engine_covers (PangoEngineShape *engine,
   static MSymbol Mlatin, Mcommon, Minherited;
   PangoCoverage *coverage;
   PangoCoverageLevel result;
-  PangoFcFont *fc_font;
-  char *fontname;
-  MFont *font;
   MSymbol script, language;
-  int check_result;
+  MPlist *spec_list, *p;
+  MFont *font;
 
   if (! Mlatin)
     {
@@ -335,22 +459,11 @@ m17n_fc_engine_covers (PangoEngineShape *engine,
   if (result == PANGO_COVERAGE_NONE)
     {
       if (debug_level > 0)
-       {
-         fc_font = PANGO_FC_FONT (pango_font);
-         fontname = (char *) FcNameUnparse (fc_font->font_pattern);
-         font = mfont_parse_name (fontname, Mfontconfig);
-         g_debug ("  %s none", 
-                  msymbol_name (mfont_get_prop (font, Mfamily)));
-         free (fontname);
-         free (font);
-       }
+       g_debug ("  %s none", m17n_fc_get_family (pango_font));
       return result;
     }
 
-  fc_font = PANGO_FC_FONT (pango_font);
-  fontname = (char *) FcNameUnparse (fc_font->font_pattern);
-  font = mfont_parse_name (fontname, Mfontconfig);
-
+  language = m17n_fc_get_language (pango_language);
   if (wc < 0x100)
     script = Mlatin;
   else
@@ -359,27 +472,26 @@ m17n_fc_engine_covers (PangoEngineShape *engine,
       if (script == Mcommon || script == Minherited)
        script = mchar_get_prop ((int) wc, msymbol ("block"));
     }
-  language = m17n_fc_get_language (pango_language);
 
-  check_result = mfont_check (frame, NULL, script, language, font);
+  font = m17n_fc_get_font (pango_font);
+  spec_list = m17n_fc_lookup_fontset (script, language);
+
+  result = PANGO_COVERAGE_NONE;
+  for (p = spec_list; mplist_key (p) != Mnil; p = mplist_next (p))
+    if (mfont_match_p (font, mplist_value (p)))
+      {
+       result = PANGO_COVERAGE_EXACT;
+       break;
+      }
+  m17n_object_unref (spec_list);
   if (debug_level > 0)
-    {
-      char *result_text = (check_result == 2 ? "exact"
-                          : check_result == 1 ? "approximate"
-                          : "fallback");
-
-      g_debug ("  (%s,%s): %s %s",
-              (script ? msymbol_name (script) : ""),
-              (language ? msymbol_name (language) : ""),
-              msymbol_name (mfont_get_prop (font, Mfamily)),
-              result_text);
-    }      
-
-  free (fontname);
-  free (font);
-  return (check_result == 2 ? PANGO_COVERAGE_EXACT
-         : check_result == 1 ? PANGO_COVERAGE_APPROXIMATE
-         : PANGO_COVERAGE_FALLBACK);
+    g_debug ("  (%s,%s): %s %s",
+            (script ? msymbol_name (script) : ""),
+            (language ? msymbol_name (language) : ""),
+            m17n_fc_get_family (pango_font),
+            result == PANGO_COVERAGE_EXACT ? "exact" : "none");
+
+  return result;
 }
 
 static void