Improvements to OpenType-dumping code, based on changes in Qt by Lars

Fri Jul 25 20:12:00 2003  Owen Taylor  <otaylor@redhat.com>

        Improvements to OpenType-dumping code, based on
        changes in Qt by Lars Knoll.

        * pango/opentype/ottest.c: Tweak the debugging output,
        suppress some warnings.

        * pango/opentype/disasm.c: Add support for
        GSUB Context/Chain GPOS MarkBase lookups, improve
        output in various ways.
diff --git a/src/disasm.c b/src/disasm.c
index 1eda9cd..01e5fb8 100644
--- a/src/disasm.c
+++ b/src/disasm.c
@@ -32,9 +32,12 @@
 #define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d</" #fld ">\n", (strct)->fld)
 #define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u</" #fld ">\n", (strct)->fld)
 #define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#4x</" #fld ">\n", (strct)->fld)
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#4x</" #fld ">\n", (strct)->fld)
+#define DUMP_USHORT_ARRAY(strct,fld,cnt) Dump_UShort_Array ((strct)->fld, cnt, #fld, stream, indent, is_gsub);
 
 #define DEF_DUMP(type) static void Dump_ ## type (TTO_ ## type *type, FILE *stream, int indent, FT_Bool is_gsub)
 #define RECURSE(name, type, val) do {  DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, is_gsub); DUMP ("</" #name ">\n"); } while (0)
+#define RECURSE_NUM(name, i, type, val) do {  DUMP ("<" #name "> <!-- %d -->\n", i); Dump_ ## type (val, stream, indent + 1, is_gsub); DUMP ("</" #name ">\n"); } while (0)
 #define DUMP_VALUE_RECORD(val, frmt) do {  DUMP ("<ValueRecord>\n"); Dump_ValueRecord (val, stream, indent + 1, is_gsub, frmt); DUMP ("</ValueRecord>\n"); } while (0)
 
 static void
@@ -59,6 +62,19 @@
 }
 
 static void 
+Dump_UShort_Array (FT_UShort *array, int count, const char *name, FILE *stream, int indent, FT_Bool is_gsub) 
+{
+  int i;
+  
+  do_indent (stream, indent);
+
+  printf ("<%s>", name);
+  for (i = 0; i < count; i++)
+    printf ("%d%s", array[i], i == 0 ? "" : " ");
+  printf ("</%s>\n", name);
+}
+
+static void 
 Print_Tag (FT_ULong tag, FILE *stream)
 {
   fprintf (stream, "%c%c%c%c", 
@@ -94,7 +110,7 @@
       fprintf (stream, "<LangSysTag>");
       Print_Tag (Script->LangSysRecord[i].LangSysTag, stream);
       fprintf (stream, "</LangSysTag>\n");
-      RECURSE (LangSys, LangSys, &Script->LangSysRecord[i].LangSys);
+      RECURSE_NUM (LangSys, i, LangSys, &Script->LangSysRecord[i].LangSys);
     }
 }
 
@@ -110,7 +126,7 @@
       fprintf (stream, "<ScriptTag>");
       Print_Tag (ScriptList->ScriptRecord[i].ScriptTag, stream);
       fprintf (stream, "</ScriptTag>\n");
-      RECURSE (Script, Script, &ScriptList->ScriptRecord[i].Script);
+      RECURSE_NUM (Script, i, Script, &ScriptList->ScriptRecord[i].Script);
     }
 }
 
@@ -125,6 +141,22 @@
     DUMP("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);
 }
 
+DEF_DUMP (MarkRecord)
+{
+  DUMP_FUINT (MarkRecord, Class);
+  DUMP("<Anchor>%d</Anchor>\n", MarkRecord->MarkAnchor.PosFormat );
+}
+
+DEF_DUMP (MarkArray)
+{
+  int i;
+
+  DUMP_FUINT (MarkArray, MarkCount);
+
+  for (i=0; i < MarkArray->MarkCount; i++)
+    RECURSE_NUM (MarkRecord, i, MarkRecord, &MarkArray->MarkRecord[i]);
+}
+
 DEF_DUMP (FeatureList)
 {
   int i;
@@ -136,8 +168,8 @@
       do_indent (stream, indent);
       fprintf (stream, "<FeatureTag>");
       Print_Tag (FeatureList->FeatureRecord[i].FeatureTag, stream);
-      fprintf (stream, "</FeatureTag>\n");
-      RECURSE (Feature, Feature, &FeatureList->FeatureRecord[i].Feature);
+      fprintf (stream, "</FeatureTag> <!-- %d -->\n", i);
+      RECURSE_NUM (Feature, i, Feature, &FeatureList->FeatureRecord[i].Feature);
     }
 }
 
@@ -151,13 +183,86 @@
       DUMP_FUINT (&Coverage->cf.cf1, GlyphCount);
 
       for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++)
-	DUMP("<Glyph>%#4x</Glyph> <!-- %d -->\n", Coverage->cf.cf1.GlyphArray[i], i);
+	DUMP("<Glyph>%#4x</Glyph> <!-- %d -->\n",
+	     Coverage->cf.cf1.GlyphArray[i], i);
     }
   else
     {
+      int i;
+      DUMP_FUINT (&Coverage->cf.cf2, RangeCount);
+      
+      for ( i = 0; i < Coverage->cf.cf2.RangeCount; i++ )
+	  DUMP("<Glyph>%#4x - %#4x</Glyph> <!-- %d -->\n",
+	       Coverage->cf.cf2.RangeRecord[i].Start,
+	       Coverage->cf.cf2.RangeRecord[i].End);
     }
 }
 
+DEF_DUMP (ClassRangeRecord)
+{
+  DUMP_FGLYPH (ClassRangeRecord, Start);
+  DUMP_FGLYPH (ClassRangeRecord, End);
+  DUMP_FUINT (ClassRangeRecord, Class);
+}
+     
+DEF_DUMP (ClassDefinition)
+{
+  DUMP_FUINT( ClassDefinition, ClassFormat);
+  DUMP_FUINT( ClassDefinition, loaded);
+
+  if (ClassDefinition->ClassFormat == 1)
+    {
+      int i;
+      TTO_ClassDefFormat1 *ClassDefFormat1 = &ClassDefinition->cd.cd1;
+      DUMP("<ClassDefinition>\n");
+      DUMP_FUINT (ClassDefFormat1, StartGlyph );
+      DUMP_FUINT (ClassDefFormat1, GlyphCount );
+      for (i = 0; i < ClassDefFormat1->GlyphCount; i++)
+	DUMP(" <Class>%d</Class> <!-- %#4x -->", ClassDefFormat1->ClassValueArray[i],
+	     ClassDefFormat1->StartGlyph+i );
+    }
+  else if (ClassDefinition->ClassFormat == 2)
+    {
+      int i;
+      TTO_ClassDefFormat2 *ClassDefFormat2 = &ClassDefinition->cd.cd2;
+      DUMP_FUINT (ClassDefFormat2, ClassRangeCount);
+      
+      for (i = 0; i < ClassDefFormat2->ClassRangeCount; i++)
+	RECURSE_NUM (ClassRangeRecord, i, ClassRangeRecord, &ClassDefFormat2->ClassRangeRecord[i]);
+    }
+  else
+    printf("invalid class def table!!!\n");
+}
+
+DEF_DUMP (SubstLookupRecord)
+{
+  DUMP_FUINT (SubstLookupRecord, SequenceIndex);
+  DUMP_FUINT (SubstLookupRecord, LookupListIndex);
+}
+
+DEF_DUMP (ChainSubClassRule)
+{
+  int i;
+
+  DUMP_USHORT_ARRAY (ChainSubClassRule, Backtrack, ChainSubClassRule->BacktrackGlyphCount);
+  DUMP_USHORT_ARRAY (ChainSubClassRule, Input, ChainSubClassRule->InputGlyphCount - 1);
+  DUMP_USHORT_ARRAY (ChainSubClassRule, Lookahead, ChainSubClassRule->LookaheadGlyphCount);
+  
+  for (i = 0; i < ChainSubClassRule->SubstCount; i++)
+    RECURSE_NUM (SubstLookupRecord, i, SubstLookupRecord, &ChainSubClassRule->SubstLookupRecord[i]);
+
+  indent--;
+}
+
+DEF_DUMP (ChainSubClassSet)
+{
+  int i;
+  
+  DUMP_FUINT( ChainSubClassSet, ChainSubClassRuleCount );
+  for (i = 0; i < ChainSubClassSet->ChainSubClassRuleCount; i++)
+    RECURSE_NUM (ChainSubClassRule, i, ChainSubClassRule, &ChainSubClassSet->ChainSubClassRule[i]);
+}
+
 static void
 Dump_GSUB_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
 {
@@ -198,7 +303,7 @@
   DUMP_FUINT (LigatureSet, LigatureCount);
 
   for (i=0; i < LigatureSet->LigatureCount; i++)
-    RECURSE (Ligature, Ligature, &LigatureSet->Ligature[i]);
+    RECURSE_NUM (Ligature, i, Ligature, &LigatureSet->Ligature[i]);
 }
 
 static void
@@ -213,7 +318,95 @@
   DUMP_FUINT (LigatureSubst, LigatureSetCount);
 
   for (i=0; i < LigatureSubst->LigatureSetCount; i++)
-    RECURSE (LigatureSet, LigatureSet, &LigatureSubst->LigatureSet[i]);
+    RECURSE_NUM (LigatureSet, i, LigatureSet, &LigatureSubst->LigatureSet[i]);
+}
+
+DEF_DUMP (ContextSubstFormat1)
+{
+  DUMP("Not implemented!!!\n");
+}
+
+DEF_DUMP (ContextSubstFormat2)
+{
+  DUMP_FUINT (ContextSubstFormat2, MaxContextLength);
+  RECURSE (Coverage, Coverage, &ContextSubstFormat2->Coverage);
+  RECURSE (ClassDefinition, ClassDefinition, &ContextSubstFormat2->ClassDef);
+}
+
+DEF_DUMP (ContextSubstFormat3)
+{
+  DUMP("Not implemented!!!\n");
+}
+
+static void
+Dump_GSUB_Lookup_Context (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+{
+  TTO_ContextSubst *ContextSubst = &subtable->st.gsub.context;
+
+  DUMP_FUINT (ContextSubst, SubstFormat);
+  switch( ContextSubst->SubstFormat )
+    {
+    case 1:
+      Dump_ContextSubstFormat1 (&ContextSubst->csf.csf1, stream, indent+2, is_gsub);
+      break;
+    case 2:
+      Dump_ContextSubstFormat2 (&ContextSubst->csf.csf2, stream, indent+2, is_gsub);
+      break;
+    case 3:
+      Dump_ContextSubstFormat3 (&ContextSubst->csf.csf3, stream, indent+2, is_gsub);
+      break;
+    default:
+      printf("invalid subformat!!!!!\n");
+    }
+}
+
+DEF_DUMP (ChainContextSubstFormat1)
+{
+  DUMP("Not implemented!!!\n");
+}
+
+DEF_DUMP (ChainContextSubstFormat2)
+{
+  int i;
+  
+  RECURSE (Coverage, Coverage, &ChainContextSubstFormat2->Coverage);
+  DUMP_FUINT (ChainContextSubstFormat2, MaxBacktrackLength);
+  RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->BacktrackClassDef);
+  DUMP_FUINT (ChainContextSubstFormat2, MaxInputLength);
+  RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->InputClassDef);
+  DUMP_FUINT (ChainContextSubstFormat2, MaxLookaheadLength);
+  RECURSE (ClassDefinition, ClassDefinition, &ChainContextSubstFormat2->LookaheadClassDef);
+  
+  DUMP_FUINT (ChainContextSubstFormat2, ChainSubClassSetCount);
+  for (i = 0; i < ChainContextSubstFormat2->ChainSubClassSetCount; i++)
+    RECURSE (ChainSubClassSet, ChainSubClassSet, &ChainContextSubstFormat2->ChainSubClassSet[i]);
+}
+
+DEF_DUMP (ChainContextSubstFormat3)
+{
+  DUMP("Not implemented!!!\n");
+}
+
+static void
+Dump_GSUB_Lookup_Chain (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+{
+  TTO_ChainContextSubst *chain = &subtable->st.gsub.chain;
+  
+  DUMP_FUINT (chain, SubstFormat);
+  switch (chain->SubstFormat)
+    {
+    case 1:
+      Dump_ChainContextSubstFormat1 (&chain->ccsf.ccsf1, stream, indent+2, is_gsub);
+      break;
+    case 2:
+      Dump_ChainContextSubstFormat2 (&chain->ccsf.ccsf2, stream, indent+2, is_gsub);
+      break;
+    case 3:
+      Dump_ChainContextSubstFormat3 (&chain->ccsf.ccsf3, stream, indent+2, is_gsub);
+      break;
+    default:
+      printf("invalid subformat!!!!!\n");
+    }
 }
 
 static void
@@ -359,6 +552,36 @@
     }
 }
 
+static void
+Dump_GPOS_Lookup_Markbase (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+{
+  int i;
+  TTO_MarkBasePos *markbase = &subtable->st.gpos.markbase;
+  
+  DUMP_FUINT (markbase, PosFormat);
+  RECURSE (Coverage, Coverage, &markbase->MarkCoverage);
+  RECURSE (Coverage, Coverage, &markbase->BaseCoverage);
+  DUMP_FUINT (markbase, ClassCount);
+  RECURSE (MarkArray, MarkArray, &markbase->MarkArray);
+  
+  DUMP ("<BaseArray>\n");
+  indent++;
+  
+  DUMP_FUINT (&markbase->BaseArray, BaseCount);
+  for (i = 0; i < markbase->BaseArray.BaseCount; i++)
+    {
+      int j;
+      TTO_BaseRecord *r = &markbase->BaseArray.BaseRecord[i];
+      DUMP ("<BaseRecord> <!-- %d -->\n",  i);
+      for (j = 0; j < markbase->ClassCount; j++)
+	DUMP ("  <Anchor>%d</Anchor>\n", r->BaseAnchor->PosFormat);
+      DUMP ("<BaseRecord>\n");
+    }
+  
+  indent--;
+  DUMP ("</BaseArray>\n");
+}
+
 DEF_DUMP (Lookup)
 {
   int i;
@@ -385,9 +608,11 @@
 	  break;
 	case  GSUB_LOOKUP_CONTEXT:
 	  lookup_name = "CONTEXT";
+	  lookup_func = Dump_GSUB_Lookup_Context;
 	  break;
 	case  GSUB_LOOKUP_CHAIN:
 	  lookup_name = "CHAIN";
+	  lookup_func = Dump_GSUB_Lookup_Chain;
 	  break;
 	}
     }
@@ -408,6 +633,7 @@
 	  break;
 	case GPOS_LOOKUP_MARKBASE:
 	  lookup_name = "MARKBASE";
+	  lookup_func = Dump_GPOS_Lookup_Markbase;
 	  break;
 	case GPOS_LOOKUP_MARKLIG:
 	  lookup_name = "MARKLIG";
@@ -442,7 +668,7 @@
   DUMP_FUINT (LookupList, LookupCount);
 
   for (i=0; i < LookupList->LookupCount; i++)
-    RECURSE (Lookup, Lookup, &LookupList->Lookup[i]);
+    RECURSE_NUM (Lookup, i, Lookup, &LookupList->Lookup[i]);
 }
 
 void