*** empty log message ***
[m17n/m17n-lib.git] / src / m17n-flt.c
index ac992ec..e082fe3 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
 
@@ -257,9 +257,9 @@ enum GlyphInfoMask
 {
   CategoryCodeMask = 0x7F,
   CombiningCodeMask = 0xFFFFFF,
-  CombinedMask = 1 << 27,
-  LeftPaddingMask = 1 << 28,
-  RightPaddingMask = 1 << 29
+  CombinedMask = 1 << 28,
+  LeftPaddingMask = 1 << 29,
+  RightPaddingMask = 1 << 30
 };
 
 #define SET_GLYPH_INFO(g, mask, ctx, info)                     \
@@ -543,7 +543,14 @@ load_category_table (MPlist *plist, MFLTFont *font)
       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)
@@ -566,6 +573,11 @@ load_category_table (MPlist *plist, MFLTFont *font)
        }
       else if (MPLIST_SYMBOL_P (elt))
        {
+         if (! mflt_enable_new_feature)
+           {
+             M17N_OBJECT_UNREF (table);
+             return NULL;
+           }
          if (font)
            {
              MFLTOtfSpec spec;
@@ -743,7 +755,16 @@ parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec)
   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 == '/')
@@ -818,7 +839,7 @@ load_otf_command (FontLayoutCmd *cmd, MSymbol sym)
   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);
@@ -1394,6 +1415,8 @@ load_flt (MFLT *flt, MPlist *key_list)
              continue;
            }
          category = load_category_table (pl, NULL);
+         if (! category)
+           goto err;
          if (! flt->coverage)
            {
              flt->coverage = category;
@@ -1420,7 +1443,7 @@ load_flt (MFLT *flt, MPlist *key_list)
     }
   if (category)
     unref_category_table (category);
-
+ err:
   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_otf_category (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
+static int try_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
 
 #define NMATCH 20
 
@@ -1703,12 +1726,12 @@ run_rule (int depth,
            {
              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)->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++;
                }
@@ -1852,6 +1875,8 @@ decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring,
       unsigned int tag = g->internal & 0xFFFFFFF;
       char enc;
 
+      if (GET_COMBINED (g))
+       continue;
       if (! category)
        {
          SET_CATEGORY_CODE (g, 0);
@@ -1989,25 +2014,46 @@ run_otf (int depth,
 }
 
 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;
-
-  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));
 
-  font->get_glyph_id (font, ctx->in, from, to);
-  if (font->drive_otf)
+  if (! otf_spec->features[0] && ! otf_spec->features[1])
     {
-      int out_len;
+      /* Reset categories.  */
+      MCharTable *table = ctx->category->table;
       int i;
 
-      to = font->drive_otf (font, otf_spec, ctx->in, from, to, NULL, NULL);
+      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);
+  if (mflt_try_otf)
+    {
+      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);
@@ -2116,7 +2162,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)
-       to = run_otf_category (depth, &cmd->body.otf, from, to, ctx);
+       to = try_otf (depth, &cmd->body.otf, from, to, ctx);
       return to;
     }
 
@@ -2139,17 +2185,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);
-       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)
@@ -2274,11 +2309,15 @@ run_stages (MFLTGlyphString *gstring, int from, int to,
 
          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
-                  ? (int) mchartable_lookup (table, g->code)
-                  : ' ');
+           {
+             enc = (GET_ENCODED (g)
+                    ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
+                    : g->code
+                    ? (int) mchartable_lookup (table, g->code)
+                    : ' ');
+             if (! GET_COMBINED (g))
+               SET_CATEGORY_CODE (g, enc);
+           }
          else
            enc = GET_CATEGORY_CODE (g);
          ctx->encoded[i - from] = enc;
@@ -2628,8 +2667,10 @@ m17n_init_flt (void)
   Mgenerator = msymbol ("generator");
   Mend = msymbol ("end");
 
+  mflt_enable_new_feature = 0;
   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 ();
@@ -3048,6 +3089,8 @@ mflt_run (MFLTGlyphString *gstring, int from, int to,
   return to;
 }
 
+int mflt_enable_new_feature;
+
 int (*mflt_iterate_otf_feature) (struct _MFLTFont *font,
                                 MFLTOtfSpec *spec,
                                 int from, int to,
@@ -3055,6 +3098,9 @@ int (*mflt_iterate_otf_feature) (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... */