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