Copyright years udpated.
[m17n/m17n-lib.git] / src / m17n-flt.c
index 75d5c7f..2723f0b 100644 (file)
@@ -1,5 +1,5 @@
 /* m17n-flt.c -- Font Layout Table sub-module.
 /* m17n-flt.c -- Font Layout Table sub-module.
-   Copyright (C) 2003, 2004, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -543,7 +543,14 @@ load_category_table (MPlist *plist, MFLTFont *font)
       elt = MPLIST_PLIST (p);
       if (MPLIST_SYMBOL_P (elt))
        {
       elt = MPLIST_PLIST (p);
       if (MPLIST_SYMBOL_P (elt))
        {
-         MPlist *next = MPLIST_NEXT (elt);
+         MPlist *next;
+
+         if (! mflt_enable_new_feature)
+           {
+             M17N_OBJECT_UNREF (table);
+             return NULL;
+           }
+         next = MPLIST_NEXT (elt);
          if (! MPLIST_INTEGER_P (next))
            MERROR_GOTO (MERROR_FLT, end);
          if (! feature_table_head)
          if (! MPLIST_INTEGER_P (next))
            MERROR_GOTO (MERROR_FLT, end);
          if (! feature_table_head)
@@ -566,6 +573,11 @@ load_category_table (MPlist *plist, MFLTFont *font)
        }
       else if (MPLIST_SYMBOL_P (elt))
        {
        }
       else if (MPLIST_SYMBOL_P (elt))
        {
+         if (! mflt_enable_new_feature)
+           {
+             M17N_OBJECT_UNREF (table);
+             return NULL;
+           }
          if (font)
            {
              MFLTOtfSpec spec;
          if (font)
            {
              MFLTOtfSpec spec;
@@ -743,7 +755,16 @@ parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec)
   memset (spec, 0, sizeof (MFLTOtfSpec));
 
   spec->sym = symbol;
   memset (spec, 0, sizeof (MFLTOtfSpec));
 
   spec->sym = symbol;
-  str += 5;                    /* skip the heading ":otf=" */
+  str += 5;                    /* skip the heading ":otf=" or ":otf?" */
+  if (str[-1] == '?')
+    {
+      if (! mflt_enable_new_feature)
+       /* The client can't use this command.  */
+       return -1;
+      if (! *str)
+       /* This is a spec to reset category codes.  */
+       return 0;
+    }
   script = gen_otf_tag (str, 8);
   str += 4;
   if (*str == '/')
   script = gen_otf_tag (str, 8);
   str += 4;
   if (*str == '/')
@@ -818,7 +839,7 @@ load_otf_command (FontLayoutCmd *cmd, MSymbol sym)
   char *name = MSYMBOL_NAME (sym);
   int result;
 
   char *name = MSYMBOL_NAME (sym);
   int result;
 
-  if (name[0] != ':' && name[0] != '?')
+  if (name[0] != ':')
     {
       /* This is old format of "otf:...".  Change it to ":otf=...".  */
       char *str = alloca (MSYMBOL_NAMELEN (sym) + 2);
     {
       /* This is old format of "otf:...".  Change it to ":otf=...".  */
       char *str = alloca (MSYMBOL_NAMELEN (sym) + 2);
@@ -1394,6 +1415,8 @@ load_flt (MFLT *flt, MPlist *key_list)
              continue;
            }
          category = load_category_table (pl, NULL);
              continue;
            }
          category = load_category_table (pl, NULL);
+         if (! category)
+           goto err;
          if (! flt->coverage)
            {
              flt->coverage = category;
          if (! flt->coverage)
            {
              flt->coverage = category;
@@ -1420,7 +1443,7 @@ load_flt (MFLT *flt, MPlist *key_list)
     }
   if (category)
     unref_category_table (category);
     }
   if (category)
     unref_category_table (category);
-
+ err:
   if (! MPLIST_TAIL_P (plist))
     {
       M17N_OBJECT_UNREF (top);
   if (! MPLIST_TAIL_P (plist))
     {
       M17N_OBJECT_UNREF (top);
@@ -1569,7 +1592,7 @@ typedef struct
 
 static int run_command (int, int, int, int, FontLayoutContext *);
 static int run_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
 
 static int run_command (int, int, int, int, FontLayoutContext *);
 static int run_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
-static int run_otf_category (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
+static int try_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
 
 #define NMATCH 20
 
 
 #define NMATCH 20
 
@@ -1703,12 +1726,12 @@ run_rule (int depth,
            {
              if (MPLIST_INTEGER_P (p))
                {
            {
              if (MPLIST_INTEGER_P (p))
                {
-                 GREF (&gstring, i)->code = MPLIST_INTEGER (p);
+                 GREF (&gstring, i)->c = MPLIST_INTEGER (p);
                  GREF (&gstring, i)->encoded = 0;
                }
              else
                {
                  GREF (&gstring, i)->encoded = 0;
                }
              else
                {
-                 GREF (&gstring, i)->code = GREF (ctx->in, idx)->code;
+                 GREF (&gstring, i)->c = GREF (ctx->in, idx)->code;
                  GREF (&gstring, i)->encoded = GREF (ctx->in, idx)->encoded;
                  idx++;
                }
                  GREF (&gstring, i)->encoded = GREF (ctx->in, idx)->encoded;
                  idx++;
                }
@@ -1861,7 +1884,8 @@ decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring,
        {
          int i;
 
        {
          int i;
 
-         g->internal &= 0x30000000;
+         /* Clear the feature tag code.  */
+         g->internal &= ~0xFFFFFFF;
          for (i = 0, enc = '\0'; i < category->feature_table.size; i++)
            if (category->feature_table.tag[i] == tag)
              {
          for (i = 0, enc = '\0'; i < category->feature_table.size; i++)
            if (category->feature_table.tag[i] == tag)
              {
@@ -1872,7 +1896,7 @@ decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring,
              }
        }
       else
              }
        }
       else
-       enc = GET_COMBINED (g) ? '\0' : GET_CATEGORY_CODE (g);
+       enc = '\0';
       if (! enc)
        enc = g->c > 0 ? (int) mchartable_lookup (category->table, g->c) : 1;
       SET_CATEGORY_CODE (g, enc);
       if (! enc)
        enc = g->c > 0 ? (int) mchartable_lookup (category->table, g->c) : 1;
       SET_CATEGORY_CODE (g, enc);
@@ -1988,25 +2012,50 @@ run_otf (int depth,
 }
 
 static int
 }
 
 static int
-run_otf_category (int depth, MFLTOtfSpec *otf_spec, int from, int to,
-                 FontLayoutContext *ctx)
+try_otf (int depth, MFLTOtfSpec *otf_spec, int from, int to,
+        FontLayoutContext *ctx)
 {
   MFLTFont *font = ctx->font;
   int from_idx = ctx->out->used;
 
 {
   MFLTFont *font = ctx->font;
   int from_idx = ctx->out->used;
 
-  if (ctx->stage->category->feature_table.size == 0)
-    return from;
-
   if (MDEBUG_FLAG () > 2)
     MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym));
 
   if (MDEBUG_FLAG () > 2)
     MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym));
 
+  if (! otf_spec->features[0] && ! otf_spec->features[1])
+    {
+      /* Reset categories.  */
+      MCharTable *table = ctx->category->table;
+      int i;
+
+      for (i = from; i < to; i++)
+       {
+         MFLTGlyph *g = GREF (ctx->in, i);
+
+         if (! GET_COMBINED (g))
+           {
+             char enc = (GET_ENCODED (g)
+                         ? (g->c > 0 ? (int) mchartable_lookup (table, g->c)
+                            : 1)
+                         : g->code
+                         ? (int) mchartable_lookup (table, g->code)
+                         : ' ');
+             SET_CATEGORY_CODE (g, enc);
+             ctx->encoded[i - ctx->encoded_offset] = enc;
+           }
+       }
+      return from;
+    }
+
+  if (ctx->stage->category->feature_table.size == 0)
+    return from;
+
   font->get_glyph_id (font, ctx->in, from, to);
   font->get_glyph_id (font, ctx->in, from, to);
-  if (font->drive_otf)
+  if (mflt_try_otf)
     {
       int out_len;
       int i;
 
     {
       int out_len;
       int i;
 
-      to = font->drive_otf (font, otf_spec, ctx->in, from, to, NULL, NULL);
+      to = mflt_try_otf (font, otf_spec, ctx->in, from, to);
       if (to < 0)
        return from;
       decode_packed_otf_tag (ctx, ctx->in, from, to, ctx->stage->category);
       if (to < 0)
        return from;
       decode_packed_otf_tag (ctx, ctx->in, from, to, ctx->stage->category);
@@ -2115,7 +2164,7 @@ run_command (int depth, int id, int from, int to, FontLayoutContext *ctx)
       else if (cmd->type == FontLayoutCmdTypeOTF)
        to = run_otf (depth, &cmd->body.otf, from, to, ctx);
       else if (cmd->type == FontLayoutCmdTypeOTFCategory)
       else if (cmd->type == FontLayoutCmdTypeOTF)
        to = run_otf (depth, &cmd->body.otf, from, to, ctx);
       else if (cmd->type == FontLayoutCmdTypeOTFCategory)
-       to = run_otf_category (depth, &cmd->body.otf, from, to, ctx);
+       to = try_otf (depth, &cmd->body.otf, from, to, ctx);
       return to;
     }
 
       return to;
     }
 
@@ -2138,17 +2187,6 @@ run_command (int depth, int id, int from, int to, FontLayoutContext *ctx)
        g = GREF (ctx->out, ctx->out->used - 1);
        if (ctx->combining_code)
          SET_COMBINING_CODE (g, ctx, ctx->combining_code);
        g = GREF (ctx->out, ctx->out->used - 1);
        if (ctx->combining_code)
          SET_COMBINING_CODE (g, ctx, ctx->combining_code);
-       else if (! GET_COMBINED (g) && ctx->category)
-         {
-           MCharTable *table = ctx->category->table;
-           char enc = (GET_ENCODED (g)
-                       ? (g->c > 0 ? (int) mchartable_lookup (table, g->c)
-                          : 1)
-                       : g->code
-                       ? (int) mchartable_lookup (table, g->code)
-                       : ' ');
-           SET_CATEGORY_CODE (g, enc);
-         }
        if (ctx->left_padding)
          SET_LEFT_PADDING (g, ctx, LeftPaddingMask);
        if (ctx->cluster_begin_idx >= 0)
        if (ctx->left_padding)
          SET_LEFT_PADDING (g, ctx, LeftPaddingMask);
        if (ctx->cluster_begin_idx >= 0)
@@ -2202,8 +2240,8 @@ run_command (int depth, int id, int from, int to, FontLayoutContext *ctx)
        g = GREF (ctx->out, ctx->out->used - 1);
        g->c = -1, g->code = 0;
        g->xadv = g->yadv = 0;
        g = GREF (ctx->out, ctx->out->used - 1);
        g->c = -1, g->code = 0;
        g->xadv = g->yadv = 0;
-       SET_ENCODED (g, 1);
-       SET_MEASURED (g, 1);
+       SET_ENCODED (g, 0);
+       SET_MEASURED (g, 0);
        SET_CATEGORY_CODE (g, ' ');
        return from;
       }
        SET_CATEGORY_CODE (g, ' ');
        return from;
       }
@@ -2239,6 +2277,7 @@ run_stages (MFLTGlyphString *gstring, int from, int to,
   int i, j;
   MFLTGlyph *g;
   MPlist *stages = flt->stages;
   int i, j;
   MFLTGlyph *g;
   MPlist *stages = flt->stages;
+  FontLayoutCategory *prev_category = NULL;
 
   from_pos = GREF (ctx->in, from)->from;
   to_pos = GREF (ctx->in, to - 1)->to;
 
   from_pos = GREF (ctx->in, from)->from;
   to_pos = GREF (ctx->in, to - 1)->to;
@@ -2270,7 +2309,8 @@ run_stages (MFLTGlyphString *gstring, int from, int to,
          MFLTGlyph *g = GREF (ctx->in, i);
          char enc;
 
          MFLTGlyph *g = GREF (ctx->in, i);
          char enc;
 
-         if (GET_COMBINED (g))
+         if (GET_COMBINED (g)
+             || (prev_category && prev_category != ctx->stage->category))
            enc = (GET_ENCODED (g)
                   ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
                   : g->code
            enc = (GET_ENCODED (g)
                   ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
                   : g->code
@@ -2317,6 +2357,7 @@ run_stages (MFLTGlyphString *gstring, int from, int to,
        break;
 
       /* Otherwise, prepare for the next stage.   */
        break;
 
       /* Otherwise, prepare for the next stage.   */
+      prev_category = ctx->stage->category;
       temp = ctx->in;
       ctx->in = ctx->out;
       if (buf.glyphs)
       temp = ctx->in;
       ctx->in = ctx->out;
       if (buf.glyphs)
@@ -2624,8 +2665,10 @@ m17n_init_flt (void)
   Mgenerator = msymbol ("generator");
   Mend = msymbol ("end");
 
   Mgenerator = msymbol ("generator");
   Mend = msymbol ("end");
 
+  mflt_enable_new_feature = 0;
   mflt_iterate_otf_feature = NULL;
   mflt_font_id = NULL;
   mflt_iterate_otf_feature = NULL;
   mflt_font_id = NULL;
+  mflt_try_otf = NULL;
 
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules."));
   MDEBUG_POP_TIME ();
 
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules."));
   MDEBUG_POP_TIME ();
@@ -2768,6 +2811,8 @@ mflt_find (int c, MFLTFont *font)
            }
          best = flt;
        }
            }
          best = flt;
        }
+      if (best == NULL)
+       return NULL;
       flt = best;
       goto found;
     }
       flt = best;
       goto found;
     }
@@ -3042,6 +3087,8 @@ mflt_run (MFLTGlyphString *gstring, int from, int to,
   return to;
 }
 
   return to;
 }
 
+int mflt_enable_new_feature;
+
 int (*mflt_iterate_otf_feature) (struct _MFLTFont *font,
                                 MFLTOtfSpec *spec,
                                 int from, int to,
 int (*mflt_iterate_otf_feature) (struct _MFLTFont *font,
                                 MFLTOtfSpec *spec,
                                 int from, int to,
@@ -3049,6 +3096,9 @@ int (*mflt_iterate_otf_feature) (struct _MFLTFont *font,
 
 MSymbol (*mflt_font_id) (struct _MFLTFont *font);
 
 
 MSymbol (*mflt_font_id) (struct _MFLTFont *font);
 
+int (*mflt_try_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec,
+                    MFLTGlyphString *gstring, int from, int to);
+
 \f
 /* for debugging... */
 
 \f
 /* for debugging... */