*** 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 (int indent, char *title, OTF_GlyphID *ids, unsigned count)
77 {
78   IPRINT ("(%s (count %d)", title, count);
79   while (count-- > 0)
80     {
81       printf (" #x%04X", *ids);
82       ids++;
83     }
84   printf (")");
85 }
86
87 static void
88 dump_coverage (int indent, char *title, OTF_Coverage *coverage)
89 {
90   int i;
91
92   IPRINT ("(%sCoverage (CoverageFormat %d)",
93           (title ? title : ""), coverage->CoverageFormat);
94   indent++;
95   if (coverage->CoverageFormat == 1)
96     {
97       dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray,
98                       coverage->Count);
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   if (class->offset)
227     {
228       indent++;
229       if (class->ClassFormat == 1)
230         {
231           IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph);
232           dump_glyph_ids (indent, "ClassValueArray",
233                           (OTF_GlyphID *) class->f.f1.ClassValueArray,
234                           class->f.f1.GlyphCount);
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 (" UnknownClassFormat");
252     }
253   printf (")");
254 }
255
256 static void
257 dump_device_table (int indent, char *title, OTF_DeviceTable *table)
258 {
259   int i;
260
261   if (! table->offset)
262     return;
263   IPRINT ("(%s (offset #x%04X)", title, table->offset);
264   indent++;
265   IPRINT ("(StartSize %d) (EndSize %d) (DeltaFormat %d)",
266           table->StartSize, table->EndSize, table->DeltaFormat);
267   IPRINT ("(DeltaValue");
268   for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
269     printf (" %d", table->DeltaValue[i]);
270   printf ("))");
271 }
272
273 \f
274
275 static void
276 dump_value_record (int indent, char *title, OTF_ValueRecord *rec)
277 {
278   IPRINT ("(%s %d %d %d %d", title,
279           rec->XPlacement, rec->YPlacement, rec->XAdvance, rec->YAdvance);
280   indent++;
281   if (rec->XPlaDevice.offset)
282     dump_device_table (indent, "XPlaDevice", &rec->XPlaDevice);
283   if (rec->YPlaDevice.offset)
284     dump_device_table (indent, "YPlaDevice", &rec->YPlaDevice);
285   if (rec->XAdvDevice.offset)
286     dump_device_table (indent, "XAdvDevice", &rec->XAdvDevice);
287   if (rec->YAdvDevice.offset)
288     dump_device_table (indent, "YAdvDevice", &rec->YAdvDevice);
289   printf (")");
290 }
291
292
293 static void
294 dump_sequence_list (int indent, OTF_Sequence *sequence, unsigned num)
295 {
296   int i;
297   IPRINT ("(SequenceCount %d)", num);
298
299   for (i = 0; i < num; i++)
300     {
301       IPRINT ("(Sequence (%d) (offset #x%04X)",
302               i, sequence[i].offset);
303       dump_glyph_ids (indent + 1, "Substitute", sequence[i].Substitute,
304                       sequence[i].GlyphCount);
305       printf (")");
306     }
307 }
308
309 static void
310 dump_alternate_set_list (int indent, OTF_AlternateSet *altset, unsigned num)
311 {
312   int i;
313
314   IPRINT ("(AlternateSetCount %d)", num);
315   for (i = 0; i < num; i++)
316     {
317       IPRINT ("(AlternateSet (%d) (offset #x%04X)",
318               i, altset[i].offset);
319       dump_glyph_ids (indent + 1, "Alternate", altset[i].Alternate,
320                       altset[i].GlyphCount);
321       printf (")");
322     }
323 }
324
325
326 static void
327 dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
328 {
329   int i, j;
330
331   IPRINT ("(LigSetCount %d)", num);
332   for (i = 0; i < num; i++)
333     {
334       IPRINT ("(LigatureSet (%d) (offset #x%04X) (count %d)",
335               i, ligset[i].offset, ligset[i].LigatureCount);
336       indent++;
337       for (j = 0; j < ligset[i].LigatureCount; j++)
338         {
339           IPRINT ("(Ligature (%d) (offset #x%04X)",
340                   j, ligset[i].Ligature[j].offset);
341           indent++;
342           IPRINT ("(LigGlyph #x%04X)",
343                   ligset[i].Ligature[j].LigGlyph);
344           dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component,
345                           ligset[i].Ligature[j].CompCount - 1);
346           printf (")");
347           indent--;
348         }
349       indent--;
350       printf (")");
351     }
352 }
353
354 static void
355 dump_class1_record_list (int indent,
356                          unsigned Class1Count, unsigned Class2Count,
357                          OTF_Class1Record *rec)
358 {
359   int i, j;
360
361   for (i = 0; i < Class1Count; i++)
362     {
363       IPRINT ("(Class1Record (%d)", i);
364       indent++;
365       for (j = 0; j < Class2Count; j++)
366         {
367           IPRINT ("(Class2Record (%d)", j);
368           indent++;
369           dump_value_record (indent, "Value1", &rec[i].Class2Record[j].Value1);
370           dump_value_record (indent, "Value2", &rec[i].Class2Record[j].Value2);
371           printf (")");
372           indent--;
373         }
374       printf (")");
375       indent--;
376     }
377 }
378
379 static void
380 dump_anchor (int indent, OTF_Anchor *anchor)
381 {
382   IPRINT ("(Anchor (offset #x%04X) (AnchorFormat %d)",
383           anchor->offset, anchor->AnchorFormat);
384   indent++;
385   IPRINT ("(XCoordinate %d) (YCoordinate %d)",
386           anchor->XCoordinate, anchor->YCoordinate);
387   if (anchor->AnchorFormat == 1)
388     ;
389   else if (anchor->AnchorFormat == 2)
390     IPRINT ("(AnchorPoint %d)", anchor->f.f1.AnchorPoint);
391   else
392     {
393       dump_device_table (indent, "XDeviceTable", &anchor->f.f2.XDeviceTable);
394       dump_device_table (indent, "YDeviceTable", &anchor->f.f2.YDeviceTable);
395     }
396   printf (")");
397 }
398
399 static void
400 dump_mark_array (int indent, OTF_MarkArray *array)
401 {
402   int i;
403
404   IPRINT ("(MarkArray (MarkCount %d)", array->MarkCount);
405   indent++;
406   for (i = 0; i < array->MarkCount; i++)
407     {
408       IPRINT ("(MarkRecord (%d) (Class %d)", i, array->MarkRecord[i].Class);
409       dump_anchor (indent + 1, &array->MarkRecord[i].MarkAnchor);
410       printf (")");
411     }
412   printf (")");
413 }
414
415 static void
416 dump_anchor_array (int indent, unsigned ClassCount, OTF_AnchorArray *array)
417 {
418   int i, j;
419
420   IPRINT ("(AnchorArray (Count %d)", array->Count);
421   indent++;
422   for (i = 0; i < array->Count; i++)
423     {
424       IPRINT ("(AnchorRecord (%d) ", i);
425       for (j = 0; j < ClassCount; j++)
426         dump_anchor (indent + 1, array->AnchorRecord[i].Anchor + j);
427       printf (")");
428     }
429   printf (")");
430 }
431
432
433 static void
434 dump_lookup_record_list (int indent, OTF_LookupRecord *rec, unsigned num)
435 {
436   int i;
437
438   IPRINT ("(LookupCount %d)", num);
439   for (i = 0; i < num; i++)
440     {
441       IPRINT ("(LookupRecord (%d)", i);
442       indent++;
443       IPRINT ("(SequenceIndex %d)", rec[i].SequenceIndex);
444       IPRINT ("(LookupListIndex %d))", rec[i].LookupListIndex);
445       indent--;
446     }
447 }
448
449
450 static void dump_lookup_subtable_gsub (int indent, int index, unsigned type,
451                                        OTF_LookupSubTableGSUB *subtable);
452 static void dump_lookup_subtable_gpos (int indent, int index, unsigned type,
453                                        OTF_LookupSubTableGPOS *subtable);
454
455
456 static void
457 dump_lookup_list (int indent, OTF_LookupList *list, int gsub)
458 {
459   int i, j;
460
461   IPRINT ("(LookupList (count %d)", list->LookupCount);
462   indent++;
463   for (i = 0; i < list->LookupCount; i++)
464     {
465       OTF_Lookup *lookup = list->Lookup + i;
466
467       IPRINT ("(Lookup (%d) (Offset #x%04X)",
468               i, lookup->offset);
469       printf (" (Type %d) (Flag #x%04X) (SubTableCount %d)",
470               lookup->LookupType, lookup->LookupFlag, lookup->SubTableCount);
471       if (gsub)
472         for (j = 0; j < lookup->SubTableCount; j++)
473           dump_lookup_subtable_gsub (indent + 1, j,
474                                      lookup->LookupType,
475                                      lookup->SubTable.gsub + j);
476       else
477         for (j = 0; j < lookup->SubTableCount; j++)
478           dump_lookup_subtable_gpos (indent + 1, j,
479                                      lookup->LookupType,
480                                      lookup->SubTable.gpos + j);
481
482       printf (")");
483     }
484   printf (")");
485 }
486
487 static void
488 dump_rule_list (int indent, OTF_Rule *rule, int count)
489 {
490   int i;
491
492   IPRINT ("(RuleCount %d)", count);
493   for (i = 0; i < count; i++)
494     {
495       IPRINT ("(Rule (%d)", i);
496       indent++;
497       IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
498       IPRINT ("(LookupCount %d)", rule[i].LookupCount);
499       dump_glyph_ids (indent, "Input", rule[i].Input, rule[i].GlyphCount - 1);
500       dump_lookup_record_list (indent, rule[i].LookupRecord,
501                                rule[i].LookupCount);
502       printf (")");
503       indent--;
504     }
505 }
506
507 static void
508 dump_rule_set_list (int indent, OTF_RuleSet *set, int count)
509 {
510   int i;
511
512   IPRINT ("(RuleSetCount %d)", count);
513   for (i = 0; i < count; i++)
514     {
515       IPRINT ("(RuleSet (%d)", i);
516       dump_rule_list (indent + 1, set[i].Rule, set[i].RuleCount);
517       printf (")");
518     }
519 }
520
521 static void
522 dump_class_rule_list (int indent, OTF_ClassRule *rule, int count)
523 {
524   int i, j;
525
526   IPRINT ("(ClassRuleCnt %d)", count);
527   for (i = 0; i < count; i++)
528     {
529       IPRINT ("(ClassRule (%d)", i);
530       indent++;
531       IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
532       IPRINT ("(LookupCount %d)", rule[i].LookupCount);
533       IPRINT ("(Class");
534       for (j = 0; j < rule[i].GlyphCount - 1; j++)
535         printf (" %d", rule[i].Class[j]);
536       printf (")");
537       dump_lookup_record_list (indent, rule[i].LookupRecord,
538                                rule[i].LookupCount);
539       printf (")");
540       indent--;
541     }
542 }
543
544 static void
545 dump_class_set_list (int indent, OTF_ClassSet *set, int count)
546 {
547   int i;
548
549   IPRINT ("(ClassSetCount %d)", count);
550   for (i = 0; i < count; i++)
551     if (set[i].offset)
552       {
553         IPRINT ("(ClassSet (%d)", i);
554         dump_class_rule_list (indent + 1, set[i].ClassRule,
555                               set[i].ClassRuleCnt);
556         printf (")");
557       }
558 }
559
560 static void
561 dump_chain_rule_list (int indent, OTF_ChainRule *rule, int count)
562 {
563   int i;
564
565   IPRINT ("(ChainRuleCount %d)", count);
566   for (i = 0; i < count; i++)
567     {
568       IPRINT ("(ChainRule (%d)", i);
569       dump_glyph_ids (indent + 1, "Backtrack",
570                       rule[i].Backtrack, rule[i].BacktrackGlyphCount);
571       dump_glyph_ids (indent + 1, "Input",
572                       rule[i].Input, rule[i].InputGlyphCount - 1);
573       dump_glyph_ids (indent + 1, "LookAhead",
574                       rule[i].LookAhead, rule[i].LookaheadGlyphCount);
575       dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
576                                rule[i].LookupCount);
577       printf (")");
578     }
579 }
580
581 static void
582 dump_chain_rule_set_list (int indent, OTF_ChainRuleSet *set, int count)
583 {
584   int i;
585
586   IPRINT ("(ChainRuleSetCount %d)", count);
587   for (i = 0; i < count; i++)
588     {
589       IPRINT ("(ChainRuleSet (%d)", i);
590       dump_chain_rule_list (indent + 1,
591                             set[i].ChainRule, set[i].ChainRuleCount);
592       printf (")");
593     }
594 }
595
596 static void
597 dump_chain_class_rule_list (int indent, OTF_ChainClassRule *rule, int count)
598 {
599   int i;
600
601   IPRINT ("(ChainClassRuleCount %d)", count);
602   for (i = 0; i < count; i++)
603     {
604       IPRINT ("(ChainClassRule (%d)", i);
605       dump_glyph_ids (indent + 1, "Backtrack",
606                       rule[i].Backtrack, rule[i].BacktrackGlyphCount);
607       dump_glyph_ids (indent + 1, "Input",
608                       rule[i].Input, rule[i].InputGlyphCount - 1);
609       dump_glyph_ids (indent + 1, "LookAhead",
610                       rule[i].LookAhead, rule[i].LookaheadGlyphCount);
611       dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
612                                rule[i].LookupCount);
613       printf (")");
614     }
615 }
616
617 static void
618 dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count)
619 {
620   int i;
621
622   IPRINT ("(ChainClassSetCount %d)", count);
623   for (i = 0; i < count; i++)
624     {
625       IPRINT ("(ChainClassSet (%d)", i);
626       dump_chain_class_rule_list (indent + 1,
627                                   set[i].ChainClassRule,
628                                   set[i].ChainClassRuleCnt);
629       printf (")");
630     }
631 }
632
633
634
635
636 \f
637 /* GSUB */
638
639 static void
640 dump_lookup_subtable_gsub (int indent, int index, unsigned type,
641                            OTF_LookupSubTableGSUB *subtable)
642 {
643   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
644   indent++;
645   switch (type)
646     {
647     case 1:
648       if (subtable->Format == 1)
649         {
650           dump_coverage (indent, NULL, &subtable->Coverage);
651           IPRINT ("(DeltaGlyhpID #x%04X)",
652                   subtable->u.single1.DeltaGlyphID);
653         }
654       else if (subtable->Format == 2)
655         {
656           dump_coverage (indent, NULL, &subtable->Coverage);
657           dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute,
658                           subtable->u.single2.GlyphCount);
659         }
660       else
661         printf (" invalid");
662       break;
663
664     case 2:
665       if (subtable->Format == 1)
666         {
667           dump_coverage (indent, NULL, &subtable->Coverage);
668           dump_sequence_list (indent,
669                               subtable->u.multiple1.Sequence,
670                               subtable->u.multiple1.SequenceCount);
671         }
672       else
673         printf (" invalid");
674       break;
675       
676     case 3:
677       if (subtable->Format == 1)
678         {
679           dump_coverage (indent, NULL, &subtable->Coverage);
680           dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet,
681                                    subtable->u.alternate1.AlternateSetCount);
682         }
683       else
684         printf (" invalid");
685       break;
686
687     case 4:
688       if (subtable->Format == 1)
689         {
690           dump_coverage (indent, NULL, &subtable->Coverage);
691           dump_ligature_set_list (indent,
692                                   subtable->u.ligature1.LigatureSet,
693                                   subtable->u.ligature1.LigSetCount);
694         }
695       else
696         printf (" invalid");
697       break;
698
699     case 5:
700       if (subtable->Format == 1)
701         {
702           dump_coverage (indent, NULL, &subtable->Coverage);
703           dump_rule_set_list (indent, subtable->u.context1.RuleSet,
704                               subtable->u.context1.RuleSetCount); 
705         }
706       else if (subtable->Format == 2)
707         {
708           dump_coverage (indent, NULL, &subtable->Coverage);
709           dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
710           dump_class_set_list (indent, subtable->u.context2.ClassSet,
711                                subtable->u.context2.ClassSetCnt);
712         }
713       else if (subtable->Format == 3)
714         {
715           dump_coverage_list (indent, "Coverage",
716                               subtable->u.context3.Coverage,
717                               subtable->u.context3.GlyphCount);
718           dump_lookup_record_list (indent,
719                                    subtable->u.context3.LookupRecord,
720                                    subtable->u.context3.LookupCount);
721         }
722       else
723         printf (" invalid");
724       break;
725
726     case 6:
727       if (subtable->Format == 1)
728         {
729           dump_coverage (indent, NULL, &subtable->Coverage);
730           dump_chain_rule_set_list
731             (indent,
732              subtable->u.chain_context1.ChainRuleSet,
733              subtable->u.chain_context1.ChainRuleSetCount);
734         }
735       else if (subtable->Format == 2)
736         {
737           dump_coverage (indent, NULL, &subtable->Coverage);
738           dump_class_def (indent, "BacktrackClassDef",
739                           &subtable->u.chain_context2.BacktrackClassDef);
740           dump_class_def (indent, "InputClassDef",
741                           &subtable->u.chain_context2.InputClassDef);
742           dump_class_def (indent, "LookaheadClassDef",
743                           &subtable->u.chain_context2.LookaheadClassDef);
744           dump_chain_class_set_list
745             (indent,
746              subtable->u.chain_context2.ChainClassSet,
747              subtable->u.chain_context2.ChainClassSetCnt);
748         }
749       else if (subtable->Format == 3)
750         {
751           dump_coverage_list
752             (indent, "BackTrackGlyphCount",
753              subtable->u.chain_context3.Backtrack,
754              subtable->u.chain_context3.BacktrackGlyphCount);
755           dump_coverage_list
756             (indent, "InputGlyphCount",
757              subtable->u.chain_context3.Input,
758              subtable->u.chain_context3.InputGlyphCount);
759           dump_coverage_list
760             (indent, "LookaheadGlyphCount",
761              subtable->u.chain_context3.LookAhead,
762              subtable->u.chain_context3.LookaheadGlyphCount);
763           dump_lookup_record_list
764             (indent,
765              subtable->u.chain_context3.LookupRecord,
766              subtable->u.chain_context3.LookupCount);
767         }
768       else
769         printf (" invalid");
770       break;
771
772     case 7:
773     case 8:
774       printf (" not-yet-substcount");
775       break;
776
777     default:
778       printf (" invalid");
779     }
780   printf (")");
781 }
782
783 static void
784 dump_gsub_table (int indent, OTF_GSUB *gsub)
785 {
786   IPRINT ("(GSUB");
787   indent++;
788   IPRINT ("(Header");
789   indent++;
790   IPRINT ("(Version %d.%d)", gsub->Version.high, gsub->Version.low);
791   IPRINT ("(ScriptList #x%04X)", gsub->ScriptList.offset);
792   IPRINT ("(FeatureList #x%04X)", gsub->FeatureList.offset);
793   IPRINT ("(LookupList #x%04X))", gsub->LookupList.offset);
794   indent--;
795   dump_script_list (indent, &gsub->ScriptList);
796   dump_feature_list (indent, &gsub->FeatureList);
797   dump_lookup_list (indent, &gsub->LookupList, 1);
798   printf (")");
799 }
800
801 \f
802 /* GPOS */
803
804 static void
805 dump_lookup_subtable_gpos (int indent, int index, unsigned type,
806                            OTF_LookupSubTableGPOS *subtable)
807 {
808   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
809   indent++;
810   switch (type)
811     {
812     case 1:
813       if (subtable->Format == 1)
814         {
815           dump_coverage (indent, NULL, &subtable->Coverage);
816           IPRINT ("(ValueFormat #x%04X)",
817                   subtable->u.single1.ValueFormat);
818           dump_value_record (indent, "Value", &subtable->u.single1.Value);
819         }
820       else if (subtable->Format == 2)
821         {
822           int i;
823
824           dump_coverage (indent, NULL, &subtable->Coverage);
825           IPRINT ("(ValueFormat #x%04X)",
826                   subtable->u.single2.ValueFormat);
827           IPRINT ("(ValueCount %d)",
828                   subtable->u.single2.ValueCount);
829           for (i = 0; i < subtable->u.single2.ValueCount; i++)
830             dump_value_record (indent, "Value", &subtable->u.single2.Value[i]);
831         }
832       else
833         printf (" invalid");
834       break;
835
836     case 2:
837       if (subtable->Format == 1)
838         {
839           printf (" not-yet-supported");
840         }
841       else if (subtable->Format == 2)
842         {
843           dump_coverage (indent, NULL, &subtable->Coverage);
844           IPRINT ("(ValueFormat1 #x%04X)",
845                   subtable->u.pair2.ValueFormat1);
846           IPRINT ("(ValueFormat2 #x%04X)",
847                   subtable->u.pair2.ValueFormat2);
848           dump_class_def (indent, "ClassDef1",
849                           &subtable->u.pair2.ClassDef1);
850           dump_class_def (indent, "ClassDef2",
851                           &subtable->u.pair2.ClassDef2);
852           IPRINT ("(Class1Count %d)",
853                   subtable->u.pair2.Class1Count);
854           IPRINT ("(Class2Count %d)",
855                   subtable->u.pair2.Class2Count);
856           dump_class1_record_list (indent,
857                                    subtable->u.pair2.Class1Count,
858                                    subtable->u.pair2.Class2Count,
859                                    subtable->u.pair2.Class1Record);
860         }
861       else
862         printf (" invalid");
863       break;
864       
865     case 3:
866       if (subtable->Format == 1)
867         {
868           printf (" not-yet-supported");
869         }
870       else
871         printf (" invalid");
872       break;
873
874     case 4:
875       if (subtable->Format == 1)
876         {
877           dump_coverage (indent, "Mark", &subtable->Coverage);
878           dump_coverage (indent, "Base",
879                          &subtable->u.mark_base1.BaseCoverage);
880           IPRINT ("(ClassCount %d)",
881                   subtable->u.mark_base1.ClassCount);
882           dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
883           dump_anchor_array (indent, subtable->u.mark_base1.ClassCount,
884                            &subtable->u.mark_base1.BaseArray);
885         }
886       break;
887
888     case 5:
889       if (subtable->Format == 1)
890         {
891           printf (" not-yet-supported");
892         }
893       else
894         printf (" invalid");
895       break;
896
897     case 6:
898       if (subtable->Format == 1)
899         {
900           dump_coverage (indent, "Mark1", &subtable->Coverage);
901           dump_coverage (indent, "Mark2",
902                          &subtable->u.mark_mark1.Mark2Coverage);
903           IPRINT ("(ClassCount %d)",
904                   subtable->u.mark_mark1.ClassCount);
905           dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
906           dump_anchor_array (indent, subtable->u.mark_mark1.ClassCount,
907                            &subtable->u.mark_mark1.Mark2Array);
908         }
909       else
910         printf (" invalid");
911       break;
912
913     case 7:
914       if (subtable->Format == 1)
915         {
916           dump_coverage (indent, NULL, &subtable->Coverage);
917           dump_rule_set_list (indent, subtable->u.context1.RuleSet,
918                               subtable->u.context1.RuleSetCount); 
919         }
920       else if (subtable->Format == 2)
921         {
922           dump_coverage (indent, NULL, &subtable->Coverage);
923           dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
924           dump_class_set_list (indent, subtable->u.context2.ClassSet,
925                                subtable->u.context2.ClassSetCnt);
926         }
927       else if (subtable->Format == 3)
928         {
929           dump_coverage_list (indent, "Coverage",
930                               subtable->u.context3.Coverage,
931                               subtable->u.context3.GlyphCount);
932           dump_lookup_record_list (indent,
933                                    subtable->u.context3.LookupRecord,
934                                    subtable->u.context3.LookupCount);
935         }
936       else
937         printf (" invalid");
938       break;
939
940     case 8:
941       if (subtable->Format == 1)
942         {
943           dump_coverage (indent, NULL, &subtable->Coverage);
944           dump_chain_rule_set_list
945             (indent,
946              subtable->u.chain_context1.ChainRuleSet,
947              subtable->u.chain_context1.ChainRuleSetCount);
948         }
949       else if (subtable->Format == 2)
950         {
951           dump_coverage (indent, NULL, &subtable->Coverage);
952           dump_class_def (indent, "BacktrackClassDef",
953                           &subtable->u.chain_context2.BacktrackClassDef);
954           dump_class_def (indent, "InputClassDef",
955                           &subtable->u.chain_context2.InputClassDef);
956           dump_class_def (indent, "LookaheadClassDef",
957                           &subtable->u.chain_context2.LookaheadClassDef);
958           dump_chain_class_set_list
959             (indent,
960              subtable->u.chain_context2.ChainClassSet,
961              subtable->u.chain_context2.ChainClassSetCnt);
962         }
963       else if (subtable->Format == 3)
964         {
965           dump_coverage_list
966             (indent, "BackTrackGlyphCount",
967              subtable->u.chain_context3.Backtrack,
968              subtable->u.chain_context3.BacktrackGlyphCount);
969           dump_coverage_list
970             (indent, "InputGlyphCount",
971              subtable->u.chain_context3.Input,
972              subtable->u.chain_context3.InputGlyphCount);
973           dump_coverage_list
974             (indent, "LookaheaGlyphCount",
975              subtable->u.chain_context3.LookAhead,
976              subtable->u.chain_context3.LookaheadGlyphCount);
977           dump_lookup_record_list
978             (indent,
979              subtable->u.chain_context3.LookupRecord,
980              subtable->u.chain_context3.LookupCount);
981         }
982       else
983         printf (" invalid");
984       break;
985     }
986   printf (")");
987 }
988
989
990 static void
991 dump_gpos_table (int indent, OTF_GPOS *gpos)
992 {
993   if (! gpos)
994     return;
995   IPRINT ("(GPOS");
996   indent++;
997   IPRINT ("(Header");
998   indent++;
999   IPRINT ("(Version %d.%d)", gpos->Version.high, gpos->Version.low);
1000   IPRINT ("(ScriptList #x%04X)", gpos->ScriptList.offset);
1001   IPRINT ("(FeatureList #x%04X)", gpos->FeatureList.offset);
1002   IPRINT ("(LookupList #x%04X))", gpos->LookupList.offset);
1003   indent--;
1004   dump_script_list (indent, &gpos->ScriptList);
1005   dump_feature_list (indent, &gpos->FeatureList);
1006   dump_lookup_list (indent, &gpos->LookupList, 0);
1007   printf (")");
1008 }
1009
1010 #if 0
1011 static void
1012 dump_base_table (OTF_BASE *base)
1013 {
1014 }
1015
1016 static void
1017 dump_jstf_table (OTF_JSTF *jstf)
1018 {
1019 }
1020 #endif
1021
1022 \f
1023 /* GDEF */
1024 static void
1025 dump_gdef_header (int indent, OTF_GDEFHeader *header)
1026 {
1027   IPRINT ("(Header");
1028   indent++;
1029   IPRINT ("(Version %d.%d)",
1030           header->Version.high, header->Version.low);
1031   IPRINT ("(GlyphClassDef #x%04X)", header->GlyphClassDef);
1032   IPRINT ("(AttachList #x%04X)", header->AttachList);
1033   IPRINT ("(LigCaretList #x%04X)", header->LigCaretList);
1034   IPRINT ("(MarkAttachClassDef #x%04X))",
1035           header->MarkAttachClassDef);
1036 }
1037
1038 static void
1039 dump_attach_list (int indent, OTF_AttachList *list)
1040 {
1041 }
1042
1043 static void
1044 dump_lig_caret_list (int indent, OTF_LigCaretList *list)
1045 {
1046   int i, j;
1047
1048   IPRINT ("(LigCaretList");
1049   indent++;
1050   dump_coverage (indent, NULL, &list->Coverage);
1051   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
1052   for (i = 0; i < list->LigGlyphCount; i++)
1053     {
1054       IPRINT ("(LigGlyph (%d) (offset #x%04X)",
1055               i, list->LigGlyph[i].offset);
1056       indent++;
1057       IPRINT ("(CaretCount %d)", list->LigGlyph[i].CaretCount);
1058       for (j = 0; j < list->LigGlyph[i].CaretCount; j++)
1059         {
1060           unsigned format = list->LigGlyph[i].CaretValue[j].CaretValueFormat;
1061
1062           IPRINT ("(Caret (%d) (CaretValueFormat %d)", j, format);
1063           if (format == 1)
1064             {
1065               printf ("(Coordinate %d)",
1066                       list->LigGlyph[i].CaretValue[j].f.f1.Coordinate);
1067             }
1068           else if (format == 2)
1069             {
1070               printf ("(CaretValuePoint %d)",
1071                       list->LigGlyph[i].CaretValue[j].f.f2.CaretValuePoint);
1072             }
1073           else if (format == 3)
1074             {
1075               printf ("(Coodinate %d)",
1076                       list->LigGlyph[i].CaretValue[j].f.f3.Coordinate);
1077               indent++;
1078               dump_device_table
1079                 (indent, "DeviceTable", 
1080                  &list->LigGlyph[i].CaretValue[j].f.f3.DeviceTable);
1081               indent--;
1082             }
1083           printf (")");
1084         }
1085       printf (")");
1086     }
1087   printf (")");
1088 }
1089
1090
1091 static void
1092 dump_gdef_table (int indent, OTF_GDEF *gdef)
1093 {
1094   if (! gdef)
1095     return;
1096   IPRINT ("(GDEF");
1097   indent++;
1098   dump_gdef_header (indent, &gdef->header);
1099   if (gdef->header.GlyphClassDef)
1100     dump_class_def (indent, "GlyphClassDef", &gdef->glyph_class_def);
1101   if (gdef->header.AttachList)
1102     dump_attach_list (indent, &gdef->attach_list);
1103   if (gdef->header.LigCaretList)
1104     dump_lig_caret_list (indent, &gdef->lig_caret_list);
1105   if (gdef->header.MarkAttachClassDef)
1106     dump_class_def (indent, "MarkAttachClassDef",
1107                     &gdef->mark_attach_class_def);
1108   printf (")");
1109 }
1110
1111 \f
1112 /* cmap */
1113 static void
1114 dump_cmap_table (int indent, OTF_cmap *cmap)
1115 {
1116   int i;
1117
1118   IPRINT ("(cmap");
1119   indent++;
1120   IPRINT ("(version %d)", cmap->version);
1121   IPRINT ("(numTables %d)", cmap->numTables);
1122   for (i = 0; i < cmap->numTables; i++)
1123     {
1124       IPRINT ("(EncodingRecord (%d) (platformID %d) (encodingID %d)",
1125               i,
1126               cmap->EncodingRecord[i].platformID,
1127               cmap->EncodingRecord[i].encodingID);
1128       indent++;
1129       IPRINT ("(Subtable (offset #x%04X) (format %d) (length #x%04X) (language %d)",
1130               cmap->EncodingRecord[i].offset,
1131               cmap->EncodingRecord[i].subtable.format,
1132               cmap->EncodingRecord[i].subtable.length,
1133               cmap->EncodingRecord[i].subtable.language);
1134       indent++;
1135       switch (cmap->EncodingRecord[i].subtable.format)
1136         {
1137         case 0:
1138           {
1139             int j, k;
1140             unsigned char *array
1141               = cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray;
1142
1143             IPRINT ("(glyphIdArray");
1144             for (j = 0; j < 16; j++)
1145               {
1146                 IPRINT (" ");
1147                 for (k = 0; k < 16; k++)
1148                   printf (" %3d", array[j * 16 + k]);
1149               }
1150             printf (")");
1151           }
1152           break;
1153
1154         case 4:
1155           {
1156             OTF_EncodingSubtable4 *sub4
1157               = cmap->EncodingRecord[i].subtable.f.f4;
1158             int j;
1159
1160             IPRINT ("(segCountX2 %d) (searchRange %d)",
1161                     sub4->segCountX2, sub4->searchRange);
1162             IPRINT ("(entrySelector %d) (rangeShift %d)",
1163                     sub4->entrySelector, sub4->rangeShift);
1164             for (j = 0; j < sub4->segCountX2 / 2; j++)
1165               {
1166                 IPRINT ("(Segment (%d)", j);
1167                 indent++;
1168                 IPRINT ("(startCount #x%04X) (endCount #x%04X)",
1169                         sub4->segments[j].startCount,
1170                         sub4->segments[j].endCount);
1171                 IPRINT ("(idDelta %d) (idRangeOffset #x%04X))",
1172                         sub4->segments[j].idDelta,
1173                         sub4->segments[j].idRangeOffset);
1174                 indent--;
1175               }
1176             IPRINT ("(glyphIdArray");
1177             for (j = 0; j < sub4->GlyphCount; j++)
1178               {
1179                 if ((j % 16) == 0)
1180                   IPRINT (" ");
1181                 printf (" %3d", sub4->glyphIdArray[j]);
1182               }
1183             printf (")");
1184           }
1185           break;
1186
1187         case 6:
1188           {
1189             OTF_EncodingSubtable6 *sub6
1190               = cmap->EncodingRecord[i].subtable.f.f6;
1191             int j;
1192
1193             IPRINT ("(firstCode %d) (entryCount %d)",
1194                     sub6->firstCode, sub6->entryCount);
1195             IPRINT ("(glyphIdArray");
1196             for (j = 0; j < sub6->entryCount; j++)
1197               {
1198                 if ((j % 16) == 0)
1199                   IPRINT (" ");
1200                 printf (" %3d", sub6->glyphIdArray[j]);
1201               }
1202             printf (")");
1203           }
1204           break;
1205         }
1206
1207       indent -= 2;
1208       printf ("))");
1209     }
1210   printf (")");
1211 }
1212 \f
1213
1214 /* name */
1215 static void
1216 dump_name_table (int indent, OTF_name *name)
1217 {
1218   int i;
1219
1220   IPRINT ("(name");
1221   indent++;
1222   IPRINT ("(format %d)", name->format);
1223   IPRINT ("(count %d)", name->count);
1224   IPRINT ("(stringOffset %d)", name->stringOffset);
1225   for (i = 0; i < name->count; i++)
1226     {
1227       OTF_NameRecord *rec = name->nameRecord + i; 
1228
1229       IPRINT ("(nameRecord (%d)", i);
1230       indent++;
1231       IPRINT ("(platformID %d) (encodingID %d) (languageID %d) (nameID %d)",
1232               rec->platformID, rec->encodingID, rec->languageID, rec->nameID);
1233       IPRINT ("(length %d) (offset #x%04X))", rec->length, rec->offset);
1234       indent--;
1235     }
1236   for (i = 0; i <= OTF_max_nameID; i++)
1237     if (name->name[i])
1238       IPRINT ("(nameID %d \"%s\")", i, name->name[i]);
1239
1240   printf (")");
1241 }
1242
1243 \f
1244
1245 static void
1246 otf_dump (OTF *otf)
1247 {
1248   int i;
1249
1250   printf ("(OTF");
1251
1252   dump_offset_table (1, &otf->offset_table);
1253   for (i = 0; i < otf->offset_table.numTables; i++)
1254     dump_table_directory (1, otf->table_dirs + i, i);
1255
1256   if (otf->head)
1257     dump_head_table (1, otf->head);
1258   if (otf->name)
1259     dump_name_table (1, otf->name);
1260   if (otf->cmap)
1261     dump_cmap_table (1, otf->cmap);
1262   if (otf->gdef)
1263     dump_gdef_table (1, otf->gdef);
1264   if (otf->gsub)
1265     dump_gsub_table (1, otf->gsub);
1266   if (otf->gpos)
1267     dump_gpos_table (1, otf->gpos);
1268 #if 0
1269   if (otf->base)
1270     dump_base_table (1, otf->base);
1271   if (otf->jstf)
1272     dump_jstf_table (1, otf->jstf);
1273 #endif
1274   printf (")\n");
1275 }
1276
1277
1278 int
1279 main (int argc, char **argv)
1280 {
1281   OTF *otf;
1282
1283   if (argc != 2)
1284     {
1285       fprintf (stderr, "Usage, dtfdump OTF-FILE");
1286       exit (1);
1287     }
1288   
1289   otf = OTF_open (argv[1]);
1290   if (! otf)
1291     {
1292       OTF_perror ("otfdump");
1293       exit (1);
1294     }
1295   OTF_get_table (otf, "head");
1296   OTF_get_table (otf, "name");
1297   OTF_get_table (otf, "cmap");
1298   OTF_get_table (otf, "GDEF");
1299   OTF_get_table (otf, "GSUB");
1300   OTF_get_table (otf, "GPOS");
1301 #if 0
1302   OTF_get_table (otf, "BASE");
1303   OTF_get_table (otf, "JSTF");
1304 #endif
1305   otf_dump (otf);
1306   OTF_close (otf);
1307   exit (0);
1308 }