*** empty log message ***
authorhanda <handa>
Fri, 31 Aug 2007 13:08:51 +0000 (13:08 +0000)
committerhanda <handa>
Fri, 31 Aug 2007 13:08:51 +0000 (13:08 +0000)
Makefile.am
configure.ac
flt.c
m17n-imconf.c

index 9fd4cc1..6182fa8 100644 (file)
@@ -1,7 +1,7 @@
 noinst_PROGRAMS = \
        linebreak replace mimdemo mimdaemon fifotest1 fifotest2 \
        imtest findfont gdkdraw finddb imsim langname viewfile pangotest \
-       flt-gui flt-otf flt-hb
+       flt-gui flt-otf flt-hb flt-pango
 
 mimdemo_LDADD = -lgd
 mimdaemon_LDADD = -lgd
@@ -28,6 +28,10 @@ flt_hb_SOURCES = flt.c
 flt_hb_CFLAGS = ${baseCFLAGS} @M17NFLT_CFLAGS@ @HB_CFLAGS@ -DFLT_HB
 flt_hb_LDFLAGS = ${baseLIBS} @M17NFLT_LIBS@ @HB_LIBS@
 
+flt_pango_SOURCES = flt.c
+flt_pango_CFLAGS = ${baseCFLAGS} @M17NFLT_CFLAGS@ @PANGO_CFLAGS@ -DFLT_PANGO
+flt_pango_LDFLAGS = ${baseLIBS} @M17NFLT_LIBS@ @PANGO_LIBS@
+
 verify: linebreak
        @echo "checking line breaking..."
        @for arg in "" --sp-cm --korean-sp --ai-as-id; do \
index 7edbef7..a9d0213 100644 (file)
@@ -9,6 +9,7 @@ PKG_CHECK_MODULES(FC, fontconfig)
 PKG_CHECK_MODULES(M17NGUI, m17n-gui)
 PKG_CHECK_MODULES(M17NFLT, m17n-flt)
 PKG_CHECK_MODULES(OTF, libotf)
+PKG_CHECK_MODULES(PANGO, pangoft2)
 
 AC_ARG_WITH(harfbuzz, [Harfbuzz source directory], HBDIR="$withval", HBDIR="../harfbuzz")
 if test -d "$HBDIR/src/.libs"; then
diff --git a/flt.c b/flt.c
index 963209b..4b4a4f0 100644 (file)
--- a/flt.c
+++ b/flt.c
 #include <harfbuzz.h>
 #define PROGNAME "flt-hb"
 
-#else (defined (FLT_PANGO))
+#else  /* (defined (FLT_PANGO)) */
 
 #include <m17n-flt.h>
-#include <pango/pango-engine.h>
+#define PANGO_ENABLE_ENGINE
+#define PANGO_ENABLE_BACKEND
+#include <pango/pango.h>
 #include <pango/pango-ot.h>
-#include <pango/pango-utils.h>
-
+#include <pango/pangoft2.h>
+#include <pango/pangofc-font.h>
 #endif
 
 static FT_Library ft_library;
 
-FT_Face
-new_face (char *fontname, char **err)
+int
+parse_font_name (char *fontname, char **family, int *size, char **err)
 {
   FcPattern *pat;
-  FcChar8 *fam, *file;
+  FcChar8 *fam;
   double pixelsize;
-  FcFontSet *fs;
-  FcObjectSet *os;
-  FT_Face face;
 
   pat = FcNameParse ((FcChar8 *) fontname);
   if (! pat)
     {
       *err = "invalid name format";
-      return NULL;
+      return -1;
     }
   if (FcPatternGetString (pat, FC_FAMILY, 0, &fam) != FcResultMatch)
     {
+      FcPatternDestroy (pat);
       *err = "no family name";
-      return NULL;
+      return -1;
     }
   if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &pixelsize) != FcResultMatch)
     pixelsize = 20;
-  FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
-  FcPatternDel (pat, FC_PIXEL_SIZE);
+  *family = strdup ((char *) fam);
+  *size = pixelsize;
+  FcPatternDestroy (pat);
+  return 0;
+}
+
+FT_Face
+new_face (char *fontname, char **err)
+{
+  FcPattern *pat;
+  FcChar8 *fam, *file;
+  int size;
+  double pixelsize;
+  FcFontSet *fs;
+  FcObjectSet *os;
+  FT_Face face;
+
+  if (parse_font_name (fontname, (char **) &fam, &size, err) < 0)
+    return NULL;
+  pixelsize = size;
+  pat = FcPatternBuild (0,
+                       FC_FAMILY, FcTypeString, fam,
+                       FC_SCALABLE, FcTypeBool, FcTrue,
+                       NULL);
+  free (fam);
   os = FcObjectSetBuild (FC_FILE, NULL);
   fs = FcFontList (NULL, pat, os);
   if (fs->nfont == 0)
@@ -837,7 +860,7 @@ drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
 {
   FontInfoHB *font_info = (FontInfoHB *) font;
   int len = to - from;
-  int i, gidx;
+  int i;
   HB_Buffer buf;
   GsubGposInfo *ginfo;
   HB_UShort *apply_order_save;
@@ -892,8 +915,6 @@ drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
        gpos_applied = 1;
     }
 
-  gidx = out->used;
-
   for (i = 0; i < buf->in_length; i++)
     {
       HB_GlyphItem hg = buf->in_string + i;
@@ -984,31 +1005,45 @@ close_font (MFLTFont *font)
 #else  /* (defined (FLT_PANGO) */
 
 typedef struct {
+  int count;
+  guint *indices;
+  PangoOTRuleset *ruleset;
+} FeatureInfo;
+
+typedef struct {
+  FeatureInfo gsub;
+  FeatureInfo gpos;
+} GsubGposInfo;
+
+typedef struct {
   MFLTFont font;
-  PangoFcFont pango_fc_font;
+  PangoFontMap *fontmap;
+  PangoContext *context;
+  PangoFcFont *pango_font;
+  MPlist *otf_spec_cache;
 } FontInfoPango;
 
 int
 get_glyph_id (MFLTFont *font, MFLTGlyph *g)
 {
   FontInfoPango *font_info = (FontInfoPango *) font;
-  PangoGlyph pg = pango_fc_font_get_glyph (font_info->pango_fc_font, g->c);
+  PangoGlyph glyph = pango_fc_font_get_glyph (font_info->pango_font, g->c);
 
-  return (pg ? (int) pg : -1);
+  return (glyph ? (int) glyph : -1);
 }
 
 int
-get_metric (MFLTFont *font, MFLTGlyphString *gstring, int form, int to)
+get_metric (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
 {
   FontInfoPango *font_info = (FontInfoPango *) font;
-  PangoFcFont fc_font = font_info->pango_fc_font;
   int i;
 
   for (i = from; i < to; i++)
     {
+      MFLTGlyph *g = gstring->glyphs + from;
       PangoRectangle inc, logical;
 
-      pango_font_get_glyph_extents ((PangoFont *) fc_font,
+      pango_font_get_glyph_extents (PANGO_FONT (font_info->pango_font),
                                    gstring->glyphs[i].code, &inc, &logical);
       g->lbearing = inc.x;
       g->rbearing = inc.x + inc.width;
@@ -1019,6 +1054,221 @@ get_metric (MFLTFont *font, MFLTGlyphString *gstring, int form, int to)
     }
 }
 
+void
+setup_features (PangoOTTableType type, FontInfoPango *font_info,
+               MFLTOtfSpec *spec, FeatureInfo *info)
+{
+  int count, preordered;
+  unsigned int *features;
+  guint script, langsys;
+  guint req_feature, index;
+  guint *feature_list;
+  int i, j, k;
+  int err;
+  FT_Face face;
+  PangoOTInfo *ot_info; 
+
+  face = pango_fc_font_lock_face (font_info->pango_font);
+  ot_info = pango_ot_info_get (face);
+  pango_fc_font_unlock_face (font_info->pango_font);
+
+  if (! pango_ot_info_find_script (ot_info, type, spec->script, &script))
+    return;
+  if (spec->langsys)
+    {
+      if (! pango_ot_info_find_language (ot_info, type, script,
+                                        spec->langsys,
+                                        &langsys, &req_feature))
+       return;
+    }
+  else
+    {
+      langsys = PANGO_OT_DEFAULT_LANGUAGE;
+      req_feature = 0xFFFF;
+    }
+  if (type == PANGO_OT_TABLE_GSUB)
+    {
+      count = spec->gsub_count;
+      features = spec->gsub;
+    }
+  else
+    {
+      count = spec->gpos_count;
+      features = spec->gpos;
+    }
+  feature_list = NULL;
+  for (preordered = 0; preordered < count; preordered++)
+    if (features[preordered] == 0)
+      {
+       feature_list = pango_ot_info_list_features (ot_info, type, 0,
+                                                   script, langsys);
+       if (! feature_list)
+         return;
+       break;
+      }
+  if (feature_list)
+    for (i = 0; feature_list[i]; i++);
+  else
+    i = preordered;
+  info->indices = malloc (sizeof (guint) * ((req_feature != 0xFFFF) + i));
+  i = 0;
+  if (req_feature != 0xFFFF)
+    info->indices[i++] = req_feature;
+  for (j = 0; j < preordered; j++)
+    if (pango_ot_info_find_feature (ot_info, type, features[j],
+                                   script, langsys, &index))
+      info->indices[i++] = index;
+  if (feature_list)
+    for (j = 0; feature_list[j]; j++)
+      {
+       for (k = preordered + 1; k < count; k++)
+         if (feature_list[j] == features[k])
+           break;
+       if (k == count
+           && pango_ot_info_find_feature (ot_info, type, feature_list[j],
+                                          script, langsys, &index))
+         info->indices[i++] = index;
+      }
+  info->count = i;
+  info->ruleset = pango_ot_ruleset_new (ot_info);
+  for (i = 0; i < info->count; i++)
+    pango_ot_ruleset_add_feature (info->ruleset, type, info->indices[i],
+                                 PANGO_OT_ALL_GLYPHS);
+}
+
+GsubGposInfo *
+setup_otf_spec (FontInfoPango *font_info, MFLTOtfSpec *spec)
+{
+  GsubGposInfo *ginfo;
+
+  if (spec->gsub_count + spec->gpos_count == 0)
+    return NULL;
+  ginfo = mplist_get (font_info->otf_spec_cache, spec->sym);
+  if (ginfo)
+    return (ginfo->gsub.count + ginfo->gpos.count > 0 ? ginfo : NULL);
+  ginfo = calloc (1, sizeof (GsubGposInfo));
+  mplist_push (font_info->otf_spec_cache, spec->sym, ginfo);
+  setup_features (PANGO_OT_TABLE_GSUB, font_info, spec, &(ginfo->gsub));
+  setup_features (PANGO_OT_TABLE_GPOS, font_info, spec, &(ginfo->gpos));
+  return ginfo;
+}
+
+int
+drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+          MFLTGlyphString *in, int from, int to,
+          MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
+{
+  FontInfoPango *font_info = (FontInfoPango *) font;
+  PangoOTBuffer *buffer;
+  GsubGposInfo *ginfo;
+  PangoGlyphString *glyphs;
+  int i;
+
+  buffer = pango_ot_buffer_new (font_info->pango_font);
+  for (i = from; i < to; i++)
+    pango_ot_buffer_add_glyph (buffer, in->glyphs[i].code, 0, i);
+  ginfo = setup_otf_spec (font_info, spec);
+  if (! ginfo)
+    goto simple_copy;
+  if (ginfo->gsub.count > 0)
+    pango_ot_ruleset_substitute (ginfo->gsub.ruleset, buffer);
+  if (ginfo->gpos.count > 0)
+    pango_ot_ruleset_position (ginfo->gpos.ruleset, buffer);
+  glyphs = pango_glyph_string_new ();
+  pango_ot_buffer_output (buffer, glyphs);
+  for (i = 0; i < glyphs->num_glyphs; i++)
+    {
+      PangoGlyphInfo *glyph_info = glyphs->glyphs + i;
+      MFLTGlyph *g;
+
+      out->glyphs[out->used] = in->glyphs[glyphs->log_clusters[i]];
+      g = out->glyphs + out->used++;
+      if (g->code != glyph_info->glyph)
+       g->c = 0, g->code = glyph_info->glyph;
+      g->xoff = glyph_info->geometry.x_offset;
+      g->yoff = glyph_info->geometry.y_offset;
+      g->xadv = glyph_info->geometry.width;
+      g->yadv = 0;
+      adjustment[i].set = 0;
+    }
+  pango_ot_buffer_destroy (buffer);
+  pango_glyph_string_free (glyphs);
+  return to;
+
+ simple_copy:
+  pango_ot_buffer_destroy (buffer);
+  for (i = from; i < to; i++)
+    out->glyphs[out->used++] = in->glyphs[i];
+  return to;
+}
+
+
+MFLTFont *
+open_font (char *fontname, char **err)
+{
+  FontInfoPango *font_info = NULL;
+  PangoFontMap *fontmap;
+  PangoContext *context;
+  PangoFontDescription *desc;
+  PangoFont *pango_font;
+  char *family;
+  int size;
+  double pango_size;
+  
+  if (parse_font_name (fontname, &family, &size, err) < 0)
+    return NULL;
+  desc = pango_font_description_new ();
+  pango_font_description_set_family (desc, family);
+  free (family);
+  pango_size = size * PANGO_SCALE;
+  pango_font_description_set_absolute_size (desc, pango_size);
+
+  fontmap = pango_ft2_font_map_new ();
+  context = pango_context_new ();
+  pango_context_set_font_map (context, fontmap);
+  pango_font = pango_context_load_font (context, desc);
+  pango_font_description_free (desc);
+  if (pango_font)
+    {
+      font_info = calloc (1, sizeof (FontInfoPango));
+      font_info->fontmap = fontmap;
+      font_info->context = context;
+      font_info->pango_font = PANGO_FC_FONT (pango_font);
+    }
+  else
+    {
+      g_object_unref (context);
+      g_object_unref (fontmap);
+    }
+  return (MFLTFont *) font_info;
+}
+
+void
+close_font (MFLTFont *font)
+{
+  FontInfoPango *font_info = (FontInfoPango *) font;
+
+  g_object_unref (font_info->context);
+  g_object_unref (font_info->fontmap);
+}
+
+int
+flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
+{
+  MFLTGlyphString gstring;
+  int len = to - from;
+  int i;
+
+  memset (&gstring, 0, sizeof (MFLTGlyphString));
+  gstring.glyph_size = sizeof (MFLTGlyph);
+  gstring.allocated = len * 2;
+  gstring.glyphs = alloca (sizeof (MFLTGlyph) * gstring.allocated);
+  for (i = 0; i < len; i++)
+    gstring.glyphs[i].c = mtext_ref_char (mt, from + i);
+  gstring.used = len;
+  return mflt_run (&gstring, 0, len, font, msymbol (flt_name));
+}
+
 #endif
 
 int
index 90eb87f..24db13f 100644 (file)
@@ -177,6 +177,9 @@ call_config_common (int (*func) (MSymbol, MSymbol, MSymbol, MPlist *),
     ERROR (error_invalid_arg);
   if (TAILP (arg))
     arg = NULL;
+  else if (mplist_key (arg) == Mplist
+          && mplist_key ((MPlist *) mplist_value (arg)) == Mnil)
+    arg = (MPlist *) mplist_value (arg);
   if (func (lang, name, target, arg) < 0)
     ERROR (error_command_fail);
   return NULL;