(lookup_gpos): Ignore mark glyphs while
[m17n/libotf.git] / example / otfdump.c
1 /* otfdump.c -- Dump OpenType Layout Tables.
2
3 Copyright (C) 2003, 2004
4   National Institute of Advanced Industrial Science and Technology (AIST)
5   Registration Number H15PRO167
6
7 This file is part of libotf.
8
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA.  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <libgen.h>
32
33 #include <otf.h>
34
35 char *indent_spaces[] =
36   { "", "  ", "    ", "      ", "        ", "          ", "            ",
37     "              ",  "                ",  "                  " };
38
39 /* Indented print.  */
40 #define IPRINT printf("\n%s", indent_spaces[indent]), printf
41
42 static void
43 dump_tag (OTF_Tag tag)
44 {
45   printf ("(tag \"");
46   putchar (tag >> 24);
47   putchar ((tag >> 16) & 0xFF);
48   putchar ((tag >> 8) & 0xFF);
49   putchar (tag & 0xFF);
50   printf ("\" #x%04X)", tag);
51 }
52
53 /* HEAD */
54
55 static void
56 dump_offset_table (int indent, OTF_OffsetTable *table)
57 {
58   IPRINT ("(OffsetTable");
59   indent++;
60   IPRINT ("(sfnt-version %d.%d)", 
61           table->sfnt_version.high, table->sfnt_version.low);
62   IPRINT ("(numTables %d)", table->numTables);
63   IPRINT ("(searchRange %d)", table->searchRange);
64   IPRINT ("(enterSelector %d)", table->enterSelector);
65   IPRINT ("(rangeShift %d))", table->rangeShift);  
66 }
67
68 static void
69 dump_table_directory (int indent, OTF_TableDirectory *table, int idx)
70 {
71   IPRINT ("(Table %d ", idx);
72   dump_tag (table->tag);
73   indent++;
74   IPRINT ("(checkSum %08X) (offset #x%08X) (length: #x%08X))",
75           table->checkSum, table->offset, table->length);
76 }
77
78 \f
79
80 /* head */
81 static void
82 dump_head_table (int indent, OTF_head *head)
83 {
84   IPRINT ("(head");
85   indent++;
86   IPRINT ("(TableVersionNumber %d.%d)",
87           head->TableVersionNumber.high, head->TableVersionNumber.low);
88   IPRINT ("(fontRevision %d.%d)",
89           head->fontRevision.high, head->fontRevision.low);
90   IPRINT ("(checkSumAdjustment #x%04X)", head->checkSumAdjustment);
91   IPRINT ("(magicNumber #x%04X)", head->magicNumber);
92   IPRINT ("(flags #x%04X)", head->flags);
93   IPRINT ("(unitsPerEm %d)", head->unitsPerEm);
94   printf (")");
95 }
96
97 \f
98 /* COMMON */
99
100 static void
101 dump_glyph_ids (int indent, char *title, OTF_GlyphID *ids, unsigned count)
102 {
103   IPRINT ("(%s (count %d)", title, count);
104   while (count-- > 0)
105     {
106       printf (" #x%04X", *ids);
107       ids++;
108     }
109   printf (")");
110 }
111
112 static int *
113 dump_coverage (int indent, char *title, OTF_Coverage *coverage)
114 {
115   int i;
116   int *char_list;
117
118   IPRINT ("(%sCoverage (CoverageFormat %d)",
119           (title ? title : ""), coverage->CoverageFormat);
120   indent++;
121   if (coverage->CoverageFormat == 1)
122     {
123       dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray,
124                       coverage->Count);
125       char_list = malloc (sizeof (int) * (coverage->Count + 1));
126       for (i = 0; i < coverage->Count; i++)
127         char_list[i] = coverage->table.GlyphArray[i];
128       char_list[i] = -1;
129     }
130   else
131     {
132       int n, c;
133
134       IPRINT ("(RangeCount %d)", coverage->Count);
135       indent++;
136       for (i = n = 0; i < coverage->Count; i++)
137         {
138           IPRINT ("(Range (%d) (Start #x%04X) (End #x%04X)", i,
139                   coverage->table.RangeRecord[i].Start,
140                   coverage->table.RangeRecord[i].End);
141           indent++;
142           IPRINT ("(StartCoverageIndex %d))",
143                   coverage->table.RangeRecord[i].StartCoverageIndex);
144           indent--;
145           n += (coverage->table.RangeRecord[i].End
146                 - coverage->table.RangeRecord[i].Start + 1);
147         }
148       char_list = malloc (sizeof (int) * (n + 1));
149       for (i = n = 0; i < coverage->Count; i++)
150         for (c = coverage->table.RangeRecord[i].Start;
151              c <= coverage->table.RangeRecord[i].End;
152              c++)
153           char_list[n++] = c;
154       char_list[n] = -1;
155     }
156   printf (")");
157   return char_list;
158 }
159
160 static void
161 dump_coverage_list (int indent, char *title,
162                     OTF_Coverage *coverage, unsigned num)
163 {
164   int i;
165
166   IPRINT ("(%s %d)", title, num);
167   for (i = 0; i < num; i++)
168     free (dump_coverage (indent, NULL, coverage + i));
169 }
170
171
172 static void
173 dump_language_system (int indent, int index, OTF_Tag tag, OTF_Offset offset,
174                       OTF_LangSys *langsys)
175 {
176   int i;
177
178   IPRINT ("(LangSys ");
179   if (index >= 0)
180     printf ("(%d) ", index);
181   if (tag)
182     dump_tag (tag);
183   else
184     printf ("DefaultLangSys");
185   printf (" (Offset #x%04X)", offset);
186   indent++;
187   IPRINT ("(LookupOrder #x%04X)", langsys->LookupOrder);
188   IPRINT ("(ReqFeatureIndex %d)", langsys->ReqFeatureIndex);
189   IPRINT ("(FeatureCount %d)", langsys->FeatureCount);
190   if (langsys->FeatureCount)
191     {
192       IPRINT ("(FeatureIndex");
193       for (i = 0; i < langsys->FeatureCount; i++)
194         printf (" %d", langsys->FeatureIndex[i]);
195       printf (")");
196     }
197   printf (")");
198 }
199
200 static void
201 dump_script_list (int indent, OTF_ScriptList *list)
202 {
203   int i, j;
204
205   IPRINT ("(ScriptList (count %d)", list->ScriptCount);
206   indent++;
207   for (i = 0; i < list->ScriptCount; i++)
208     {
209       OTF_Script *script = list->Script + i;
210
211       IPRINT ("(Script (%d) ", i);
212       dump_tag (list->Script[i].ScriptTag);
213       printf (" (Offset #x%04X)", list->Script[i].offset);
214       indent++;
215       IPRINT ("(DefaultLangSysOffset #x%04X)",
216               script->DefaultLangSysOffset);
217       if (script->DefaultLangSysOffset)
218         dump_language_system (indent, -1, 0,
219                               script->DefaultLangSysOffset,
220                               &script->DefaultLangSys);
221       IPRINT ("(LangSysCount %d)", script->LangSysCount);
222       for (j = 0; j < script->LangSysCount; j++)
223         dump_language_system (indent, j,
224                               script->LangSysRecord[j].LangSysTag,
225                               script->LangSysRecord[j].LangSys,
226                               script->LangSys + j);
227       printf (")");
228       indent--;
229     }
230   printf (")");
231 }
232
233 static void
234 dump_feature_list (int indent, OTF_FeatureList *list)
235 {
236   int i, j;
237   
238   IPRINT ("(FeatureList (count %d)", list->FeatureCount);
239   indent++;
240   for (i = 0; i < list->FeatureCount; i++)
241     {
242       OTF_Feature *feature = list->Feature + i;
243
244       IPRINT ("(Feature (%d) ", i);
245       dump_tag (list->Feature[i].FeatureTag);
246       printf (" (Offset #x%04X)", list->Feature[i].offset);
247       printf (" (LookupCount %d)", feature->LookupCount);
248       if (feature->LookupCount)
249         {
250           indent++;
251           IPRINT ("(LookupListIndex");
252           for (j = 0; j < feature->LookupCount; j++)
253             printf (" %d", feature->LookupListIndex[j]);
254           printf (")");
255           indent--;
256         }
257       printf (")");
258     }
259   printf (")");
260 }
261
262 static void
263 dump_class_def (int indent, char *title, OTF_ClassDef *class)
264 {
265   IPRINT ("(%s (offset #x%04X) (ClassFormat %d)",
266           (title ? title : "ClassDef"),
267           class->offset, class->ClassFormat);
268   if (class->offset)
269     {
270       indent++;
271       if (class->ClassFormat == 1)
272         {
273           IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph);
274           dump_glyph_ids (indent, "ClassValueArray",
275                           (OTF_GlyphID *) class->f.f1.ClassValueArray,
276                           class->f.f1.GlyphCount);
277         }
278       else if (class->ClassFormat == 2)
279         {
280           int i;
281
282           IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount);
283           IPRINT ("(ClassRangeRecord");
284           indent++;
285           for (i = 0; i < class->f.f2.ClassRangeCount; i++)
286             IPRINT ("((Start #x%04X) (End #x%04X) (class %d))",
287                     class->f.f2.ClassRangeRecord[i].Start,
288                     class->f.f2.ClassRangeRecord[i].End,
289                     class->f.f2.ClassRangeRecord[i].Class);
290           printf (")");
291         }
292       else
293         printf (" UnknownClassFormat");
294     }
295   printf (")");
296 }
297
298 static void
299 dump_device_table (int indent, char *title, OTF_DeviceTable *table)
300 {
301   int i;
302
303   if (! table->offset)
304     return;
305   IPRINT ("(%s (offset #x%04X)", title, table->offset);
306   indent++;
307   IPRINT ("(StartSize %d) (EndSize %d) (DeltaFormat %d)",
308           table->StartSize, table->EndSize, table->DeltaFormat);
309   IPRINT ("(DeltaValue");
310   for (i = 0; i < table->EndSize - table->StartSize + 1; i++)
311     printf (" %d", table->DeltaValue[i]);
312   printf ("))");
313 }
314
315 \f
316
317 static void
318 dump_value_record (int indent, char *title, OTF_ValueRecord *rec)
319 {
320   IPRINT ("(%s %d %d %d %d", title,
321           rec->XPlacement, rec->YPlacement, rec->XAdvance, rec->YAdvance);
322   indent++;
323   if (rec->XPlaDevice.offset)
324     dump_device_table (indent, "XPlaDevice", &rec->XPlaDevice);
325   if (rec->YPlaDevice.offset)
326     dump_device_table (indent, "YPlaDevice", &rec->YPlaDevice);
327   if (rec->XAdvDevice.offset)
328     dump_device_table (indent, "XAdvDevice", &rec->XAdvDevice);
329   if (rec->YAdvDevice.offset)
330     dump_device_table (indent, "YAdvDevice", &rec->YAdvDevice);
331   printf (")");
332 }
333
334
335 static void
336 dump_sequence_list (int indent, OTF_Sequence *sequence, unsigned num)
337 {
338   int i;
339   IPRINT ("(SequenceCount %d)", num);
340
341   for (i = 0; i < num; i++)
342     {
343       IPRINT ("(Sequence (%d) (offset #x%04X)",
344               i, sequence[i].offset);
345       dump_glyph_ids (indent + 1, "Substitute", sequence[i].Substitute,
346                       sequence[i].GlyphCount);
347       printf (")");
348     }
349 }
350
351 static void
352 dump_alternate_set_list (int indent, OTF_AlternateSet *altset, unsigned num)
353 {
354   int i;
355
356   IPRINT ("(AlternateSetCount %d)", num);
357   for (i = 0; i < num; i++)
358     {
359       IPRINT ("(AlternateSet (%d) (offset #x%04X)",
360               i, altset[i].offset);
361       dump_glyph_ids (indent + 1, "Alternate", altset[i].Alternate,
362                       altset[i].GlyphCount);
363       printf (")");
364     }
365 }
366
367
368 static void
369 dump_ligature_set_list (int indent, int *char_list,
370                         OTF_LigatureSet *ligset, unsigned num)
371 {
372   int i, j, k;
373
374   IPRINT ("(LigSetCount %d)", num);
375   for (i = 0; i < num; i++)
376     {
377       IPRINT ("(LigatureSet (%d) (offset #x%04X) (count %d)",
378               i, ligset[i].offset, ligset[i].LigatureCount);
379       indent++;
380       for (j = 0; j < ligset[i].LigatureCount; j++)
381         {
382           IPRINT ("(Ligature (%d) (offset #x%04X)",
383                   j, ligset[i].Ligature[j].offset);
384           indent++;
385           IPRINT ("(LigGlyph #x%04X)",
386                   ligset[i].Ligature[j].LigGlyph);
387           dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component,
388                           ligset[i].Ligature[j].CompCount - 1);
389           IPRINT ("(i.e. #x%04X", char_list[i]);
390           for (k = 0; k < ligset[i].Ligature[j].CompCount - 1; k++)
391             printf (" #x%04X", ligset[i].Ligature[j].Component[k]);
392           printf (" = #x%04X)", ligset[i].Ligature[j].LigGlyph);
393           printf (")");
394           indent--;
395         }
396       indent--;
397       printf (")");
398     }
399 }
400
401 static void
402 dump_pair_set_list (int indent, unsigned count, OTF_PairSet *set)
403 {
404   int i, j;
405
406   for (i = 0; i < count; i++)
407     {
408       IPRINT ("(PairSet (%d)", i);
409       indent++;
410       for (j = 0; j < set[i].PairValueCount; j++)
411         {
412           IPRINT ("(PairValueRecord (%d)", j);
413           indent++;
414           IPRINT ("(SecondGlyph #x%04X)",
415                   set[i].PairValueRecord[j].SecondGlyph);
416           dump_value_record (indent, "Value1",
417                              &set[i].PairValueRecord[j].Value1);
418           dump_value_record (indent, "Value2",
419                              &set[i].PairValueRecord[j].Value2);
420           printf (")");
421           indent--;
422         }
423       printf (")");
424       indent--;
425     }
426 }
427
428 static void
429 dump_class1_record_list (int indent,
430                          unsigned Class1Count, unsigned Class2Count,
431                          OTF_Class1Record *rec)
432 {
433   int i, j;
434
435   for (i = 0; i < Class1Count; i++)
436     {
437       IPRINT ("(Class1Record (%d)", i);
438       indent++;
439       for (j = 0; j < Class2Count; j++)
440         {
441           IPRINT ("(Class2Record (%d)", j);
442           indent++;
443           dump_value_record (indent, "Value1", &rec[i].Class2Record[j].Value1);
444           dump_value_record (indent, "Value2", &rec[i].Class2Record[j].Value2);
445           printf (")");
446           indent--;
447         }
448       printf (")");
449       indent--;
450     }
451 }
452
453 static void
454 dump_anchor (int indent, OTF_Anchor *anchor)
455 {
456   IPRINT ("(Anchor (offset #x%04X) (AnchorFormat %d)",
457           anchor->offset, anchor->AnchorFormat);
458   indent++;
459   IPRINT ("(XCoordinate %d) (YCoordinate %d)",
460           anchor->XCoordinate, anchor->YCoordinate);
461   if (anchor->AnchorFormat == 1)
462     ;
463   else if (anchor->AnchorFormat == 2)
464     IPRINT ("(AnchorPoint %d)", anchor->f.f1.AnchorPoint);
465   else
466     {
467       dump_device_table (indent, "XDeviceTable", &anchor->f.f2.XDeviceTable);
468       dump_device_table (indent, "YDeviceTable", &anchor->f.f2.YDeviceTable);
469     }
470   printf (")");
471 }
472
473 static void
474 dump_entry_exit_list (int indent, unsigned count, OTF_EntryExitRecord *rec)
475 {
476   int i;
477
478   for (i = 0; i < count; i++)
479     {
480       IPRINT ("(EntryExitRecord (%d)", i);
481       indent++;
482       dump_anchor (indent, &rec[i].EntryAnchor);
483       dump_anchor (indent, &rec[i].EntryAnchor);
484       printf (")");
485       indent--;
486     }
487 }
488
489 static void
490 dump_mark_array (int indent, OTF_MarkArray *array)
491 {
492   int i;
493
494   IPRINT ("(MarkArray (MarkCount %d)", array->MarkCount);
495   indent++;
496   for (i = 0; i < array->MarkCount; i++)
497     {
498       IPRINT ("(MarkRecord (%d) (Class %d)", i, array->MarkRecord[i].Class);
499       dump_anchor (indent + 1, &array->MarkRecord[i].MarkAnchor);
500       printf (")");
501     }
502   printf (")");
503 }
504
505 static void
506 dump_anchor_array (int indent, unsigned ClassCount, OTF_AnchorArray *array)
507 {
508   int i, j;
509
510   IPRINT ("(AnchorArray (Count %d)", array->Count);
511   indent++;
512   for (i = 0; i < array->Count; i++)
513     {
514       IPRINT ("(AnchorRecord (%d) ", i);
515       for (j = 0; j < ClassCount; j++)
516         dump_anchor (indent + 1, array->AnchorRecord[i].Anchor + j);
517       printf (")");
518     }
519   printf (")");
520 }
521
522
523 static void
524 dump_lookup_record_list (int indent, OTF_LookupRecord *rec, unsigned num)
525 {
526   int i;
527
528   IPRINT ("(LookupCount %d)", num);
529   for (i = 0; i < num; i++)
530     {
531       IPRINT ("(LookupRecord (%d)", i);
532       indent++;
533       IPRINT ("(SequenceIndex %d)", rec[i].SequenceIndex);
534       IPRINT ("(LookupListIndex %d))", rec[i].LookupListIndex);
535       indent--;
536     }
537 }
538
539
540 static void dump_lookup_subtable_gsub (int indent, int index, unsigned type,
541                                        OTF_LookupSubTableGSUB *subtable);
542 static void dump_lookup_subtable_gpos (int indent, int index, unsigned type,
543                                        OTF_LookupSubTableGPOS *subtable);
544
545
546 static void
547 dump_lookup_list (int indent, OTF_LookupList *list, int gsub)
548 {
549   int i, j;
550
551   IPRINT ("(LookupList (count %d)", list->LookupCount);
552   indent++;
553   for (i = 0; i < list->LookupCount; i++)
554     {
555       OTF_Lookup *lookup = list->Lookup + i;
556
557       IPRINT ("(Lookup (%d) (Offset #x%04X)",
558               i, lookup->offset);
559       printf (" (Type %d) (Flag #x%04X) (SubTableCount %d)",
560               lookup->LookupType, lookup->LookupFlag, lookup->SubTableCount);
561       if (gsub)
562         for (j = 0; j < lookup->SubTableCount; j++)
563           dump_lookup_subtable_gsub (indent + 1, j,
564                                      lookup->LookupType,
565                                      lookup->SubTable.gsub + j);
566       else
567         for (j = 0; j < lookup->SubTableCount; j++)
568           dump_lookup_subtable_gpos (indent + 1, j,
569                                      lookup->LookupType,
570                                      lookup->SubTable.gpos + j);
571
572       printf (")");
573     }
574   printf (")");
575 }
576
577 static void
578 dump_rule_list (int indent, OTF_Rule *rule, int count)
579 {
580   int i;
581
582   IPRINT ("(RuleCount %d)", count);
583   for (i = 0; i < count; i++)
584     {
585       IPRINT ("(Rule (%d)", i);
586       indent++;
587       IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
588       IPRINT ("(LookupCount %d)", rule[i].LookupCount);
589       dump_glyph_ids (indent, "Input", rule[i].Input, rule[i].GlyphCount - 1);
590       dump_lookup_record_list (indent, rule[i].LookupRecord,
591                                rule[i].LookupCount);
592       printf (")");
593       indent--;
594     }
595 }
596
597 static void
598 dump_rule_set_list (int indent, OTF_RuleSet *set, int count)
599 {
600   int i;
601
602   IPRINT ("(RuleSetCount %d)", count);
603   for (i = 0; i < count; i++)
604     {
605       IPRINT ("(RuleSet (%d)", i);
606       dump_rule_list (indent + 1, set[i].Rule, set[i].RuleCount);
607       printf (")");
608     }
609 }
610
611 static void
612 dump_class_rule_list (int indent, OTF_ClassRule *rule, int count)
613 {
614   int i, j;
615
616   IPRINT ("(ClassRuleCnt %d)", count);
617   for (i = 0; i < count; i++)
618     {
619       IPRINT ("(ClassRule (%d)", i);
620       indent++;
621       IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
622       IPRINT ("(LookupCount %d)", rule[i].LookupCount);
623       IPRINT ("(Class");
624       for (j = 0; j < rule[i].GlyphCount - 1; j++)
625         printf (" %d", rule[i].Class[j]);
626       printf (")");
627       dump_lookup_record_list (indent, rule[i].LookupRecord,
628                                rule[i].LookupCount);
629       printf (")");
630       indent--;
631     }
632 }
633
634 static void
635 dump_class_set_list (int indent, OTF_ClassSet *set, int count)
636 {
637   int i;
638
639   IPRINT ("(ClassSetCount %d)", count);
640   for (i = 0; i < count; i++)
641     if (set[i].offset)
642       {
643         IPRINT ("(ClassSet (%d)", i);
644         dump_class_rule_list (indent + 1, set[i].ClassRule,
645                               set[i].ClassRuleCnt);
646         printf (")");
647       }
648 }
649
650 static void
651 dump_chain_rule_list (int indent, OTF_ChainRule *rule, int count)
652 {
653   int i;
654
655   IPRINT ("(ChainRuleCount %d)", count);
656   for (i = 0; i < count; i++)
657     {
658       IPRINT ("(ChainRule (%d)", i);
659       dump_glyph_ids (indent + 1, "Backtrack",
660                       rule[i].Backtrack, rule[i].BacktrackGlyphCount);
661       dump_glyph_ids (indent + 1, "Input",
662                       rule[i].Input, rule[i].InputGlyphCount - 1);
663       dump_glyph_ids (indent + 1, "LookAhead",
664                       rule[i].LookAhead, rule[i].LookaheadGlyphCount);
665       dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
666                                rule[i].LookupCount);
667       printf (")");
668     }
669 }
670
671 static void
672 dump_chain_rule_set_list (int indent, OTF_ChainRuleSet *set, int count)
673 {
674   int i;
675
676   IPRINT ("(ChainRuleSetCount %d)", count);
677   for (i = 0; i < count; i++)
678     {
679       IPRINT ("(ChainRuleSet (%d)", i);
680       dump_chain_rule_list (indent + 1,
681                             set[i].ChainRule, set[i].ChainRuleCount);
682       printf (")");
683     }
684 }
685
686 static void
687 dump_chain_class_rule_list (int indent, OTF_ChainClassRule *rule, int count)
688 {
689   int i;
690
691   IPRINT ("(ChainClassRuleCount %d)", count);
692   for (i = 0; i < count; i++)
693     {
694       IPRINT ("(ChainClassRule (%d)", i);
695       dump_glyph_ids (indent + 1, "Backtrack",
696                       rule[i].Backtrack, rule[i].BacktrackGlyphCount);
697       dump_glyph_ids (indent + 1, "Input",
698                       rule[i].Input, rule[i].InputGlyphCount - 1);
699       dump_glyph_ids (indent + 1, "LookAhead",
700                       rule[i].LookAhead, rule[i].LookaheadGlyphCount);
701       dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
702                                rule[i].LookupCount);
703       printf (")");
704     }
705 }
706
707 static void
708 dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count)
709 {
710   int i;
711
712   IPRINT ("(ChainClassSetCount %d)", count);
713   for (i = 0; i < count; i++)
714     {
715       IPRINT ("(ChainClassSet (%d)", i);
716       dump_chain_class_rule_list (indent + 1,
717                                   set[i].ChainClassRule,
718                                   set[i].ChainClassRuleCnt);
719       printf (")");
720     }
721 }
722
723
724
725
726 \f
727 /* GSUB */
728
729 static void
730 dump_lookup_subtable_gsub (int indent, int index, unsigned type,
731                            OTF_LookupSubTableGSUB *subtable)
732 {
733   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
734   indent++;
735   switch (type)
736     {
737     case 1:
738       if (subtable->Format == 1)
739         {
740           free (dump_coverage (indent, NULL, &subtable->Coverage));
741           IPRINT ("(DeltaGlyhpID #x%04X)",
742                   subtable->u.single1.DeltaGlyphID);
743         }
744       else if (subtable->Format == 2)
745         {
746           free (dump_coverage (indent, NULL, &subtable->Coverage));
747           dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute,
748                           subtable->u.single2.GlyphCount);
749         }
750       else
751         printf (" invalid");
752       break;
753
754     case 2:
755       if (subtable->Format == 1)
756         {
757           free (dump_coverage (indent, NULL, &subtable->Coverage));
758           dump_sequence_list (indent,
759                               subtable->u.multiple1.Sequence,
760                               subtable->u.multiple1.SequenceCount);
761         }
762       else
763         printf (" invalid");
764       break;
765       
766     case 3:
767       if (subtable->Format == 1)
768         {
769           free (dump_coverage (indent, NULL, &subtable->Coverage));
770           dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet,
771                                    subtable->u.alternate1.AlternateSetCount);
772         }
773       else
774         printf (" invalid");
775       break;
776
777     case 4:
778       if (subtable->Format == 1)
779         {
780           int *char_list = dump_coverage (indent, NULL, &subtable->Coverage);
781           dump_ligature_set_list (indent, char_list,
782                                   subtable->u.ligature1.LigatureSet,
783                                   subtable->u.ligature1.LigSetCount);
784           free (char_list);
785         }
786       else
787         printf (" invalid");
788       break;
789
790     case 5:
791       if (subtable->Format == 1)
792         {
793           free (dump_coverage (indent, NULL, &subtable->Coverage));
794           dump_rule_set_list (indent, subtable->u.context1.RuleSet,
795                               subtable->u.context1.RuleSetCount); 
796         }
797       else if (subtable->Format == 2)
798         {
799           free (dump_coverage (indent, NULL, &subtable->Coverage));
800           dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
801           dump_class_set_list (indent, subtable->u.context2.ClassSet,
802                                subtable->u.context2.ClassSetCnt);
803         }
804       else if (subtable->Format == 3)
805         {
806           dump_coverage_list (indent, "Coverage",
807                               subtable->u.context3.Coverage,
808                               subtable->u.context3.GlyphCount);
809           dump_lookup_record_list (indent,
810                                    subtable->u.context3.LookupRecord,
811                                    subtable->u.context3.LookupCount);
812         }
813       else
814         printf (" invalid");
815       break;
816
817     case 6:
818       if (subtable->Format == 1)
819         {
820           free (dump_coverage (indent, NULL, &subtable->Coverage));
821           dump_chain_rule_set_list
822             (indent,
823              subtable->u.chain_context1.ChainRuleSet,
824              subtable->u.chain_context1.ChainRuleSetCount);
825         }
826       else if (subtable->Format == 2)
827         {
828           free (dump_coverage (indent, NULL, &subtable->Coverage));
829           dump_class_def (indent, "BacktrackClassDef",
830                           &subtable->u.chain_context2.BacktrackClassDef);
831           dump_class_def (indent, "InputClassDef",
832                           &subtable->u.chain_context2.InputClassDef);
833           dump_class_def (indent, "LookaheadClassDef",
834                           &subtable->u.chain_context2.LookaheadClassDef);
835           dump_chain_class_set_list
836             (indent,
837              subtable->u.chain_context2.ChainClassSet,
838              subtable->u.chain_context2.ChainClassSetCnt);
839         }
840       else if (subtable->Format == 3)
841         {
842           dump_coverage_list
843             (indent, "BackTrackGlyphCount",
844              subtable->u.chain_context3.Backtrack,
845              subtable->u.chain_context3.BacktrackGlyphCount);
846           dump_coverage_list
847             (indent, "InputGlyphCount",
848              subtable->u.chain_context3.Input,
849              subtable->u.chain_context3.InputGlyphCount);
850           dump_coverage_list
851             (indent, "LookaheadGlyphCount",
852              subtable->u.chain_context3.LookAhead,
853              subtable->u.chain_context3.LookaheadGlyphCount);
854           dump_lookup_record_list
855             (indent,
856              subtable->u.chain_context3.LookupRecord,
857              subtable->u.chain_context3.LookupCount);
858         }
859       else
860         printf (" invalid");
861       break;
862
863     case 7:
864       IPRINT ("(ExtensionLookupType %d)",
865               subtable->u.extension1.ExtensionLookupType);
866       IPRINT ("(ExtensionOffset %d)",
867               subtable->u.extension1.ExtensionOffset);
868       dump_lookup_subtable_gsub (indent, index, 
869                                  subtable->u.extension1.ExtensionLookupType,
870                                  subtable->u.extension1.ExtensionSubtable);
871       break;
872
873     case 8:
874       printf (" not-yet-supported");
875       break;
876
877     default:
878       printf (" invalid");
879     }
880   printf (")");
881 }
882
883 static void
884 dump_gsub_table (int indent, OTF_GSUB *gsub)
885 {
886   IPRINT ("(GSUB");
887   indent++;
888   IPRINT ("(Header");
889   indent++;
890   IPRINT ("(Version %d.%d)", gsub->Version.high, gsub->Version.low);
891   IPRINT ("(ScriptList #x%04X)", gsub->ScriptList.offset);
892   IPRINT ("(FeatureList #x%04X)", gsub->FeatureList.offset);
893   IPRINT ("(LookupList #x%04X))", gsub->LookupList.offset);
894   indent--;
895   dump_script_list (indent, &gsub->ScriptList);
896   dump_feature_list (indent, &gsub->FeatureList);
897   dump_lookup_list (indent, &gsub->LookupList, 1);
898   printf (")");
899 }
900
901 \f
902 /* GPOS */
903
904 static void
905 dump_lookup_subtable_gpos (int indent, int index, unsigned type,
906                            OTF_LookupSubTableGPOS *subtable)
907 {
908   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
909   indent++;
910   switch (type)
911     {
912     case 1:
913       if (subtable->Format == 1)
914         {
915           free (dump_coverage (indent, NULL, &subtable->Coverage));
916           IPRINT ("(ValueFormat #x%04X)",
917                   subtable->u.single1.ValueFormat);
918           dump_value_record (indent, "Value", &subtable->u.single1.Value);
919         }
920       else if (subtable->Format == 2)
921         {
922           int i;
923
924           free (dump_coverage (indent, NULL, &subtable->Coverage));
925           IPRINT ("(ValueFormat #x%04X)",
926                   subtable->u.single2.ValueFormat);
927           IPRINT ("(ValueCount %d)",
928                   subtable->u.single2.ValueCount);
929           for (i = 0; i < subtable->u.single2.ValueCount; i++)
930             dump_value_record (indent, "Value", &subtable->u.single2.Value[i]);
931         }
932       else
933         printf (" invalid");
934       break;
935
936     case 2:
937       if (subtable->Format == 1)
938         {
939           free (dump_coverage (indent, NULL, &subtable->Coverage));
940           IPRINT ("(ValueFormat1 #x%04X)",
941                   subtable->u.pair1.ValueFormat1);
942           IPRINT ("(ValueFormat2 #x%04X)",
943                   subtable->u.pair1.ValueFormat2);
944           dump_pair_set_list (indent, subtable->u.pair1.PairSetCount,
945                               subtable->u.pair1.PairSet);
946         }
947       else if (subtable->Format == 2)
948         {
949           free (dump_coverage (indent, NULL, &subtable->Coverage));
950           IPRINT ("(ValueFormat1 #x%04X)",
951                   subtable->u.pair2.ValueFormat1);
952           IPRINT ("(ValueFormat2 #x%04X)",
953                   subtable->u.pair2.ValueFormat2);
954           dump_class_def (indent, "ClassDef1",
955                           &subtable->u.pair2.ClassDef1);
956           dump_class_def (indent, "ClassDef2",
957                           &subtable->u.pair2.ClassDef2);
958           IPRINT ("(Class1Count %d)",
959                   subtable->u.pair2.Class1Count);
960           IPRINT ("(Class2Count %d)",
961                   subtable->u.pair2.Class2Count);
962           dump_class1_record_list (indent,
963                                    subtable->u.pair2.Class1Count,
964                                    subtable->u.pair2.Class2Count,
965                                    subtable->u.pair2.Class1Record);
966         }
967       else
968         printf (" invalid");
969       break;
970       
971     case 3:
972       if (subtable->Format == 1)
973         {
974           free (dump_coverage (indent, NULL, &subtable->Coverage));
975           dump_entry_exit_list (indent, subtable->u.cursive1.EntryExitCount,
976                                 subtable->u.cursive1.EntryExitRecord);
977         }
978       else
979         printf (" invalid");
980       break;
981
982     case 4:
983       if (subtable->Format == 1)
984         {
985           free (dump_coverage (indent, "Mark", &subtable->Coverage));
986           free (dump_coverage (indent, "Base",
987                                &subtable->u.mark_base1.BaseCoverage));
988           IPRINT ("(ClassCount %d)",
989                   subtable->u.mark_base1.ClassCount);
990           dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
991           dump_anchor_array (indent, subtable->u.mark_base1.ClassCount,
992                            &subtable->u.mark_base1.BaseArray);
993         }
994       break;
995
996     case 5:
997       if (subtable->Format == 1)
998         {
999           OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
1000           int i, j, k;
1001
1002           free (dump_coverage (indent, "Mark", &subtable->Coverage));
1003           free (dump_coverage (indent, "Ligature",
1004                                &mark_lig1->LigatureCoverage));
1005           IPRINT ("(ClassCount %d)", mark_lig1->ClassCount);
1006           dump_mark_array (indent, &mark_lig1->MarkArray);
1007           IPRINT ("(LigatureArray (%d)",
1008                   mark_lig1->LigatureArray.LigatureCount);
1009           indent++;
1010           for (i = 0; i < mark_lig1->LigatureArray.LigatureCount; i++)
1011             {
1012               OTF_LigatureAttach *attach
1013                 = mark_lig1->LigatureArray.LigatureAttach + i;
1014
1015               IPRINT ("(LigatureAttach (%d)", attach->ComponentCount);
1016               indent++;
1017               for (j = 0; j < attach->ComponentCount; j++)
1018                 {
1019                   OTF_ComponentRecord *rec = attach->ComponentRecord + j;
1020
1021                   IPRINT ("(LigatureAnchor (%d)", mark_lig1->ClassCount);
1022                   for (k = 0; k < mark_lig1->ClassCount; k++)
1023                     if (rec->LigatureAnchor[k].AnchorFormat)
1024                       dump_anchor (indent + 1, rec->LigatureAnchor + k);
1025                   printf (")");
1026                 }
1027               printf (")");
1028               indent--;
1029             }
1030           printf (")");
1031         }
1032       else
1033         printf (" invalid");
1034       break;
1035
1036     case 6:
1037       if (subtable->Format == 1)
1038         {
1039           free (dump_coverage (indent, "Mark1", &subtable->Coverage));
1040           free (dump_coverage (indent, "Mark2",
1041                                &subtable->u.mark_mark1.Mark2Coverage));
1042           IPRINT ("(ClassCount %d)",
1043                   subtable->u.mark_mark1.ClassCount);
1044           dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
1045           dump_anchor_array (indent, subtable->u.mark_mark1.ClassCount,
1046                            &subtable->u.mark_mark1.Mark2Array);
1047         }
1048       else
1049         printf (" invalid");
1050       break;
1051
1052     case 7:
1053       if (subtable->Format == 1)
1054         {
1055           free (dump_coverage (indent, NULL, &subtable->Coverage));
1056           dump_rule_set_list (indent, subtable->u.context1.RuleSet,
1057                               subtable->u.context1.RuleSetCount); 
1058         }
1059       else if (subtable->Format == 2)
1060         {
1061           free (dump_coverage (indent, NULL, &subtable->Coverage));
1062           dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
1063           dump_class_set_list (indent, subtable->u.context2.ClassSet,
1064                                subtable->u.context2.ClassSetCnt);
1065         }
1066       else if (subtable->Format == 3)
1067         {
1068           dump_coverage_list (indent, "Coverage",
1069                               subtable->u.context3.Coverage,
1070                               subtable->u.context3.GlyphCount);
1071           dump_lookup_record_list (indent,
1072                                    subtable->u.context3.LookupRecord,
1073                                    subtable->u.context3.LookupCount);
1074         }
1075       else
1076         printf (" invalid");
1077       break;
1078
1079     case 8:
1080       if (subtable->Format == 1)
1081         {
1082           free (dump_coverage (indent, NULL, &subtable->Coverage));
1083           dump_chain_rule_set_list
1084             (indent,
1085              subtable->u.chain_context1.ChainRuleSet,
1086              subtable->u.chain_context1.ChainRuleSetCount);
1087         }
1088       else if (subtable->Format == 2)
1089         {
1090           free (dump_coverage (indent, NULL, &subtable->Coverage));
1091           dump_class_def (indent, "BacktrackClassDef",
1092                           &subtable->u.chain_context2.BacktrackClassDef);
1093           dump_class_def (indent, "InputClassDef",
1094                           &subtable->u.chain_context2.InputClassDef);
1095           dump_class_def (indent, "LookaheadClassDef",
1096                           &subtable->u.chain_context2.LookaheadClassDef);
1097           dump_chain_class_set_list
1098             (indent,
1099              subtable->u.chain_context2.ChainClassSet,
1100              subtable->u.chain_context2.ChainClassSetCnt);
1101         }
1102       else if (subtable->Format == 3)
1103         {
1104           dump_coverage_list
1105             (indent, "BackTrackGlyphCount",
1106              subtable->u.chain_context3.Backtrack,
1107              subtable->u.chain_context3.BacktrackGlyphCount);
1108           dump_coverage_list
1109             (indent, "InputGlyphCount",
1110              subtable->u.chain_context3.Input,
1111              subtable->u.chain_context3.InputGlyphCount);
1112           dump_coverage_list
1113             (indent, "LookaheaGlyphCount",
1114              subtable->u.chain_context3.LookAhead,
1115              subtable->u.chain_context3.LookaheadGlyphCount);
1116           dump_lookup_record_list
1117             (indent,
1118              subtable->u.chain_context3.LookupRecord,
1119              subtable->u.chain_context3.LookupCount);
1120         }
1121       else
1122         printf (" invalid");
1123       break;
1124
1125     case 9:
1126       if (subtable->Format == 1)
1127         {
1128           IPRINT ("(ExtensionLookupType %d)",
1129                   subtable->u.extension1.ExtensionLookupType);
1130           IPRINT ("(ExtensionOffset %d)",
1131                   subtable->u.extension1.ExtensionOffset);
1132           dump_lookup_subtable_gpos
1133             (indent, index, 
1134              subtable->u.extension1.ExtensionLookupType,
1135              subtable->u.extension1.ExtensionSubtable);
1136         }
1137       else
1138         printf (" invalid");
1139     }
1140   printf (")");
1141 }
1142
1143
1144 static void
1145 dump_gpos_table (int indent, OTF_GPOS *gpos)
1146 {
1147   if (! gpos)
1148     return;
1149   IPRINT ("(GPOS");
1150   indent++;
1151   IPRINT ("(Header");
1152   indent++;
1153   IPRINT ("(Version %d.%d)", gpos->Version.high, gpos->Version.low);
1154   IPRINT ("(ScriptList #x%04X)", gpos->ScriptList.offset);
1155   IPRINT ("(FeatureList #x%04X)", gpos->FeatureList.offset);
1156   IPRINT ("(LookupList #x%04X))", gpos->LookupList.offset);
1157   indent--;
1158   dump_script_list (indent, &gpos->ScriptList);
1159   dump_feature_list (indent, &gpos->FeatureList);
1160   dump_lookup_list (indent, &gpos->LookupList, 0);
1161   printf (")");
1162 }
1163
1164 #if 0
1165 static void
1166 dump_base_table (OTF_BASE *base)
1167 {
1168 }
1169
1170 static void
1171 dump_jstf_table (OTF_JSTF *jstf)
1172 {
1173 }
1174 #endif
1175
1176 \f
1177 /* GDEF */
1178 static void
1179 dump_gdef_header (int indent, OTF_GDEFHeader *header)
1180 {
1181   IPRINT ("(Header");
1182   indent++;
1183   IPRINT ("(Version %d.%d)",
1184           header->Version.high, header->Version.low);
1185   IPRINT ("(GlyphClassDef #x%04X)", header->GlyphClassDef);
1186   IPRINT ("(AttachList #x%04X)", header->AttachList);
1187   IPRINT ("(LigCaretList #x%04X)", header->LigCaretList);
1188   IPRINT ("(MarkAttachClassDef #x%04X))",
1189           header->MarkAttachClassDef);
1190 }
1191
1192 static void
1193 dump_attach_list (int indent, OTF_AttachList *list)
1194 {
1195 }
1196
1197 static void
1198 dump_lig_caret_list (int indent, OTF_LigCaretList *list)
1199 {
1200   int i, j;
1201
1202   IPRINT ("(LigCaretList");
1203   indent++;
1204   free (dump_coverage (indent, NULL, &list->Coverage));
1205   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
1206   for (i = 0; i < list->LigGlyphCount; i++)
1207     {
1208       IPRINT ("(LigGlyph (%d) (offset #x%04X)",
1209               i, list->LigGlyph[i].offset);
1210       indent++;
1211       IPRINT ("(CaretCount %d)", list->LigGlyph[i].CaretCount);
1212       for (j = 0; j < list->LigGlyph[i].CaretCount; j++)
1213         {
1214           unsigned format = list->LigGlyph[i].CaretValue[j].CaretValueFormat;
1215
1216           IPRINT ("(Caret (%d) (CaretValueFormat %d)", j, format);
1217           if (format == 1)
1218             {
1219               printf ("(Coordinate %d)",
1220                       list->LigGlyph[i].CaretValue[j].f.f1.Coordinate);
1221             }
1222           else if (format == 2)
1223             {
1224               printf ("(CaretValuePoint %d)",
1225                       list->LigGlyph[i].CaretValue[j].f.f2.CaretValuePoint);
1226             }
1227           else if (format == 3)
1228             {
1229               printf ("(Coodinate %d)",
1230                       list->LigGlyph[i].CaretValue[j].f.f3.Coordinate);
1231               indent++;
1232               dump_device_table
1233                 (indent, "DeviceTable", 
1234                  &list->LigGlyph[i].CaretValue[j].f.f3.DeviceTable);
1235               indent--;
1236             }
1237           printf (")");
1238         }
1239       printf (")");
1240     }
1241   printf (")");
1242 }
1243
1244
1245 static void
1246 dump_gdef_table (int indent, OTF_GDEF *gdef)
1247 {
1248   if (! gdef)
1249     return;
1250   IPRINT ("(GDEF");
1251   indent++;
1252   dump_gdef_header (indent, &gdef->header);
1253   if (gdef->header.GlyphClassDef)
1254     dump_class_def (indent, "GlyphClassDef", &gdef->glyph_class_def);
1255   if (gdef->header.AttachList)
1256     dump_attach_list (indent, &gdef->attach_list);
1257   if (gdef->header.LigCaretList)
1258     dump_lig_caret_list (indent, &gdef->lig_caret_list);
1259   if (gdef->header.MarkAttachClassDef)
1260     dump_class_def (indent, "MarkAttachClassDef",
1261                     &gdef->mark_attach_class_def);
1262   printf (")");
1263 }
1264
1265 \f
1266 /* cmap */
1267 static void
1268 dump_cmap_table (int indent, OTF_cmap *cmap)
1269 {
1270   int i;
1271
1272   IPRINT ("(cmap");
1273   indent++;
1274   IPRINT ("(version %d)", cmap->version);
1275   IPRINT ("(numTables %d)", cmap->numTables);
1276   for (i = 0; i < cmap->numTables; i++)
1277     {
1278       IPRINT ("(EncodingRecord (%d) (platformID %d) (encodingID %d)",
1279               i,
1280               cmap->EncodingRecord[i].platformID,
1281               cmap->EncodingRecord[i].encodingID);
1282       indent++;
1283       IPRINT ("(Subtable (offset #x%04X) (format %d) (length #x%04X) (language %d)",
1284               cmap->EncodingRecord[i].offset,
1285               cmap->EncodingRecord[i].subtable.format,
1286               cmap->EncodingRecord[i].subtable.length,
1287               cmap->EncodingRecord[i].subtable.language);
1288       indent++;
1289       switch (cmap->EncodingRecord[i].subtable.format)
1290         {
1291         case 0:
1292           {
1293             int j, k;
1294             unsigned char *array
1295               = cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray;
1296
1297             IPRINT ("(glyphIdArray");
1298             for (j = 0; j < 16; j++)
1299               {
1300                 IPRINT (" ");
1301                 for (k = 0; k < 16; k++)
1302                   printf (" %3d", array[j * 16 + k]);
1303               }
1304             printf (")");
1305           }
1306           break;
1307
1308         case 4:
1309           {
1310             OTF_EncodingSubtable4 *sub4
1311               = cmap->EncodingRecord[i].subtable.f.f4;
1312             int j;
1313
1314             IPRINT ("(segCountX2 %d) (searchRange %d)",
1315                     sub4->segCountX2, sub4->searchRange);
1316             IPRINT ("(entrySelector %d) (rangeShift %d)",
1317                     sub4->entrySelector, sub4->rangeShift);
1318             for (j = 0; j < sub4->segCountX2 / 2; j++)
1319               {
1320                 IPRINT ("(Segment (%d)", j);
1321                 indent++;
1322                 IPRINT ("(startCount #x%04X) (endCount #x%04X)",
1323                         sub4->segments[j].startCount,
1324                         sub4->segments[j].endCount);
1325                 IPRINT ("(idDelta %d) (idRangeOffset #x%04X))",
1326                         sub4->segments[j].idDelta,
1327                         sub4->segments[j].idRangeOffset);
1328                 indent--;
1329               }
1330             IPRINT ("(glyphIdArray");
1331             for (j = 0; j < sub4->GlyphCount; j++)
1332               {
1333                 if ((j % 16) == 0)
1334                   IPRINT (" ");
1335                 printf (" %3d", sub4->glyphIdArray[j]);
1336               }
1337             printf (")");
1338           }
1339           break;
1340
1341         case 6:
1342           {
1343             OTF_EncodingSubtable6 *sub6
1344               = cmap->EncodingRecord[i].subtable.f.f6;
1345             int j;
1346
1347             IPRINT ("(firstCode %d) (entryCount %d)",
1348                     sub6->firstCode, sub6->entryCount);
1349             IPRINT ("(glyphIdArray");
1350             for (j = 0; j < sub6->entryCount; j++)
1351               {
1352                 if ((j % 16) == 0)
1353                   IPRINT (" ");
1354                 printf (" %3d", sub6->glyphIdArray[j]);
1355               }
1356             printf (")");
1357           }
1358           break;
1359
1360         case 12:
1361           {
1362             OTF_EncodingSubtable12 *sub12
1363               = cmap->EncodingRecord[i].subtable.f.f12;
1364             int j;
1365
1366             for (j = 0; j < sub12->nGroups; j++)
1367               {
1368                 IPRINT ("(Group (#x%X) (startChar #x%04X) (endChar #x%04X) (startGlyphID #x%X))",
1369                         j,
1370                         sub12->Groups[j].startCharCode,
1371                         sub12->Groups[j].endCharCode,
1372                         sub12->Groups[j].startGlyphID);
1373               }
1374           }
1375         }
1376
1377       indent -= 2;
1378       printf ("))");
1379     }
1380   printf (")");
1381 }
1382 \f
1383
1384 /* name */
1385 static void
1386 dump_name_table (int indent, OTF_name *name)
1387 {
1388   int i;
1389
1390   IPRINT ("(name");
1391   indent++;
1392   IPRINT ("(format %d)", name->format);
1393   IPRINT ("(count %d)", name->count);
1394   IPRINT ("(stringOffset %d)", name->stringOffset);
1395   for (i = 0; i < name->count; i++)
1396     {
1397       OTF_NameRecord *rec = name->nameRecord + i; 
1398
1399       IPRINT ("(nameRecord (%d)", i);
1400       indent++;
1401       IPRINT ("(platformID %d) (encodingID %d) (languageID %d) (nameID %d)",
1402               rec->platformID, rec->encodingID, rec->languageID, rec->nameID);
1403       IPRINT ("(length %d) (offset #x%04X))", rec->length, rec->offset);
1404       indent--;
1405     }
1406   for (i = 0; i <= OTF_max_nameID; i++)
1407     if (name->name[i])
1408       IPRINT ("(nameID %d \"%s\")", i, name->name[i]);
1409
1410   printf (")");
1411 }
1412
1413 \f
1414
1415 static void
1416 otf_dump (OTF *otf)
1417 {
1418   int i;
1419
1420   printf ("(OTF");
1421
1422   dump_offset_table (1, &otf->offset_table);
1423   for (i = 0; i < otf->offset_table.numTables; i++)
1424     dump_table_directory (1, otf->table_dirs + i, i);
1425
1426   if (otf->head)
1427     dump_head_table (1, otf->head);
1428   if (otf->name)
1429     dump_name_table (1, otf->name);
1430   if (otf->cmap)
1431     dump_cmap_table (1, otf->cmap);
1432   if (otf->gdef)
1433     dump_gdef_table (1, otf->gdef);
1434   if (otf->gsub)
1435     dump_gsub_table (1, otf->gsub);
1436   if (otf->gpos)
1437     dump_gpos_table (1, otf->gpos);
1438 #if 0
1439   if (otf->base)
1440     dump_base_table (1, otf->base);
1441   if (otf->jstf)
1442     dump_jstf_table (1, otf->jstf);
1443 #endif
1444   printf (")\n");
1445 }
1446
1447
1448 int
1449 main (int argc, char **argv)
1450 {
1451   OTF *otf;
1452
1453   if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
1454     {
1455       fprintf (stderr, "Usage: %s OTF-FILE\n", basename (argv[0]));
1456       exit (argc != 2);
1457     }
1458   
1459   otf = OTF_open (argv[1]);
1460   if (! otf)
1461     {
1462       OTF_perror ("otfdump");
1463       exit (1);
1464     }
1465   OTF_get_table (otf, "head");
1466   OTF_get_table (otf, "name");
1467   OTF_get_table (otf, "cmap");
1468   OTF_get_table (otf, "GDEF");
1469   OTF_get_table (otf, "GSUB");
1470   OTF_get_table (otf, "GPOS");
1471 #if 0
1472   OTF_get_table (otf, "BASE");
1473   OTF_get_table (otf, "JSTF");
1474 #endif
1475   otf_dump (otf);
1476   OTF_close (otf);
1477   exit (0);
1478 }