(parse_otf_command): Fix handing of negative features.
[m17n/m17n-lib.git] / src / m17n-flt.c
index 65970d4..7a34e3d 100644 (file)
@@ -742,14 +742,29 @@ otf_store_features (char *p, char *end, unsigned *buf)
   buf[i] = 0;
 }
 
+/* SYMBOL's name       features[0] [1] for checking    for applying
+   -------------       --------------- ------------    ------------
+   SCRIPT              [0]         [0]     any|any        all  all
+   SCRIPT=             NULL        [0]    none&1         none  all
+   SCRIPT+             [0]        NULL       1&none       all  none
+   SCRIPT=F1           [F1,0]      [0]      F1&1           F1  all
+   SCRIPT+F1           [0]      [F1,0]    none&F1        none  F1
+   SCRIPT=F1+          [F1,0]     NULL      F1&none        F1  none
+   SCRIPT=~F2          [-1,F2,0]   [0]     ~F2&1       all~F2  all
+   SCRIPT=F1,~F2       [F1,-1,A2,0][0]  F1&~F2&1       F1 (*1) all
+
+   (*1) Invalid specification
+ */
+
 static int
 parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec)
 {
   char *str = MSYMBOL_NAME (symbol);
   char *end = str + MSYMBOL_NAMELEN (symbol);
   unsigned int script, langsys;
-  char *gsub, *gpos;
-  int gsub_count = 0, gpos_count = 0;
+  char *features[3];
+  int feature_count[2];                /* [0]:GSUB, [1]:GPOS */
+  int i;
   char *p;
 
   memset (spec, 0, sizeof (MFLTOtfSpec));
@@ -765,64 +780,51 @@ parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec)
        /* This is a spec to reset category codes.  */
        return 0;
     }
-  script = gen_otf_tag (str, 8);
+  spec->script = gen_otf_tag (str, 8);
   str += 4;
   if (*str == '/')
     {
-      langsys = gen_otf_tag (str, 8);
+      spec->langsys = gen_otf_tag (str, 8);
       str += 4;
     }
   else
-    langsys = 0;
-  gsub = str;
+    spec->langsys = 0;
+  features[0] = str;
   if (*str != '=')
     /* Apply all GSUB features.  */
-      gsub_count = 1;
+      feature_count[0] = -1;
   else
     {
       p = str + 1;
-      str = otf_count_features (p, end, '+', &gsub_count);
+      str = otf_count_features (p, end, '+', feature_count);
       if (! str)
        MERROR (MERROR_FLT, -1);
     }
-  gpos = str;
+  features[1] = str;
   if (*str != '+')
     /* Apply all GPOS features.  */
-    gpos_count = 1;
+    feature_count[1] = -1;
   else
     {
       p = str + 1;
-      str = otf_count_features (p, end, '\0', &gpos_count);
+      str = otf_count_features (p, end, '\0', feature_count + 1);
       if (! str)
        MERROR (MERROR_FLT, -1);
     }
-
-  spec->script = script;
-  spec->langsys = langsys;
-  if (gsub_count > 0)
-    {
-      spec->features[0] = malloc (sizeof (int) * (gsub_count + 1));
-      if (! spec->features[0])
-       return -2;
-      if (*gsub == '=')
-       otf_store_features (gsub + 1, gpos, spec->features[0]);
-      else
-       spec->features[0][0] = 0xFFFFFFFF, spec->features[0][1] = 0;
-    }
-  if (gpos_count > 0)
-    {
-      spec->features[1] = malloc (sizeof (int) * (gpos_count + 1));
-      if (! spec->features[1])
-       {
-         if (spec->features[0])
-           free (spec->features[0]);
+  features[2] = str;
+  for (i = 0; i < 2; i++)
+    if (feature_count[i])
+      {
+       spec->features[i] = malloc (sizeof (int) * (feature_count[i] + 1));
+       if (! spec->features[i])
          return -2;
-       }
-      if (*gpos == '+')
-       otf_store_features (gpos + 1, str, spec->features[1]);
-      else
-       spec->features[1][0] = 0xFFFFFFFF, spec->features[1][1] = 0;
-    }
+       if (feature_count[i] > 0)
+         otf_store_features (features[i] + 1, features[i + 1],
+                             spec->features[i]);
+       else
+         spec->features[i][1] = 0;
+      }
+
   return 0;
 }
 
@@ -1882,13 +1884,14 @@ decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring,
          SET_CATEGORY_CODE (g, 0);
          continue;
        }
+      enc = '\0';
       if (tag & 0xFFFFF80)
        {
          int i;
 
          /* Clear the feature tag code.  */
          g->internal &= ~0xFFFFFFF;
-         for (i = 0, enc = '\0'; i < category->feature_table.size; i++)
+         for (i = 0; i < category->feature_table.size; i++)
            if (category->feature_table.tag[i] == tag)
              {
                enc = category->feature_table.code[i];
@@ -1897,10 +1900,9 @@ decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring,
                break;
              }
        }
-      else
-       enc = '\0';
       if (! enc)
-       enc = g->c > 0 ? (int) mchartable_lookup (category->table, g->c) : 1;
+       enc = (g->c > 0 ? (int) mchartable_lookup (category->table, g->c)
+              : g->c == 0 ? 1 : ' ');
       SET_CATEGORY_CODE (g, enc);
     }
 }
@@ -2018,7 +2020,6 @@ try_otf (int depth, MFLTOtfSpec *otf_spec, int from, int to,
         FontLayoutContext *ctx)
 {
   MFLTFont *font = ctx->font;
-  int from_idx = ctx->out->used;
 
   if (MDEBUG_FLAG () > 2)
     MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym));
@@ -2054,9 +2055,6 @@ try_otf (int depth, MFLTOtfSpec *otf_spec, int from, int to,
   font->get_glyph_id (font, ctx->in, from, to);
   if (mflt_try_otf)
     {
-      int out_len;
-      int i;
-
       to = mflt_try_otf (font, otf_spec, ctx->in, from, to);
       if (to < 0)
        return from;
@@ -2237,12 +2235,14 @@ run_command (int depth, int id, int from, int to, FontLayoutContext *ctx)
       {
        int i;
 
+       if (MDEBUG_FLAG () > 2)
+         MDEBUG_PRINT2 ("\n [FLT] %*s|", depth, "");
        i = from < to ? from : from - 1;
        GDUP (ctx, i);
        g = GREF (ctx->out, ctx->out->used - 1);
        g->c = -1, g->code = 0;
        g->xadv = g->yadv = 0;
-       SET_ENCODED (g, 0);
+       SET_ENCODED (g, 1);
        SET_MEASURED (g, 0);
        SET_CATEGORY_CODE (g, ' ');
        return from;
@@ -2676,7 +2676,7 @@ m17n_init_flt (void)
   mflt_font_id = NULL;
   mflt_try_otf = NULL;
 
-  MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules."));
+  MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize the flt modules."));
   MDEBUG_POP_TIME ();
 }
 
@@ -2691,7 +2691,7 @@ m17n_fini_flt (void)
 
   MDEBUG_PUSH_TIME ();
   free_flt_list ();
-  MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the flt modules."));
+  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the flt modules."));
   MDEBUG_POP_TIME ();
   m17n_fini_core ();
 }
@@ -3057,14 +3057,24 @@ mflt_run (MFLTGlyphString *gstring, int from, int to,
        {
          MDEBUG_PRINT ("\n [FLT]   (RESULT");
          if (MDEBUG_FLAG () > 1)
-           for (i = 0; this_from < this_to; this_from++, i++)
-             {
-               if (i > 0 && i % 4 == 0)
-                 MDEBUG_PRINT ("\n [FLT]          ");
-               g = GREF (gstring, this_from);
-               MDEBUG_PRINT4 (" (%04X %d %d %d)",
-                              g->code, g->xadv, g->xoff, g->yoff);
-             }
+           {
+             int idx = -1;
+             for (i = 0; this_from < this_to; i++, this_from++)
+               {
+                 g = GREF (gstring, this_from);
+                 if (g->from != idx)
+                   {
+                     if (i > 0)
+                       MDEBUG_PRINT2 ("\n [FLT]           %02d-%02d",
+                                      g->from, g->to);
+                     else
+                       MDEBUG_PRINT2 (" %02d-%02d", g->from, g->to);
+                     idx = g->from;
+                   }
+                 MDEBUG_PRINT4 (" (%04X %d %d %d)",
+                                g->code, g->xadv, g->xoff, g->yoff);
+               }
+           }
          else
            for (; this_from < this_to; this_from++)
              MDEBUG_PRINT1 (" %04X", GREF (gstring, this_from)->code);
@@ -3117,7 +3127,7 @@ dump_flt_cmd (FontLayoutStage *stage, int id, int indent)
   prefix[indent] = 0;
 
   if (id >= 0)
-    fprintf (stderr, "0x%02X", id);
+    fprintf (mdebug__output, "0x%02X", id);
   else if (id <= CMD_ID_OFFSET_INDEX)
     {
       int idx = CMD_ID_TO_INDEX (id);
@@ -3128,57 +3138,58 @@ dump_flt_cmd (FontLayoutStage *stage, int id, int indent)
          FontLayoutCmdRule *rule = &cmd->body.rule;
          int i;
 
-         fprintf (stderr, "(rule ");
+         fprintf (mdebug__output, "(rule ");
          if (rule->src_type == SRC_REGEX)
-           fprintf (stderr, "\"%s\"", rule->src.re.pattern);
+           fprintf (mdebug__output, "\"%s\"", rule->src.re.pattern);
          else if (rule->src_type == SRC_INDEX)
-           fprintf (stderr, "%d", rule->src.match_idx);
+           fprintf (mdebug__output, "%d", rule->src.match_idx);
          else if (rule->src_type == SRC_SEQ)
-           fprintf (stderr, "(seq)");
+           fprintf (mdebug__output, "(seq)");
          else if (rule->src_type == SRC_RANGE)
-           fprintf (stderr, "(range)");
+           fprintf (mdebug__output, "(range)");
          else
-           fprintf (stderr, "(invalid src)");
+           fprintf (mdebug__output, "(invalid src)");
 
          for (i = 0; i < rule->n_cmds; i++)
            {
-             fprintf (stderr, "\n%s  ", prefix);
+             fprintf (mdebug__output, "\n%s  ", prefix);
              dump_flt_cmd (stage, rule->cmd_ids[i], indent + 2);
            }
-         fprintf (stderr, ")");
+         fprintf (mdebug__output, ")");
        }
       else if (cmd->type == FontLayoutCmdTypeCond)
        {
          FontLayoutCmdCond *cond = &cmd->body.cond;
          int i;
 
-         fprintf (stderr, "(cond");
+         fprintf (mdebug__output, "(cond");
          for (i = 0; i < cond->n_cmds; i++)
            {
-             fprintf (stderr, "\n%s  ", prefix);
+             fprintf (mdebug__output, "\n%s  ", prefix);
              dump_flt_cmd (stage, cond->cmd_ids[i], indent + 2);
            }
-         fprintf (stderr, ")");
+         fprintf (mdebug__output, ")");
        }
       else if (cmd->type == FontLayoutCmdTypeOTF)
        {
-         fprintf (stderr, "(otf)");
+         fprintf (mdebug__output, "(otf)");
        }
       else
-       fprintf (stderr, "(error-command)");
+       fprintf (mdebug__output, "(error-command)");
     }
   else if (id <= CMD_ID_OFFSET_COMBINING)
-    fprintf (stderr, "cominging-code");
+    fprintf (mdebug__output, "cominging-code");
   else
-    fprintf (stderr, "(predefiend %d)", id);
+    fprintf (mdebug__output, "(predefiend %d)", id);
 }
 
 /***en
     @brief Dump a Font Layout Table.
 
     The mdebug_dump_flt () function prints the Font Layout Table $FLT
-    in a human readable way to the stderr.  $INDENT specifies how many
-    columns to indent the lines but the first one.
+    in a human readable way to the stderr or to what specified by the
+    environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
+    many columns to indent the lines but the first one.
 
     @return
     This function returns $FLT.  */
@@ -3192,22 +3203,22 @@ mdebug_dump_flt (MFLT *flt, int indent)
 
   memset (prefix, 32, indent);
   prefix[indent] = 0;
-  fprintf (stderr, "(flt");
+  fprintf (mdebug__output, "(flt");
   MPLIST_DO (plist, flt->stages)
     {
       FontLayoutStage *stage = (FontLayoutStage *) MPLIST_VAL (plist);
       int i;
 
-      fprintf (stderr, "\n%s  (stage %d", prefix, stage_idx);
+      fprintf (mdebug__output, "\n%s  (stage %d", prefix, stage_idx);
       for (i = 0; i < stage->used; i++)
        {
-         fprintf (stderr, "\n%s    ", prefix);
+         fprintf (mdebug__output, "\n%s    ", prefix);
          dump_flt_cmd (stage, INDEX_TO_CMD_ID (i), indent + 4);
        }
-      fprintf (stderr, ")");
+      fprintf (mdebug__output, ")");
       stage_idx++;
     }
-  fprintf (stderr, ")");
+  fprintf (mdebug__output, ")");
   return flt;
 }
 
@@ -3216,14 +3227,14 @@ mflt_dump_gstring (MFLTGlyphString *gstring)
 {
   int i;
 
-  fprintf (stderr, "(flt-gstring");
+  fprintf (mdebug__output, "(flt-gstring");
   for (i = 0; i < gstring->used; i++)
     {
       MFLTGlyph *g = GREF (gstring, i);
-      fprintf (stderr, "\n  (%02d pos:%d-%d c:%04X code:%04X cat:%c)",
+      fprintf (mdebug__output, "\n  (%02d pos:%d-%d c:%04X code:%04X cat:%c)",
               i, g->from, g->to, g->c, g->code, GET_CATEGORY_CODE (g));
     }
-  fprintf (stderr, ")\n");
+  fprintf (mdebug__output, ")\n");
 }
 
 /*** @} */