*** empty log message ***
[m17n/libotf.git] / example / otfdump.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7
8 #include <otf.h>
9
10 char *indent_spaces[] =
11   { "", "  ", "    ", "      ", "        ", "          ", "            ",
12     "              ",  "                ",  "                  " };
13
14 /* Indented print.  */
15 #define IPRINT printf("\n%s", indent_spaces[indent]), printf
16
17 static void
18 dump_tag (OTF_Tag tag)
19 {
20   printf ("(tag \"");
21   putchar (tag >> 24);
22   putchar ((tag >> 16) & 0xFF);
23   putchar ((tag >> 8) & 0xFF);
24   putchar (tag & 0xFF);
25   printf ("\" #x%04X)", tag);
26 }
27
28 /* HEAD */
29
30 static void
31 dump_offset_table (int indent, OTF_OffsetTable *table)
32 {
33   IPRINT ("(OffsetTable");
34   indent++;
35   IPRINT ("(sfnt-version %d.%d)", 
36           table->sfnt_version.high, table->sfnt_version.low);
37   IPRINT ("(numTables %d)", table->numTables);
38   IPRINT ("(searchRange %d)", table->searchRange);
39   IPRINT ("(enterSelector %d)", table->enterSelector);
40   IPRINT ("(rangeShift %d))", table->rangeShift);  
41 }
42
43 static void
44 dump_table_directory (int indent, OTF_TableDirectory *table, int idx)
45 {
46   IPRINT ("(Table %d ", idx);
47   dump_tag (table->tag);
48   indent++;
49   IPRINT ("(checkSum %08X) (offset #x%08X) (length: #x%08X))",
50           table->checkSum, table->offset, table->length);
51 }
52
53 \f
54
55 /* head */
56 static void
57 dump_head_table (int indent, OTF_head *head)
58 {
59   IPRINT ("(head");
60   indent++;
61   IPRINT ("(TableVersionNumber %d.%d)",
62           head->TableVersionNumber.high, head->TableVersionNumber.low);
63   IPRINT ("(fontRevision %d.%d)",
64           head->fontRevision.high, head->fontRevision.low);
65   IPRINT ("(checkSumAdjustment #x%04X)", head->checkSumAdjustment);
66   IPRINT ("(magicNumber #x%04X)", head->magicNumber);
67   IPRINT ("(flags #x%04X)", head->flags);
68   IPRINT ("(unitsPerEm %d)", head->unitsPerEm);
69   printf (")");
70 }
71
72 \f
73 /* COMMON */
74
75 static void
76 dump_glyph_ids (OTF_GlyphID *ids, unsigned num)
77 {
78   while (num-- > 0)
79     {
80       printf (" #x%04X", *ids);
81       ids++;
82     }
83 }
84
85 static void
86 dump_coverage (int indent, char *title, OTF_Coverage *coverage)
87 {
88   int i;
89
90   IPRINT ("(%sCoverage (CoverageFormat %d)",
91           (title ? title : ""), coverage->CoverageFormat);
92   indent++;
93   if (coverage->CoverageFormat == 1)
94     {
95       IPRINT ("(GlyphCount %d)", coverage->Count);
96       IPRINT ("(GlyphArray");
97       dump_glyph_ids (coverage->table.GlyphArray, coverage->Count);
98       printf (")");
99     }
100   else
101     {
102       IPRINT ("(RangeCount %d)", coverage->Count);
103       indent++;
104       for (i = 0; i < coverage->Count; i++)
105         {
106           IPRINT ("(Range (%d) (Start #x%04X) (End #x%04X)", i,
107                   coverage->table.RangeRecord[i].Start,
108                   coverage->table.RangeRecord[i].End);
109           indent++;
110           IPRINT ("(StartCoverageIndex %d))",
111                   coverage->table.RangeRecord[i].StartCoverageIndex);
112           indent--;
113         }
114     }
115   printf (")");
116 }
117
118 static void
119 dump_coverage_list (int indent, char *title,
120                     OTF_Coverage *coverage, unsigned num)
121 {
122   int i;
123
124   IPRINT ("(%s %d)", title, num);
125   for (i = 0; i < num; i++)
126     dump_coverage (indent, NULL, coverage + i);
127 }
128
129
130 static void
131 dump_language_system (int indent, int index, OTF_Tag tag, OTF_Offset offset,
132                       OTF_LangSys *langsys)
133 {
134   int i;
135
136   IPRINT ("(LangSys ");
137   if (index >= 0)
138     printf ("(%d) ", index);
139   if (tag)
140     dump_tag (tag);
141   else
142     printf ("DefaultLangSys");
143   printf (" (Offset #x%04X)", offset);
144   indent++;
145   IPRINT ("(LookupOrder #x%04X)", langsys->LookupOrder);
146   IPRINT ("(ReqFeatureIndex %d)", langsys->ReqFeatureIndex);
147   IPRINT ("(FeatureCount %d)", langsys->FeatureCount);
148   if (langsys->FeatureCount)
149     {
150       IPRINT ("(FeatureIndex");
151       for (i = 0; i < langsys->FeatureCount; i++)
152         printf (" %d", langsys->FeatureIndex[i]);
153       printf (")");
154     }
155   printf (")");
156 }
157
158 static void
159 dump_script_list (int indent, OTF_ScriptList *list)
160 {
161   int i, j;
162
163   IPRINT ("(ScriptList (count %d)", list->ScriptCount);
164   indent++;
165   for (i = 0; i < list->ScriptCount; i++)
166     {
167       OTF_Script *script = list->Script + i;
168
169       IPRINT ("(Script (%d) ", i);
170       dump_tag (list->Script[i].ScriptTag);
171       printf (" (Offset #x%04X)", list->Script[i].offset);
172       indent++;
173       IPRINT ("(DefaultLangSysOffset #x%04X)",
174               script->DefaultLangSysOffset);
175       if (script->DefaultLangSysOffset)
176         dump_language_system (indent, -1, 0,
177                               script->DefaultLangSysOffset,
178                               &script->DefaultLangSys);
179       IPRINT ("(LangSysCount %d)", script->LangSysCount);
180       for (j = 0; j < script->LangSysCount; j++)
181         dump_language_system (indent, j,
182                               script->LangSysRecord[j].LangSysTag,
183                               script->LangSysRecord[j].LangSys,
184                               script->LangSys + j);
185       printf (")");
186       indent--;
187     }
188   printf (")");
189 }
190
191 static void
192 dump_feature_list (int indent, OTF_FeatureList *list)
193 {
194   int i, j;
195   
196   IPRINT ("(FeatureList (count %d)", list->FeatureCount);
197   indent++;
198   for (i = 0; i < list->FeatureCount; i++)
199     {
200       OTF_Feature *feature = list->Feature + i;
201
202       IPRINT ("(Feature (%d) ", i);
203       dump_tag (list->Feature[i].FeatureTag);
204       printf (" (Offset #x%04X)", list->Feature[i].offset);
205       printf (" (LookupCount %d)", feature->LookupCount);
206       if (feature->LookupCount)
207         {
208           indent++;
209           IPRINT ("(LookupListIndex");
210           for (j = 0; j < feature->LookupCount; j++)
211             printf (" %d", feature->LookupListIndex[j]);
212           printf (")");
213           indent--;
214         }
215       printf (")");
216     }
217   printf (")");
218 }
219
220 static void
221 dump_class_def (int indent, char *title, OTF_ClassDef *class)
222 {
223   IPRINT ("(%s (offset #x%04X) (ClassFormat %d)",
224           (title ? title : "ClassDef"),
225           class->offset, class->ClassFormat);
226   indent++;
227   if (class->ClassFormat == 1)
228     {
229       IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph);
230       IPRINT ("(GlyphCount %d)", class->f.f1.GlyphCount);
231       IPRINT ("(ClassValueArray");
232       dump_glyph_ids ((OTF_GlyphID *) class->f.f1.ClassValueArray,
233                       class->f.f1.GlyphCount);
234       printf (")");
235     }
236   else if (class->ClassFormat == 2)
237     {
238       int i;
239
240       IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount);
241       IPRINT ("(ClassRangeRecord");
242       indent++;
243       for (i = 0; i < class->f.f2.ClassRangeCount; i++)
244         IPRINT ("((Start #x%04X) (End #x%04X) (class %d))",
245                 class->f.f2.ClassRangeRecord[i].Start,
246                 class->f.f2.ClassRangeRecord[i].End,
247                 class->f.f2.ClassRangeRecord[i].Class);
248       printf (")");
249     }
250   else
251     printf ("UknownClassFormat");
252   printf (")");
253 }
254
255 static void
256 dump_device_table (int indent, char *title, OTF_DeviceTable *table)
257 {
258   int i;
259
260   if (! table->offset)
261     return;
262   IPRINT ("(%s (offset #x%04X)", title, table->offset);
263   indent++;
264   IPRINT ("(StartSize %d) (EndSize %d) (DeltaFormat %d)",
265           table->StartSize, table->EndSize, table->DeltaFormat);
266   IPRINT ("(DeltaValue");
267   for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
268     printf (" %d", table->DeltaValue[i]);
269   printf ("))");
270 }
271
272 \f
273
274 static void
275 dump_value_record (int indent, char *title, OTF_ValueRecord *rec)
276 {
277   IPRINT ("(%s %d %d %d %d", title,
278           rec->XPlacement, rec->YPlacement, rec->XAdvance, rec->YAdvance);
279   indent++;
280   if (rec->XPlaDevice.offset)
281     dump_device_table (indent, "XPlaDevice", &rec->XPlaDevice);
282   if (rec->YPlaDevice.offset)
283     dump_device_table (indent, "YPlaDevice", &rec->YPlaDevice);
284   if (rec->XAdvDevice.offset)
285     dump_device_table (indent, "XAdvDevice", &rec->XAdvDevice);
286   if (rec->YAdvDevice.offset)
287     dump_device_table (indent, "YAdvDevice", &rec->YAdvDevice);
288   printf (")");
289 }
290
291
292 static void
293 dump_sequence_list (int indent, OTF_Sequence *sequence, unsigned num)
294 {
295   int i;
296   IPRINT ("(SequenceCount %d)", num);
297
298   for (i = 0; i < num; i++)
299     {
300       IPRINT ("(Sequence (%d) (offset #x%04X)",
301               i, sequence[i].offset);
302       indent++;
303       IPRINT ("(GlyphCount %d)", sequence[i].GlyphCount);
304       IPRINT ("(Substitute");
305       dump_glyph_ids (sequence[i].Substitute, sequence[i].GlyphCount);
306       printf ("))");
307       indent--;
308     }
309 }
310
311 static void
312 dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
313 {
314   int i, j;
315
316   IPRINT ("(LigSetCount %d)", num);
317   for (i = 0; i < num; i++)
318     {
319       IPRINT ("(LigatureSet (%d) (offset #x%04X) (count %d)",
320               i, ligset[i].offset, ligset[i].LigatureCount);
321       indent++;
322       for (j = 0; j < ligset[i].LigatureCount; j++)
323         {
324           IPRINT ("(Ligature (%d) (offset #x%04X)",
325                   j, ligset[i].Ligature[j].offset);
326           indent++;
327           IPRINT ("(LigGlyph #x%04X)",
328                   ligset[i].Ligature[j].LigGlyph);
329           IPRINT ("(ComCount %d)",
330                   ligset[i].Ligature[j].CompCount);
331           IPRINT ("(Component");
332           dump_glyph_ids (ligset[i].Ligature[j].Component,
333                           ligset[i].Ligature[j].CompCount - 1);
334           printf ("))");
335           indent--;
336         }
337       indent--;
338       printf (")");
339     }
340 }
341
342 static void
343 dump_class1_record_list (int indent,
344                          unsigned Class1Count, unsigned Class2Count,
345                          OTF_Class1Record *rec)
346 {
347   int i, j;
348
349   for (i = 0; i < Class1Count; i++)
350     {
351       IPRINT ("(Class1Record (%d)", i);
352       indent++;
353       for (j = 0; j < Class2Count; j++)
354         {
355           IPRINT ("(Class2Record (%d)", j);
356           indent++;
357           dump_value_record (indent, "Value1", &rec[i].Class2Record[j].Value1);
358           dump_value_record (indent, "Value2", &rec[i].Class2Record[j].Value2);
359           printf (")");
360           indent--;
361         }
362       printf (")");
363       indent--;
364     }
365 }
366
367 static void
368 dump_anchor (int indent, OTF_Anchor *anchor)
369 {
370   IPRINT ("(Anchor (offset #x%04X) (AnchorFormat %d)",
371           anchor->offset, anchor->AnchorFormat);
372   indent++;
373   IPRINT ("(XCoordinate %d) (YCoordinate %d)",
374           anchor->XCoordinate, anchor->YCoordinate);
375   if (anchor->AnchorFormat == 1)
376     ;
377   else if (anchor->AnchorFormat == 2)
378     IPRINT ("(AnchorPoint %d)", anchor->f.f1.AnchorPoint);
379   else
380     {
381       dump_device_table (indent, "XDeviceTable", &anchor->f.f2.XDeviceTable);
382       dump_device_table (indent, "YDeviceTable", &anchor->f.f2.YDeviceTable);
383     }
384   printf (")");
385 }
386
387 static void
388 dump_mark_array (int indent, OTF_MarkArray *array)
389 {
390   int i;
391
392   IPRINT ("(MarkArray (MarkCount %d)", array->MarkCount);
393   indent++;
394   for (i = 0; i < array->MarkCount; i++)
395     {
396       IPRINT ("(MarkRecord (%d) (Class %d)", i, array->MarkRecord[i].Class);
397       dump_anchor (indent + 1, &array->MarkRecord[i].MarkAnchor);
398       printf (")");
399     }
400   printf (")");
401 }
402
403 static void
404 dump_base_array (int indent, unsigned ClassCount, OTF_BaseArray *array)
405 {
406   int i, j;
407
408   IPRINT ("(BaseArray (BaseCount %d)", array->BaseCount);
409   indent++;
410   for (i = 0; i < array->BaseCount; i++)
411     {
412       IPRINT ("(BaseRecord (%d) ", i);
413       for (j = 0; j < ClassCount; j++)
414         dump_anchor (indent + 1, array->BaseRecord[i].BaseAnchor + j);
415       printf (")");
416     }
417   printf (")");
418 }
419
420
421 static void
422 dump_subst_lookup_record_list (int indent,
423                                OTF_SubstLookupRecord *rec, unsigned num)
424 {
425   int i;
426
427   IPRINT ("(SubstCount %d)", num);
428   for (i = 0; i < num; i++)
429     {
430       IPRINT ("(SubstLookupRecord (%d)", i);
431       indent++;
432       IPRINT ("(SequenceIndex %d)", rec[i].SequenceIndex);
433       IPRINT ("(LookupListIndex %d))", rec[i].LookupListIndex);
434       indent--;
435     }
436 }
437
438
439 static void dump_lookup_subtable_gsub (int indent, int index, unsigned type,
440                                        OTF_LookupSubTable *subtable);
441 static void dump_lookup_subtable_gpos (int indent, int index, unsigned type,
442                                        OTF_LookupSubTable *subtable);
443
444
445 static void
446 dump_lookup_list (int indent, OTF_LookupList *list, int gsub)
447 {
448   int i, j;
449
450   IPRINT ("(LookupList (count %d)", list->LookupCount);
451   indent++;
452   for (i = 0; i < list->LookupCount; i++)
453     {
454       OTF_Lookup *lookup = list->Lookup + i;
455
456       IPRINT ("(Lookup (%d) (Offset #x%04X)",
457               i, lookup->offset);
458       printf (" (Type %d) (Flag #x%04X) (SubTableCount %d)",
459               lookup->LookupType, lookup->LookupFlag, lookup->SubTableCount);
460       if (gsub)
461         for (j = 0; j < lookup->SubTableCount; j++)
462           dump_lookup_subtable_gsub (indent + 1, j,
463                                      lookup->LookupType, lookup->SubTable + j);
464       else
465         for (j = 0; j < lookup->SubTableCount; j++)
466           dump_lookup_subtable_gpos (indent + 1, j,
467                                      lookup->LookupType, lookup->SubTable + j);
468
469       printf (")");
470     }
471   printf (")");
472 }
473
474
475 \f
476 /* GSUB */
477
478 static void
479 dump_lookup_subtable_gsub (int indent, int index, unsigned type,
480                            OTF_LookupSubTable *subtable)
481 {
482   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
483   indent++;
484   switch (type)
485     {
486     case 1:
487       if (subtable->Format == 1)
488         {
489           dump_coverage (indent, NULL, &subtable->Coverage);
490           IPRINT ("(DeltaGlyhpID #x%04X)",
491                   subtable->sub.gsub.single1.DeltaGlyphID);
492         }
493       else if (subtable->Format == 2)
494         {
495           dump_coverage (indent, NULL, &subtable->Coverage);
496           IPRINT ("(GlyphCount %d)",
497                   subtable->sub.gsub.single2.GlyphCount);
498           IPRINT ("(Substitute");
499           dump_glyph_ids (subtable->sub.gsub.single2.Substitute,
500                           subtable->sub.gsub.single2.GlyphCount);
501           printf (")");
502         }
503       break;
504
505     case 2:
506       if (subtable->Format == 1)
507         {
508           dump_coverage (indent, NULL, &subtable->Coverage);
509           dump_sequence_list (indent,
510                               subtable->sub.gsub.multiple1.Sequence,
511                               subtable->sub.gsub.multiple1.SequenceCount);
512         }
513       break;
514       
515     case 4:
516       if (subtable->Format == 1)
517         {
518           dump_coverage (indent, NULL, &subtable->Coverage);
519           dump_ligature_set_list (indent,
520                                   subtable->sub.gsub.ligature1.LigatureSet,
521                                   subtable->sub.gsub.ligature1.LigSetCount);
522         }
523       break;
524
525     case 6:
526       if (subtable->Format == 1)
527         {
528 #if 0
529           read_coverage (fp, offset,
530                          &subtable->sub.gsub.chain_context1.Coverage);
531           subtable->sub.gsub.chain_context1.ChainSubRuleSetCount
532             = (read_chain_subrule_set
533                (fp, offset,
534                 &subtable->sub.gsub.chain_context1.ChainSubRuleSet));
535 #endif
536         }
537       else if (subtable->Format == 2)
538         {
539 #if 0
540           read_coverage (fp, offset,
541                          &subtable->sub.gsub.chain_context2.Coverage);
542           read_class_def (fp, offset,
543                           &subtable->sub.gsub.chain_context2.Backtrack);
544           read_class_def (fp, offset,
545                           &subtable->sub.gsub.chain_context2.Input);
546           read_class_def (fp, offset,
547                           &subtable->sub.gsub.chain_context2.LookAhead);
548           subtable->sub.gsub.chain_context2.ChainSubClassSetCnt
549             = (read_chain_subclass_set
550                (fp, offset,
551                 &subtable->sub.gsub.chain_context2.ChainSubClassSet));
552 #endif
553         }
554       else if (subtable->Format == 3)
555         {
556           dump_coverage_list
557             (indent, "BackTrackGlyphCount",
558              subtable->sub.gsub.chain_context3.Backtrack,
559              subtable->sub.gsub.chain_context3.BacktrackGlyphCount);
560           dump_coverage_list
561             (indent, "InputGlyphCount",
562              subtable->sub.gsub.chain_context3.Input,
563              subtable->sub.gsub.chain_context3.InputGlyphCount);
564           dump_coverage_list
565             (indent, "LookaheaGlyphCount",
566              subtable->sub.gsub.chain_context3.LookAhead,
567              subtable->sub.gsub.chain_context3.LookaheadGlyphCount);
568           dump_subst_lookup_record_list
569             (indent,
570              subtable->sub.gsub.chain_context3.SubstLookupRecord,
571              subtable->sub.gsub.chain_context3.SubstCount);
572         }
573       break;
574     }
575   printf (")");
576 }
577
578 static void
579 dump_gsub_table (int indent, OTF_GSUB *gsub)
580 {
581   IPRINT ("(GSUB");
582   indent++;
583   IPRINT ("(Header");
584   indent++;
585   IPRINT ("(Version %d.%d)", gsub->Version.high, gsub->Version.low);
586   IPRINT ("(ScriptList #x%04X)", gsub->ScriptList.offset);
587   IPRINT ("(FeatureList #x%04X)", gsub->FeatureList.offset);
588   IPRINT ("(LookupList #x%04X))", gsub->LookupList.offset);
589   indent--;
590   dump_script_list (indent, &gsub->ScriptList);
591   dump_feature_list (indent, &gsub->FeatureList);
592   dump_lookup_list (indent, &gsub->LookupList, 1);
593   printf (")");
594 }
595
596 \f
597 /* GPOS */
598
599 static void
600 dump_lookup_subtable_gpos (int indent, int index, unsigned type,
601                            OTF_LookupSubTable *subtable)
602 {
603   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
604   indent++;
605   switch (type)
606     {
607     case 1:
608 #if 0
609       if (subtable->Format == 1)
610         {
611           dump_coverage (indent, NULL, &subtable->sub.gpos.single1.Coverage);
612           IPRINT ("(DeltaGlyhpID #x%04X)",
613                   subtable->sub.gsub.single1.DeltaGlyphID);
614         }
615       else if (subtable->Format == 2)
616         {
617           dump_coverage (indent, NULL, &subtable->sub.gsub.single2.Coverage);
618           IPRINT ("(GlyphCount %d)",
619                   subtable->sub.gsub.single2.GlyphCount);
620           IPRINT ("(Substitute");
621           dump_glyph_ids (subtable->sub.gsub.single2.Substitute,
622                           subtable->sub.gsub.single2.GlyphCount);
623           printf (")");
624         }
625 #endif
626       break;
627
628     case 2:
629       if (subtable->Format == 1)
630         {
631           dump_coverage (indent, NULL, &subtable->Coverage);
632         }
633       else if (subtable->Format == 2)
634         {
635           dump_coverage (indent, NULL, &subtable->Coverage);
636           IPRINT ("(ValueFormat1 #x%04X)",
637                   subtable->sub.gpos.pair2.ValueFormat1);
638           IPRINT ("(ValueFormat2 #x%04X)",
639                   subtable->sub.gpos.pair2.ValueFormat2);
640           dump_class_def (indent, "ClassDef1",
641                           &subtable->sub.gpos.pair2.ClassDef1);
642           dump_class_def (indent, "ClassDef2",
643                           &subtable->sub.gpos.pair2.ClassDef2);
644           IPRINT ("(Class1Count %d)",
645                   subtable->sub.gpos.pair2.Class1Count);
646           IPRINT ("(Class2Count %d)",
647                   subtable->sub.gpos.pair2.Class2Count);
648           dump_class1_record_list (indent,
649                                    subtable->sub.gpos.pair2.Class1Count,
650                                    subtable->sub.gpos.pair2.Class2Count,
651                                    subtable->sub.gpos.pair2.Class1Record);
652         }
653       break;
654       
655     case 4:
656       if (subtable->Format == 1)
657         {
658           dump_coverage (indent, "Mark", &subtable->Coverage);
659           dump_coverage (indent, "Base",
660                          &subtable->sub.gpos.mark_base1.BaseCoverage);
661           IPRINT ("(ClassCount %d)",
662                   subtable->sub.gpos.mark_base1.ClassCount);
663           dump_mark_array (indent, &subtable->sub.gpos.mark_base1.MarkArray);
664           dump_base_array (indent, subtable->sub.gpos.mark_base1.ClassCount,
665                            &subtable->sub.gpos.mark_base1.BaseArray);
666         }
667       break;
668
669     case 6:
670       if (subtable->Format == 1)
671         {
672 #if 0
673           read_coverage (fp, offset,
674                          &subtable->sub.gsub.chain_context1.Coverage);
675           subtable->sub.gsub.chain_context1.ChainSubRuleSetCount
676             = (read_chain_subrule_set
677                (fp, offset,
678                 &subtable->sub.gsub.chain_context1.ChainSubRuleSet));
679 #endif
680         }
681       else if (subtable->Format == 2)
682         {
683 #if 0
684           read_coverage (fp, offset,
685                          &subtable->sub.gsub.chain_context2.Coverage);
686           read_class_def (fp, offset,
687                           &subtable->sub.gsub.chain_context2.Backtrack);
688           read_class_def (fp, offset,
689                           &subtable->sub.gsub.chain_context2.Input);
690           read_class_def (fp, offset,
691                           &subtable->sub.gsub.chain_context2.LookAhead);
692           subtable->sub.gsub.chain_context2.ChainSubClassSetCnt
693             = (read_chain_subclass_set
694                (fp, offset,
695                 &subtable->sub.gsub.chain_context2.ChainSubClassSet));
696 #endif
697         }
698       else if (subtable->Format == 3)
699         {
700 #if 0
701           dump_coverage_list
702             (indent, "BackTrackGlyphCount",
703              subtable->sub.gsub.chain_context3.Backtrack,
704              subtable->sub.gsub.chain_context3.BacktrackGlyphCount);
705           dump_coverage_list
706             (indent, "InputGlyphCount",
707              subtable->sub.gsub.chain_context3.Input,
708              subtable->sub.gsub.chain_context3.InputGlyphCount);
709           dump_coverage_list
710             (indent, "LookaheaGlyphCount",
711              subtable->sub.gsub.chain_context3.LookAhead,
712              subtable->sub.gsub.chain_context3.LookaheadGlyphCount);
713           dump_subst_lookup_record_list
714             (indent,
715              subtable->sub.gsub.chain_context3.SubstLookupRecord,
716              subtable->sub.gsub.chain_context3.SubstCount);
717 #endif
718         }
719       break;
720     }
721   printf (")");
722 }
723
724
725 static void
726 dump_gpos_table (int indent, OTF_GPOS *gpos)
727 {
728   IPRINT ("(GPOS");
729   indent++;
730   IPRINT ("(Header");
731   indent++;
732   IPRINT ("(Version %d.%d)", gpos->Version.high, gpos->Version.low);
733   IPRINT ("(ScriptList #x%04X)", gpos->ScriptList.offset);
734   IPRINT ("(FeatureList #x%04X)", gpos->FeatureList.offset);
735   IPRINT ("(LookupList #x%04X))", gpos->LookupList.offset);
736   indent--;
737   dump_script_list (indent, &gpos->ScriptList);
738   dump_feature_list (indent, &gpos->FeatureList);
739   dump_lookup_list (indent, &gpos->LookupList, 0);
740   printf (")");
741 }
742
743 #if 0
744 static void
745 dump_base_table (OTF_BASE *base)
746 {
747 }
748
749 static void
750 dump_jstf_table (OTF_JSTF *jstf)
751 {
752 }
753 #endif
754
755 \f
756 /* GDEF */
757 static void
758 dump_gdef_header (int indent, OTF_GDEFHeader *header)
759 {
760   IPRINT ("(Header\n");
761   indent++;
762   IPRINT ("(Version %d.%d)",
763           header->Version.high, header->Version.low);
764   IPRINT ("(GlyphClassDef #x%04X)", header->GlyphClassDef);
765   IPRINT ("(AttachList #x%04X)", header->AttachList);
766   IPRINT ("(LigCaretList #x%04X)", header->LigCaretList);
767   IPRINT ("(MarkAttachClassDef #x%04X))",
768           header->MarkAttachClassDef);
769 }
770
771 static void
772 dump_attach_list (int indent, OTF_AttachList *list)
773 {
774 }
775
776 static void
777 dump_lig_caret_list (int indent, OTF_LigCaretList *list)
778 {
779   int i, j;
780
781   IPRINT ("(LigCaretList");
782   indent++;
783   dump_coverage (indent, NULL, &list->Coverage);
784   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
785   for (i = 0; i < list->LigGlyphCount; i++)
786     {
787       IPRINT ("(LigGlyph (%d) (offset #x%04X)",
788               i, list->LigGlyph[i].offset);
789       indent++;
790       IPRINT ("(CaretCount %d)", list->LigGlyph[i].CaretCount);
791       for (j = 0; j < list->LigGlyph[i].CaretCount; j++)
792         {
793           unsigned format = list->LigGlyph[i].CaretValue[j].CaretValueFormat;
794
795           IPRINT ("(Caret (%d) (CaretValueFormat %d)", j, format);
796           if (format == 1)
797             {
798               printf ("(Coordinate %d)",
799                       list->LigGlyph[i].CaretValue[j].f.f1.Coordinate);
800             }
801           else if (format == 2)
802             {
803               printf ("(CaretValuePoint %d)",
804                       list->LigGlyph[i].CaretValue[j].f.f2.CaretValuePoint);
805             }
806           else if (format == 3)
807             {
808               printf ("(Coodinate %d)",
809                       list->LigGlyph[i].CaretValue[j].f.f3.Coordinate);
810               indent++;
811               dump_device_table
812                 (indent, "DeviceTable", 
813                  &list->LigGlyph[i].CaretValue[j].f.f3.DeviceTable);
814               indent--;
815             }
816           printf (")");
817         }
818       printf (")");
819     }
820   printf (")");
821 }
822
823
824 static void
825 dump_gdef_table (int indent, OTF_GDEF *gdef)
826 {
827   IPRINT ("(GDEF");
828   indent++;
829   dump_gdef_header (indent, &gdef->header);
830   if (gdef->header.GlyphClassDef)
831     dump_class_def (indent, "GlyphClassDef", &gdef->glyph_class_def);
832   if (gdef->header.AttachList)
833     dump_attach_list (indent, &gdef->attach_list);
834   if (gdef->header.LigCaretList)
835     dump_lig_caret_list (indent, &gdef->lig_caret_list);
836   if (gdef->header.MarkAttachClassDef)
837     dump_class_def (indent, "MarkAttachClassDef",
838                     &gdef->mark_attach_class_def);
839   printf (")");
840 }
841
842 \f
843 /* cmap */
844 static void
845 dump_cmap_table (int indent, OTF_cmap *cmap)
846 {
847   int i;
848
849   IPRINT ("(cmap");
850   indent++;
851   IPRINT ("(version %d)", cmap->version);
852   IPRINT ("(numTables %d)", cmap->numTables);
853   for (i = 0; i < cmap->numTables; i++)
854     {
855       IPRINT ("(EncodingRecord (%d) (platformID %d) (encodingID %d)",
856               i,
857               cmap->EncodingRecord[i].platformID,
858               cmap->EncodingRecord[i].encodingID);
859       indent++;
860       IPRINT ("(Subtable (offset #x%04X) (format %d) (length #x%04X) (language %d)",
861               cmap->EncodingRecord[i].offset,
862               cmap->EncodingRecord[i].subtable.format,
863               cmap->EncodingRecord[i].subtable.length,
864               cmap->EncodingRecord[i].subtable.language);
865       indent++;
866       switch (cmap->EncodingRecord[i].subtable.format)
867         {
868         case 0:
869           {
870             int j, k;
871             unsigned char *array
872               = cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray;
873
874             IPRINT ("(glyphIdArray");
875             for (j = 0; j < 16; j++)
876               {
877                 IPRINT (" ");
878                 for (k = 0; k < 16; k++)
879                   printf (" %3d", array[j * 16 + k]);
880               }
881             printf (")");
882           }
883           break;
884
885         case 4:
886           {
887             OTF_EncodingSubtable4 *sub4
888               = cmap->EncodingRecord[i].subtable.f.f4;
889             int j;
890
891             IPRINT ("(segCountX2 %d) (searchRange %d)",
892                     sub4->segCountX2, sub4->searchRange);
893             IPRINT ("(entrySelector %d) (rangeShift %d)",
894                     sub4->entrySelector, sub4->rangeShift);
895             for (j = 0; j < sub4->segCountX2 / 2; j++)
896               {
897                 IPRINT ("(Segment (%d)", j);
898                 indent++;
899                 IPRINT ("(startCount #x%04X) (endCount #x%04X)",
900                         sub4->segments[j].startCount,
901                         sub4->segments[j].endCount);
902                 IPRINT ("(idDelta %d) (idRangeOffset #x%04X))",
903                         sub4->segments[j].idDelta,
904                         sub4->segments[j].idRangeOffset);
905                 indent--;
906               }
907             IPRINT ("(glyphIdArray");
908             for (j = 0; j < sub4->GlyphCount; j++)
909               {
910                 if ((j % 16) == 0)
911                   IPRINT (" ");
912                 printf (" %3d", sub4->glyphIdArray[j]);
913               }
914             printf (")");
915           }
916           break;
917         }
918
919       indent -= 2;
920       printf ("))");
921     }
922   printf (")");
923 }
924 \f
925
926 /* name */
927 static void
928 dump_name_table (int indent, OTF_name *name)
929 {
930   int i;
931
932   IPRINT ("(name");
933   indent++;
934   IPRINT ("(format %d)", name->format);
935   IPRINT ("(count %d)", name->count);
936   IPRINT ("(stringOffset %d)", name->stringOffset);
937   for (i = 0; i < name->count; i++)
938     {
939       OTF_NameRecord *rec = name->nameRecord + i; 
940
941       IPRINT ("(nameRecord (%d)", i);
942       indent++;
943       IPRINT ("(platformID %d) (encodingID %d) (languageID %d) (nameID %d)",
944               rec->platformID, rec->encodingID, rec->languageID, rec->nameID);
945       IPRINT ("(length %d) (offset #x%04X))", rec->length, rec->offset);
946       indent--;
947     }
948   for (i = 0; i <= OTF_max_nameID; i++)
949     if (name->name[i])
950       IPRINT ("(nameID %d \"%s\")", i, name->name[i]);
951
952   printf (")");
953 }
954
955 \f
956
957 static void
958 otf_dump (OTF *otf)
959 {
960   int i;
961
962   printf ("(OTF");
963   dump_offset_table (1, &otf->offset_table);
964   for (i = 0; i < otf->offset_table.numTables; i++)
965     dump_table_directory (1, otf->table_dirs + i, i);
966   dump_head_table (1, (OTF_head *) otf_get_table (otf, otf_tag ("head")));
967   dump_name_table (1, (OTF_name *) otf_get_table (otf, otf_tag ("name")));
968   dump_cmap_table (1, (OTF_cmap *) otf_get_table (otf, otf_tag ("cmap")));
969   dump_gdef_table (1, (OTF_GDEF *) otf_get_table (otf, otf_tag ("GDEF")));
970   dump_gsub_table (1, (OTF_GSUB *) otf_get_table (otf, otf_tag ("GSUB")));
971   dump_gpos_table (1, (OTF_GPOS *) otf_get_table (otf, otf_tag ("GPOS")));
972 #if 0
973   dump_base_table (1, (OTF_BASE *) otf_get_table (otf, otf_tag ("BASE")));
974   dump_jstf_table (1, (OTF_JSTF *) otf_get_table (otf, otf_tag ("JSTF")));
975 #endif
976   printf (")\n");
977 }
978
979
980 int
981 main (int argc, char **argv)
982 {
983   OTF *otf;
984
985   if (argc != 2)
986     {
987       fprintf (stderr, "Usage, dtfdump OTF-FILE");
988       exit (1);
989     }
990   
991   otf = otf_open (argv[1]);
992   otf_dump (otf);
993   otf_close (otf);
994   exit (0);
995 }