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