*** 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       IPRINT ("(ExtensionLookupType %d)",
774               subtable->u.extension1.ExtensionLookupType);
775       IPRINT ("(ExtensionOffset %d)",
776               subtable->u.extension1.ExtensionOffset);
777       dump_lookup_subtable_gsub (indent, index, 
778                                  subtable->u.extension1.ExtensionLookupType,
779                                  (subtable
780                                   + subtable->u.extension1.ExtensionOffset));
781       break;
782
783     case 8:
784       printf (" not-yet-substcount");
785       break;
786
787     default:
788       printf (" invalid");
789     }
790   printf (")");
791 }
792
793 static void
794 dump_gsub_table (int indent, OTF_GSUB *gsub)
795 {
796   IPRINT ("(GSUB");
797   indent++;
798   IPRINT ("(Header");
799   indent++;
800   IPRINT ("(Version %d.%d)", gsub->Version.high, gsub->Version.low);
801   IPRINT ("(ScriptList #x%04X)", gsub->ScriptList.offset);
802   IPRINT ("(FeatureList #x%04X)", gsub->FeatureList.offset);
803   IPRINT ("(LookupList #x%04X))", gsub->LookupList.offset);
804   indent--;
805   dump_script_list (indent, &gsub->ScriptList);
806   dump_feature_list (indent, &gsub->FeatureList);
807   dump_lookup_list (indent, &gsub->LookupList, 1);
808   printf (")");
809 }
810
811 \f
812 /* GPOS */
813
814 static void
815 dump_lookup_subtable_gpos (int indent, int index, unsigned type,
816                            OTF_LookupSubTableGPOS *subtable)
817 {
818   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
819   indent++;
820   switch (type)
821     {
822     case 1:
823       if (subtable->Format == 1)
824         {
825           dump_coverage (indent, NULL, &subtable->Coverage);
826           IPRINT ("(ValueFormat #x%04X)",
827                   subtable->u.single1.ValueFormat);
828           dump_value_record (indent, "Value", &subtable->u.single1.Value);
829         }
830       else if (subtable->Format == 2)
831         {
832           int i;
833
834           dump_coverage (indent, NULL, &subtable->Coverage);
835           IPRINT ("(ValueFormat #x%04X)",
836                   subtable->u.single2.ValueFormat);
837           IPRINT ("(ValueCount %d)",
838                   subtable->u.single2.ValueCount);
839           for (i = 0; i < subtable->u.single2.ValueCount; i++)
840             dump_value_record (indent, "Value", &subtable->u.single2.Value[i]);
841         }
842       else
843         printf (" invalid");
844       break;
845
846     case 2:
847       if (subtable->Format == 1)
848         {
849           printf (" not-yet-supported");
850         }
851       else if (subtable->Format == 2)
852         {
853           dump_coverage (indent, NULL, &subtable->Coverage);
854           IPRINT ("(ValueFormat1 #x%04X)",
855                   subtable->u.pair2.ValueFormat1);
856           IPRINT ("(ValueFormat2 #x%04X)",
857                   subtable->u.pair2.ValueFormat2);
858           dump_class_def (indent, "ClassDef1",
859                           &subtable->u.pair2.ClassDef1);
860           dump_class_def (indent, "ClassDef2",
861                           &subtable->u.pair2.ClassDef2);
862           IPRINT ("(Class1Count %d)",
863                   subtable->u.pair2.Class1Count);
864           IPRINT ("(Class2Count %d)",
865                   subtable->u.pair2.Class2Count);
866           dump_class1_record_list (indent,
867                                    subtable->u.pair2.Class1Count,
868                                    subtable->u.pair2.Class2Count,
869                                    subtable->u.pair2.Class1Record);
870         }
871       else
872         printf (" invalid");
873       break;
874       
875     case 3:
876       if (subtable->Format == 1)
877         {
878           printf (" not-yet-supported");
879         }
880       else
881         printf (" invalid");
882       break;
883
884     case 4:
885       if (subtable->Format == 1)
886         {
887           dump_coverage (indent, "Mark", &subtable->Coverage);
888           dump_coverage (indent, "Base",
889                          &subtable->u.mark_base1.BaseCoverage);
890           IPRINT ("(ClassCount %d)",
891                   subtable->u.mark_base1.ClassCount);
892           dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
893           dump_anchor_array (indent, subtable->u.mark_base1.ClassCount,
894                            &subtable->u.mark_base1.BaseArray);
895         }
896       break;
897
898     case 5:
899       if (subtable->Format == 1)
900         {
901           printf (" not-yet-supported");
902         }
903       else
904         printf (" invalid");
905       break;
906
907     case 6:
908       if (subtable->Format == 1)
909         {
910           dump_coverage (indent, "Mark1", &subtable->Coverage);
911           dump_coverage (indent, "Mark2",
912                          &subtable->u.mark_mark1.Mark2Coverage);
913           IPRINT ("(ClassCount %d)",
914                   subtable->u.mark_mark1.ClassCount);
915           dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
916           dump_anchor_array (indent, subtable->u.mark_mark1.ClassCount,
917                            &subtable->u.mark_mark1.Mark2Array);
918         }
919       else
920         printf (" invalid");
921       break;
922
923     case 7:
924       if (subtable->Format == 1)
925         {
926           dump_coverage (indent, NULL, &subtable->Coverage);
927           dump_rule_set_list (indent, subtable->u.context1.RuleSet,
928                               subtable->u.context1.RuleSetCount); 
929         }
930       else if (subtable->Format == 2)
931         {
932           dump_coverage (indent, NULL, &subtable->Coverage);
933           dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
934           dump_class_set_list (indent, subtable->u.context2.ClassSet,
935                                subtable->u.context2.ClassSetCnt);
936         }
937       else if (subtable->Format == 3)
938         {
939           dump_coverage_list (indent, "Coverage",
940                               subtable->u.context3.Coverage,
941                               subtable->u.context3.GlyphCount);
942           dump_lookup_record_list (indent,
943                                    subtable->u.context3.LookupRecord,
944                                    subtable->u.context3.LookupCount);
945         }
946       else
947         printf (" invalid");
948       break;
949
950     case 8:
951       if (subtable->Format == 1)
952         {
953           dump_coverage (indent, NULL, &subtable->Coverage);
954           dump_chain_rule_set_list
955             (indent,
956              subtable->u.chain_context1.ChainRuleSet,
957              subtable->u.chain_context1.ChainRuleSetCount);
958         }
959       else if (subtable->Format == 2)
960         {
961           dump_coverage (indent, NULL, &subtable->Coverage);
962           dump_class_def (indent, "BacktrackClassDef",
963                           &subtable->u.chain_context2.BacktrackClassDef);
964           dump_class_def (indent, "InputClassDef",
965                           &subtable->u.chain_context2.InputClassDef);
966           dump_class_def (indent, "LookaheadClassDef",
967                           &subtable->u.chain_context2.LookaheadClassDef);
968           dump_chain_class_set_list
969             (indent,
970              subtable->u.chain_context2.ChainClassSet,
971              subtable->u.chain_context2.ChainClassSetCnt);
972         }
973       else if (subtable->Format == 3)
974         {
975           dump_coverage_list
976             (indent, "BackTrackGlyphCount",
977              subtable->u.chain_context3.Backtrack,
978              subtable->u.chain_context3.BacktrackGlyphCount);
979           dump_coverage_list
980             (indent, "InputGlyphCount",
981              subtable->u.chain_context3.Input,
982              subtable->u.chain_context3.InputGlyphCount);
983           dump_coverage_list
984             (indent, "LookaheaGlyphCount",
985              subtable->u.chain_context3.LookAhead,
986              subtable->u.chain_context3.LookaheadGlyphCount);
987           dump_lookup_record_list
988             (indent,
989              subtable->u.chain_context3.LookupRecord,
990              subtable->u.chain_context3.LookupCount);
991         }
992       else
993         printf (" invalid");
994       break;
995     }
996   printf (")");
997 }
998
999
1000 static void
1001 dump_gpos_table (int indent, OTF_GPOS *gpos)
1002 {
1003   if (! gpos)
1004     return;
1005   IPRINT ("(GPOS");
1006   indent++;
1007   IPRINT ("(Header");
1008   indent++;
1009   IPRINT ("(Version %d.%d)", gpos->Version.high, gpos->Version.low);
1010   IPRINT ("(ScriptList #x%04X)", gpos->ScriptList.offset);
1011   IPRINT ("(FeatureList #x%04X)", gpos->FeatureList.offset);
1012   IPRINT ("(LookupList #x%04X))", gpos->LookupList.offset);
1013   indent--;
1014   dump_script_list (indent, &gpos->ScriptList);
1015   dump_feature_list (indent, &gpos->FeatureList);
1016   dump_lookup_list (indent, &gpos->LookupList, 0);
1017   printf (")");
1018 }
1019
1020 #if 0
1021 static void
1022 dump_base_table (OTF_BASE *base)
1023 {
1024 }
1025
1026 static void
1027 dump_jstf_table (OTF_JSTF *jstf)
1028 {
1029 }
1030 #endif
1031
1032 \f
1033 /* GDEF */
1034 static void
1035 dump_gdef_header (int indent, OTF_GDEFHeader *header)
1036 {
1037   IPRINT ("(Header");
1038   indent++;
1039   IPRINT ("(Version %d.%d)",
1040           header->Version.high, header->Version.low);
1041   IPRINT ("(GlyphClassDef #x%04X)", header->GlyphClassDef);
1042   IPRINT ("(AttachList #x%04X)", header->AttachList);
1043   IPRINT ("(LigCaretList #x%04X)", header->LigCaretList);
1044   IPRINT ("(MarkAttachClassDef #x%04X))",
1045           header->MarkAttachClassDef);
1046 }
1047
1048 static void
1049 dump_attach_list (int indent, OTF_AttachList *list)
1050 {
1051 }
1052
1053 static void
1054 dump_lig_caret_list (int indent, OTF_LigCaretList *list)
1055 {
1056   int i, j;
1057
1058   IPRINT ("(LigCaretList");
1059   indent++;
1060   dump_coverage (indent, NULL, &list->Coverage);
1061   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
1062   for (i = 0; i < list->LigGlyphCount; i++)
1063     {
1064       IPRINT ("(LigGlyph (%d) (offset #x%04X)",
1065               i, list->LigGlyph[i].offset);
1066       indent++;
1067       IPRINT ("(CaretCount %d)", list->LigGlyph[i].CaretCount);
1068       for (j = 0; j < list->LigGlyph[i].CaretCount; j++)
1069         {
1070           unsigned format = list->LigGlyph[i].CaretValue[j].CaretValueFormat;
1071
1072           IPRINT ("(Caret (%d) (CaretValueFormat %d)", j, format);
1073           if (format == 1)
1074             {
1075               printf ("(Coordinate %d)",
1076                       list->LigGlyph[i].CaretValue[j].f.f1.Coordinate);
1077             }
1078           else if (format == 2)
1079             {
1080               printf ("(CaretValuePoint %d)",
1081                       list->LigGlyph[i].CaretValue[j].f.f2.CaretValuePoint);
1082             }
1083           else if (format == 3)
1084             {
1085               printf ("(Coodinate %d)",
1086                       list->LigGlyph[i].CaretValue[j].f.f3.Coordinate);
1087               indent++;
1088               dump_device_table
1089                 (indent, "DeviceTable", 
1090                  &list->LigGlyph[i].CaretValue[j].f.f3.DeviceTable);
1091               indent--;
1092             }
1093           printf (")");
1094         }
1095       printf (")");
1096     }
1097   printf (")");
1098 }
1099
1100
1101 static void
1102 dump_gdef_table (int indent, OTF_GDEF *gdef)
1103 {
1104   if (! gdef)
1105     return;
1106   IPRINT ("(GDEF");
1107   indent++;
1108   dump_gdef_header (indent, &gdef->header);
1109   if (gdef->header.GlyphClassDef)
1110     dump_class_def (indent, "GlyphClassDef", &gdef->glyph_class_def);
1111   if (gdef->header.AttachList)
1112     dump_attach_list (indent, &gdef->attach_list);
1113   if (gdef->header.LigCaretList)
1114     dump_lig_caret_list (indent, &gdef->lig_caret_list);
1115   if (gdef->header.MarkAttachClassDef)
1116     dump_class_def (indent, "MarkAttachClassDef",
1117                     &gdef->mark_attach_class_def);
1118   printf (")");
1119 }
1120
1121 \f
1122 /* cmap */
1123 static void
1124 dump_cmap_table (int indent, OTF_cmap *cmap)
1125 {
1126   int i;
1127
1128   IPRINT ("(cmap");
1129   indent++;
1130   IPRINT ("(version %d)", cmap->version);
1131   IPRINT ("(numTables %d)", cmap->numTables);
1132   for (i = 0; i < cmap->numTables; i++)
1133     {
1134       IPRINT ("(EncodingRecord (%d) (platformID %d) (encodingID %d)",
1135               i,
1136               cmap->EncodingRecord[i].platformID,
1137               cmap->EncodingRecord[i].encodingID);
1138       indent++;
1139       IPRINT ("(Subtable (offset #x%04X) (format %d) (length #x%04X) (language %d)",
1140               cmap->EncodingRecord[i].offset,
1141               cmap->EncodingRecord[i].subtable.format,
1142               cmap->EncodingRecord[i].subtable.length,
1143               cmap->EncodingRecord[i].subtable.language);
1144       indent++;
1145       switch (cmap->EncodingRecord[i].subtable.format)
1146         {
1147         case 0:
1148           {
1149             int j, k;
1150             unsigned char *array
1151               = cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray;
1152
1153             IPRINT ("(glyphIdArray");
1154             for (j = 0; j < 16; j++)
1155               {
1156                 IPRINT (" ");
1157                 for (k = 0; k < 16; k++)
1158                   printf (" %3d", array[j * 16 + k]);
1159               }
1160             printf (")");
1161           }
1162           break;
1163
1164         case 4:
1165           {
1166             OTF_EncodingSubtable4 *sub4
1167               = cmap->EncodingRecord[i].subtable.f.f4;
1168             int j;
1169
1170             IPRINT ("(segCountX2 %d) (searchRange %d)",
1171                     sub4->segCountX2, sub4->searchRange);
1172             IPRINT ("(entrySelector %d) (rangeShift %d)",
1173                     sub4->entrySelector, sub4->rangeShift);
1174             for (j = 0; j < sub4->segCountX2 / 2; j++)
1175               {
1176                 IPRINT ("(Segment (%d)", j);
1177                 indent++;
1178                 IPRINT ("(startCount #x%04X) (endCount #x%04X)",
1179                         sub4->segments[j].startCount,
1180                         sub4->segments[j].endCount);
1181                 IPRINT ("(idDelta %d) (idRangeOffset #x%04X))",
1182                         sub4->segments[j].idDelta,
1183                         sub4->segments[j].idRangeOffset);
1184                 indent--;
1185               }
1186             IPRINT ("(glyphIdArray");
1187             for (j = 0; j < sub4->GlyphCount; j++)
1188               {
1189                 if ((j % 16) == 0)
1190                   IPRINT (" ");
1191                 printf (" %3d", sub4->glyphIdArray[j]);
1192               }
1193             printf (")");
1194           }
1195           break;
1196
1197         case 6:
1198           {
1199             OTF_EncodingSubtable6 *sub6
1200               = cmap->EncodingRecord[i].subtable.f.f6;
1201             int j;
1202
1203             IPRINT ("(firstCode %d) (entryCount %d)",
1204                     sub6->firstCode, sub6->entryCount);
1205             IPRINT ("(glyphIdArray");
1206             for (j = 0; j < sub6->entryCount; j++)
1207               {
1208                 if ((j % 16) == 0)
1209                   IPRINT (" ");
1210                 printf (" %3d", sub6->glyphIdArray[j]);
1211               }
1212             printf (")");
1213           }
1214           break;
1215         }
1216
1217       indent -= 2;
1218       printf ("))");
1219     }
1220   printf (")");
1221 }
1222 \f
1223
1224 /* name */
1225 static void
1226 dump_name_table (int indent, OTF_name *name)
1227 {
1228   int i;
1229
1230   IPRINT ("(name");
1231   indent++;
1232   IPRINT ("(format %d)", name->format);
1233   IPRINT ("(count %d)", name->count);
1234   IPRINT ("(stringOffset %d)", name->stringOffset);
1235   for (i = 0; i < name->count; i++)
1236     {
1237       OTF_NameRecord *rec = name->nameRecord + i; 
1238
1239       IPRINT ("(nameRecord (%d)", i);
1240       indent++;
1241       IPRINT ("(platformID %d) (encodingID %d) (languageID %d) (nameID %d)",
1242               rec->platformID, rec->encodingID, rec->languageID, rec->nameID);
1243       IPRINT ("(length %d) (offset #x%04X))", rec->length, rec->offset);
1244       indent--;
1245     }
1246   for (i = 0; i <= OTF_max_nameID; i++)
1247     if (name->name[i])
1248       IPRINT ("(nameID %d \"%s\")", i, name->name[i]);
1249
1250   printf (")");
1251 }
1252
1253 \f
1254
1255 static void
1256 otf_dump (OTF *otf)
1257 {
1258   int i;
1259
1260   printf ("(OTF");
1261
1262   dump_offset_table (1, &otf->offset_table);
1263   for (i = 0; i < otf->offset_table.numTables; i++)
1264     dump_table_directory (1, otf->table_dirs + i, i);
1265
1266   if (otf->head)
1267     dump_head_table (1, otf->head);
1268   if (otf->name)
1269     dump_name_table (1, otf->name);
1270   if (otf->cmap)
1271     dump_cmap_table (1, otf->cmap);
1272   if (otf->gdef)
1273     dump_gdef_table (1, otf->gdef);
1274   if (otf->gsub)
1275     dump_gsub_table (1, otf->gsub);
1276   if (otf->gpos)
1277     dump_gpos_table (1, otf->gpos);
1278 #if 0
1279   if (otf->base)
1280     dump_base_table (1, otf->base);
1281   if (otf->jstf)
1282     dump_jstf_table (1, otf->jstf);
1283 #endif
1284   printf (")\n");
1285 }
1286
1287
1288 int
1289 main (int argc, char **argv)
1290 {
1291   OTF *otf;
1292
1293   if (argc != 2)
1294     {
1295       fprintf (stderr, "Usage, dtfdump OTF-FILE");
1296       exit (1);
1297     }
1298   
1299   otf = OTF_open (argv[1]);
1300   if (! otf)
1301     {
1302       OTF_perror ("otfdump");
1303       exit (1);
1304     }
1305   OTF_get_table (otf, "head");
1306   OTF_get_table (otf, "name");
1307   OTF_get_table (otf, "cmap");
1308   OTF_get_table (otf, "GDEF");
1309   OTF_get_table (otf, "GSUB");
1310   OTF_get_table (otf, "GPOS");
1311 #if 0
1312   OTF_get_table (otf, "BASE");
1313   OTF_get_table (otf, "JSTF");
1314 #endif
1315   otf_dump (otf);
1316   OTF_close (otf);
1317   exit (0);
1318 }