(get_anchor): Delete it.
[m17n/libotf.git] / example / otfdump.c
index 80b580d..f5961e5 100644 (file)
@@ -1,9 +1,34 @@
+/* otfdump.c -- Dump OpenType Layout Tables.
+
+Copyright (C) 2003, 2004, 2008
+  National Institute of Advanced Industrial Science and Technology (AIST)
+  Registration Number H15PRO167
+
+This file is part of libotf.
+
+Libotf 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.
+
+Libotf 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 this library, in a file named COPYING; if not,
+write to the Free Software Foundation, Inc., 59 Temple Place, Suite
+330, Boston, MA 02111-1307, USA.  */
+
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <libgen.h>
 
 #include <otf.h>
 
@@ -84,10 +109,11 @@ dump_glyph_ids (int indent, char *title, OTF_GlyphID *ids, unsigned count)
   printf (")");
 }
 
-static void
+static int *
 dump_coverage (int indent, char *title, OTF_Coverage *coverage)
 {
   int i;
+  int *char_list;
 
   IPRINT ("(%sCoverage (CoverageFormat %d)",
          (title ? title : ""), coverage->CoverageFormat);
@@ -96,12 +122,18 @@ dump_coverage (int indent, char *title, OTF_Coverage *coverage)
     {
       dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray,
                      coverage->Count);
+      char_list = malloc (sizeof (int) * (coverage->Count + 1));
+      for (i = 0; i < coverage->Count; i++)
+       char_list[i] = coverage->table.GlyphArray[i];
+      char_list[i] = -1;
     }
   else
     {
+      int n, c;
+
       IPRINT ("(RangeCount %d)", coverage->Count);
       indent++;
-      for (i = 0; i < coverage->Count; i++)
+      for (i = n = 0; i < coverage->Count; i++)
        {
          IPRINT ("(Range (%d) (Start #x%04X) (End #x%04X)", i,
                  coverage->table.RangeRecord[i].Start,
@@ -110,9 +142,19 @@ dump_coverage (int indent, char *title, OTF_Coverage *coverage)
          IPRINT ("(StartCoverageIndex %d))",
                  coverage->table.RangeRecord[i].StartCoverageIndex);
          indent--;
+         n += (coverage->table.RangeRecord[i].End
+               - coverage->table.RangeRecord[i].Start + 1);
        }
+      char_list = malloc (sizeof (int) * (n + 1));
+      for (i = n = 0; i < coverage->Count; i++)
+       for (c = coverage->table.RangeRecord[i].Start;
+            c <= coverage->table.RangeRecord[i].End;
+            c++)
+         char_list[n++] = c;
+      char_list[n] = -1;
     }
   printf (")");
+  return char_list;
 }
 
 static void
@@ -123,7 +165,7 @@ dump_coverage_list (int indent, char *title,
 
   IPRINT ("(%s %d)", title, num);
   for (i = 0; i < num; i++)
-    dump_coverage (indent, NULL, coverage + i);
+    free (dump_coverage (indent, NULL, coverage + i));
 }
 
 
@@ -264,10 +306,14 @@ dump_device_table (int indent, char *title, OTF_DeviceTable *table)
   indent++;
   IPRINT ("(StartSize %d) (EndSize %d) (DeltaFormat %d)",
          table->StartSize, table->EndSize, table->DeltaFormat);
-  IPRINT ("(DeltaValue");
-  for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
-    printf (" %d", table->DeltaValue[i]);
-  printf ("))");
+  if (table->DeltaValue)
+    {
+      IPRINT ("(DeltaValue");
+      for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
+       printf (" %d", table->DeltaValue[i]);
+      printf (")");
+    }
+  printf (")");
 }
 
 \f
@@ -324,9 +370,10 @@ dump_alternate_set_list (int indent, OTF_AlternateSet *altset, unsigned num)
 
 
 static void
-dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
+dump_ligature_set_list (int indent, int *char_list,
+                       OTF_LigatureSet *ligset, unsigned num)
 {
-  int i, j;
+  int i, j, k;
 
   IPRINT ("(LigSetCount %d)", num);
   for (i = 0; i < num; i++)
@@ -343,6 +390,10 @@ dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
                  ligset[i].Ligature[j].LigGlyph);
          dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component,
                          ligset[i].Ligature[j].CompCount - 1);
+         IPRINT ("(i.e. #x%04X", char_list[i]);
+         for (k = 0; k < ligset[i].Ligature[j].CompCount - 1; k++)
+           printf (" #x%04X", ligset[i].Ligature[j].Component[k]);
+         printf (" = #x%04X)", ligset[i].Ligature[j].LigGlyph);
          printf (")");
          indent--;
        }
@@ -352,6 +403,33 @@ dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
 }
 
 static void
+dump_pair_set_list (int indent, unsigned count, OTF_PairSet *set)
+{
+  int i, j;
+
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(PairSet (%d)", i);
+      indent++;
+      for (j = 0; j < set[i].PairValueCount; j++)
+       {
+         IPRINT ("(PairValueRecord (%d)", j);
+         indent++;
+         IPRINT ("(SecondGlyph #x%04X)",
+                 set[i].PairValueRecord[j].SecondGlyph);
+         dump_value_record (indent, "Value1",
+                            &set[i].PairValueRecord[j].Value1);
+         dump_value_record (indent, "Value2",
+                            &set[i].PairValueRecord[j].Value2);
+         printf (")");
+         indent--;
+       }
+      printf (")");
+      indent--;
+    }
+}
+
+static void
 dump_class1_record_list (int indent,
                         unsigned Class1Count, unsigned Class2Count,
                         OTF_Class1Record *rec)
@@ -397,6 +475,22 @@ dump_anchor (int indent, OTF_Anchor *anchor)
 }
 
 static void
+dump_entry_exit_list (int indent, unsigned count, OTF_EntryExitRecord *rec)
+{
+  int i;
+
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(EntryExitRecord (%d)", i);
+      indent++;
+      dump_anchor (indent, &rec[i].EntryAnchor);
+      dump_anchor (indent, &rec[i].EntryAnchor);
+      printf (")");
+      indent--;
+    }
+}
+
+static void
 dump_mark_array (int indent, OTF_MarkArray *array)
 {
   int i;
@@ -621,13 +715,14 @@ dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count)
 
   IPRINT ("(ChainClassSetCount %d)", count);
   for (i = 0; i < count; i++)
-    {
-      IPRINT ("(ChainClassSet (%d)", i);
-      dump_chain_class_rule_list (indent + 1,
-                                 set[i].ChainClassRule,
-                                 set[i].ChainClassRuleCnt);
-      printf (")");
-    }
+    if (set[i].offset)
+      {
+       IPRINT ("(ChainClassSet (%d)", i);
+       dump_chain_class_rule_list (indent + 1,
+                                   set[i].ChainClassRule,
+                                   set[i].ChainClassRuleCnt);
+       printf (")");
+      }
 }
 
 
@@ -647,13 +742,13 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 1:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(DeltaGlyhpID #x%04X)",
                  subtable->u.single1.DeltaGlyphID);
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute,
                          subtable->u.single2.GlyphCount);
        }
@@ -664,7 +759,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 2:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_sequence_list (indent,
                              subtable->u.multiple1.Sequence,
                              subtable->u.multiple1.SequenceCount);
@@ -676,7 +771,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 3:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet,
                                   subtable->u.alternate1.AlternateSetCount);
        }
@@ -687,10 +782,11 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 4:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
-         dump_ligature_set_list (indent,
+         int *char_list = dump_coverage (indent, NULL, &subtable->Coverage);
+         dump_ligature_set_list (indent, char_list,
                                  subtable->u.ligature1.LigatureSet,
                                  subtable->u.ligature1.LigSetCount);
+         free (char_list);
        }
       else
        printf (" invalid");
@@ -699,13 +795,13 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 5:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_rule_set_list (indent, subtable->u.context1.RuleSet,
                              subtable->u.context1.RuleSetCount); 
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
          dump_class_set_list (indent, subtable->u.context2.ClassSet,
                               subtable->u.context2.ClassSetCnt);
@@ -726,7 +822,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 6:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_chain_rule_set_list
            (indent,
             subtable->u.chain_context1.ChainRuleSet,
@@ -734,7 +830,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_class_def (indent, "BacktrackClassDef",
                          &subtable->u.chain_context2.BacktrackClassDef);
          dump_class_def (indent, "InputClassDef",
@@ -770,8 +866,17 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
       break;
 
     case 7:
+      IPRINT ("(ExtensionLookupType %d)",
+             subtable->u.extension1.ExtensionLookupType);
+      IPRINT ("(ExtensionOffset %d)",
+             subtable->u.extension1.ExtensionOffset);
+      dump_lookup_subtable_gsub (indent, index, 
+                                subtable->u.extension1.ExtensionLookupType,
+                                subtable->u.extension1.ExtensionSubtable);
+      break;
+
     case 8:
-      printf (" not-yet-substcount");
+      printf (" not-yet-supported");
       break;
 
     default:
@@ -812,7 +917,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 1:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(ValueFormat #x%04X)",
                  subtable->u.single1.ValueFormat);
          dump_value_record (indent, "Value", &subtable->u.single1.Value);
@@ -821,7 +926,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
        {
          int i;
 
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(ValueFormat #x%04X)",
                  subtable->u.single2.ValueFormat);
          IPRINT ("(ValueCount %d)",
@@ -836,11 +941,17 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 2:
       if (subtable->Format == 1)
        {
-         printf (" not-yet-supported");
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         IPRINT ("(ValueFormat1 #x%04X)",
+                 subtable->u.pair1.ValueFormat1);
+         IPRINT ("(ValueFormat2 #x%04X)",
+                 subtable->u.pair1.ValueFormat2);
+         dump_pair_set_list (indent, subtable->u.pair1.PairSetCount,
+                             subtable->u.pair1.PairSet);
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(ValueFormat1 #x%04X)",
                  subtable->u.pair2.ValueFormat1);
          IPRINT ("(ValueFormat2 #x%04X)",
@@ -865,7 +976,9 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 3:
       if (subtable->Format == 1)
        {
-         printf (" not-yet-supported");
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_entry_exit_list (indent, subtable->u.cursive1.EntryExitCount,
+                               subtable->u.cursive1.EntryExitRecord);
        }
       else
        printf (" invalid");
@@ -874,9 +987,9 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 4:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, "Mark", &subtable->Coverage);
-         dump_coverage (indent, "Base",
-                        &subtable->u.mark_base1.BaseCoverage);
+         free (dump_coverage (indent, "Mark", &subtable->Coverage));
+         free (dump_coverage (indent, "Base",
+                              &subtable->u.mark_base1.BaseCoverage));
          IPRINT ("(ClassCount %d)",
                  subtable->u.mark_base1.ClassCount);
          dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
@@ -888,7 +1001,38 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 5:
       if (subtable->Format == 1)
        {
-         printf (" not-yet-supported");
+         OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
+         int i, j, k;
+
+         free (dump_coverage (indent, "Mark", &subtable->Coverage));
+         free (dump_coverage (indent, "Ligature",
+                              &mark_lig1->LigatureCoverage));
+         IPRINT ("(ClassCount %d)", mark_lig1->ClassCount);
+         dump_mark_array (indent, &mark_lig1->MarkArray);
+         IPRINT ("(LigatureArray (%d)",
+                 mark_lig1->LigatureArray.LigatureCount);
+         indent++;
+         for (i = 0; i < mark_lig1->LigatureArray.LigatureCount; i++)
+           {
+             OTF_LigatureAttach *attach
+               = mark_lig1->LigatureArray.LigatureAttach + i;
+
+             IPRINT ("(LigatureAttach (%d)", attach->ComponentCount);
+             indent++;
+             for (j = 0; j < attach->ComponentCount; j++)
+               {
+                 OTF_ComponentRecord *rec = attach->ComponentRecord + j;
+
+                 IPRINT ("(LigatureAnchor (%d)", mark_lig1->ClassCount);
+                 for (k = 0; k < mark_lig1->ClassCount; k++)
+                   if (rec->LigatureAnchor[k].AnchorFormat)
+                     dump_anchor (indent + 1, rec->LigatureAnchor + k);
+                 printf (")");
+               }
+             printf (")");
+             indent--;
+           }
+         printf (")");
        }
       else
        printf (" invalid");
@@ -897,9 +1041,9 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 6:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, "Mark1", &subtable->Coverage);
-         dump_coverage (indent, "Mark2",
-                        &subtable->u.mark_mark1.Mark2Coverage);
+         free (dump_coverage (indent, "Mark1", &subtable->Coverage));
+         free (dump_coverage (indent, "Mark2",
+                              &subtable->u.mark_mark1.Mark2Coverage));
          IPRINT ("(ClassCount %d)",
                  subtable->u.mark_mark1.ClassCount);
          dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
@@ -913,13 +1057,13 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 7:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_rule_set_list (indent, subtable->u.context1.RuleSet,
                              subtable->u.context1.RuleSetCount); 
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
          dump_class_set_list (indent, subtable->u.context2.ClassSet,
                               subtable->u.context2.ClassSetCnt);
@@ -940,7 +1084,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
     case 8:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_chain_rule_set_list
            (indent,
             subtable->u.chain_context1.ChainRuleSet,
@@ -948,7 +1092,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_class_def (indent, "BacktrackClassDef",
                          &subtable->u.chain_context2.BacktrackClassDef);
          dump_class_def (indent, "InputClassDef",
@@ -982,6 +1126,21 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type,
       else
        printf (" invalid");
       break;
+
+    case 9:
+      if (subtable->Format == 1)
+       {
+         IPRINT ("(ExtensionLookupType %d)",
+                 subtable->u.extension1.ExtensionLookupType);
+         IPRINT ("(ExtensionOffset %d)",
+                 subtable->u.extension1.ExtensionOffset);
+         dump_lookup_subtable_gpos
+           (indent, index, 
+            subtable->u.extension1.ExtensionLookupType,
+            subtable->u.extension1.ExtensionSubtable);
+       }
+      else
+       printf (" invalid");
     }
   printf (")");
 }
@@ -1047,7 +1206,7 @@ dump_lig_caret_list (int indent, OTF_LigCaretList *list)
 
   IPRINT ("(LigCaretList");
   indent++;
-  dump_coverage (indent, NULL, &list->Coverage);
+  free (dump_coverage (indent, NULL, &list->Coverage));
   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
   for (i = 0; i < list->LigGlyphCount; i++)
     {
@@ -1202,6 +1361,75 @@ dump_cmap_table (int indent, OTF_cmap *cmap)
            printf (")");
          }
          break;
+
+       case 12:
+         {
+           OTF_EncodingSubtable12 *sub12
+             = cmap->EncodingRecord[i].subtable.f.f12;
+           int j;
+
+           for (j = 0; j < sub12->nGroups; j++)
+             {
+               IPRINT ("(Group (#x%X) (startChar #x%04X) (endChar #x%04X) (startGlyphID #x%X))",
+                       j,
+                       sub12->Groups[j].startCharCode,
+                       sub12->Groups[j].endCharCode,
+                       sub12->Groups[j].startGlyphID);
+             }
+         }
+         break;
+
+       case 14:
+         {
+           OTF_EncodingSubtable14 *sub14
+             = cmap->EncodingRecord[i].subtable.f.f14;
+           unsigned j,k;
+
+           IPRINT ("(VariationSelectorRecords %d)",sub14->nRecords);
+           for (j = 0; j < sub14->nRecords; j++)
+             {
+               OTF_VariationSelectorRecord *record = sub14->Records + j;
+               IPRINT ("(VariationSelectorRecord (varSelector #x%x)",
+                       record->varSelector);
+               indent += 1;
+               IPRINT ("(defaultUVSOffset #x%x)",
+                       record->defaultUVSOffset);
+               if (record->defaultUVSOffset) 
+                 {
+                   IPRINT ("(defaultUVS");
+                   indent += 1;
+                   for (k = 0 ; k < record->numUnicodeValueRanges; k++)
+                     {
+                       OTF_UnicodeValueRange *unicodeValueRange
+                         = &record->unicodeValueRanges[k];
+                       IPRINT("(startUnicodeValue #x%x) (additionalCount %d)",
+                              unicodeValueRange->startUnicodeValue,
+                              unicodeValueRange->additionalCount);
+                     }
+                   printf (")");
+                   indent -= 1;
+                 }
+               IPRINT ("(nonDefaultUVSOffset #x%x)",
+                       record->nonDefaultUVSOffset);
+               if (record->nonDefaultUVSOffset) 
+                 {
+                   IPRINT ("(NonDefaultUVS");
+                   indent += 1;
+                   for (k=0; k < record->numUVSMappings; k++)
+                     {
+                       OTF_UVSMapping *uvsMapping
+                         = &record->uvsMappings[k];
+                       IPRINT("(unicodeValue #x%x) (glyphID %d)",
+                              uvsMapping->unicodeValue,
+                              uvsMapping->glyphID);
+                     }
+                   printf (")");
+                   indent -= 1;
+                 }
+               printf (")");
+               indent -= 1;
+             }
+         }
        }
 
       indent -= 2;
@@ -1280,10 +1508,10 @@ main (int argc, char **argv)
 {
   OTF *otf;
 
-  if (argc != 2)
+  if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
     {
-      fprintf (stderr, "Usage, dtfdump OTF-FILE");
-      exit (1);
+      fprintf (stderr, "Usage: %s OTF-FILE\n", basename (argv[0]));
+      exit (argc != 2);
     }
   
   otf = OTF_open (argv[1]);